If you run:
solc path-to-somefile/somefile.sol (other options), the generated bytecode, instead of doing a reference like this:
__SafeMath.sol:SafeMath__
inserts this cropped output:
__src/contracts/SafeMath.sol:Safe__
Regards,
Mauro.
This is by design. It is covered in the "using the compiler" section, albeit not well explained.
Thanks @axic for answering.
@ChrisChinchilla do you want to take a brief look at the mentioned section and see if it explains it well? If you have questions after reading it, then perhaps it doesn't do a good job at.
@axic To be honest, I read the linked passage, and I recreated the OP's problem, i.e., running solc in a path above the solidity file produces the different output. But reading the text, I don't really understand what relates to the issue, or what I can do (should) about it. So I guess the docs need some work.
This has been mentioned by the zeppelin audit again. I think we should either completely remove this feature with 0.5.0 or turn it into something like:
myContract.bin:
0xab4455...3344___________L3__________6534455...
L3: src/contracts/SafeMath.sol:SafeMath
I'm escalating this issue above "documentation only".
We have preferred the "standard json" to be used, instead of the command line --link option. The "standard json" supports linking options as an input, but also outputs linking offsets properly.
To improve the current situation, we could change the placeholder, but shouldn't remove it, otherwise unlinked code with 0x0 library addresses could be deployed.
I suggest to change it to __<hash>__, where hash is a truncated hash of the fully qualified name (i.e. library name + function name).
And output a list of library functions used in a given contract through "standard json".
Note that this is just about library contracts, not functions. The fact that we do not know the libraries involved anymore is actually a big drawback.
Although I think that standard-json already has a list of unlinked references and thus we should not need the list you mention.
@axic, a hash is a good idea but unless you also add the mapping hash -> filename in the output, you should specify how paths are treatened, for e.g., is backslashes are converted to slashes, if paths are normalized, etc. when the hash is calculated.
We could internally only use the hash, and just append a mapping hash -> fully qualified library name for informative purposes.
I suggest to change it to __
__, where hash is a truncated hash of the fully qualified name (i.e. library name + function name).
In order to avoid confusing this with the previous version, I think we should make a small deviation.
Some possible deviations:
__00113412342134213423_ or __00113412342134213423___)__$00113412342134213423...__)Otherwise detector code could mistake it as a library name.
I believe the function name is not necessary because the mark is used to replace other contract's address.
I am not entirely sure I understand you.
I mean, above it is mentioned to build the hash based on the library name + function name. Currently it is used the filename + library/contract name, the hash should be based on the latter.
Why shouldn't it include the filename in the hash?
To clarify:
library name + function name: No
filename + library/contract name: Yes
@axic what about __0xab123__? 0x is not a valid library name and is usually used to prefix hex values.
I would not reduce the number of underscores to stay as compatible as possible and only break at the point of the identifier itself.
On the other hand, __0xab123__ could suggest that it is an address.
So perhaps $ is the best way. In that case, though, I would propose to use __$abc123...$__ so that the number of hex digits stays even.
We seem to have two options at hand:
a) _abc123..._ (single underscores)
b) __$abc123..$__ (two underscores plus dollar sign)
Unless current linkers are updated:
in case of a) linkers will not detect it as an unlinked section, will leave them unchanged and the resulting bytecode will still be unlinked resulting in a deployment error
in case of b) linkers could detect it as a regular unlinked library, but would raise an error perhaps with $abc123..$ not found.
I think b) may make more sense.
@pipermerriam @yann300 @iurimatias @maraoz @elopio can you please review this and leave an opinion which one we should take (by tomorrow)?
I don't really have an opinion about this API anymore because we've moved to standard-json for everything and no longer introspect the bytecode in this way.
@pipermerriam what do you mean? Is there some new doc?
https://solidity.readthedocs.io/en/develop/using-the-compiler.html#output-description
linkReferences: {
"libraryFile.sol": {
// Byte offsets into the bytecode. Linking replaces the 20 bytes located there.
"Library1": [
{ start: 0, length: 20 },
{ start: 200, length: 20 }
]
}
}
The standard-json compiler interface outputs this data which allows you to link the bytecode without introspecting it's values.
As far as I know, linkReferences are created based on the command line parameter that fills the m_libraries variable.
It is not a good solution because you have to know in advance the libraries you are using recursively, something that is resolved when the #imports are processed. Also on large projects you end with a very big command-line.
As far as I know, linkReferences are created based on the command line parameter that fills the m_libraries variable.
I am not sure what you mean, but linkReferences is filled for every unlinked instance.
@mxmauro I'm also not sure what you mean, but what you describe seems to be a different issue. If you are talking about --libraries - the option to that can also be a file name, so the comandline will not get longer.
Time ago I did a nodejs' wrapper to use the native compiler and remember I had to use linkReferences as you guys mention above. Didn't remember :)
It works but I have to ensure sources and urls have the full paths and also have to use --allow-paths to be able to specify absolute ones.