-
Notifications
You must be signed in to change notification settings - Fork 140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Constructor size check #57
Conversation
import hre from 'hardhat' | ||
|
||
/** | ||
* Contracts defined here are the ones for which cosntructor size check will be performed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Contracts defined here are the ones for which cosntructor size check will be performed. | |
* Contracts defined here are the ones for which constructor size check will be performed. |
console.log('Start constructor size check') | ||
|
||
// get constructor bytecode and check if it has expected length | ||
for (const [contractName, expectedLength] of Object.entries( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a danger here that a new contract will be added that should be checked, but we forget to add to the list above. Perhaps the list should be an exclusions list, or we somehow have another check that dynamically creates a list from the contracts that are used by the atomic token bridge creator.
const constructorBytecode = await _getConstructorBytecode(contractName) | ||
const constructorBytecodeLength = _lengthInBytes(constructorBytecode) | ||
|
||
if (constructorBytecodeLength !== expectedLength) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we know that all the contracts should have the constructor equal to 608060405234801561001057600080fd5b50615e7c806100206000396000f3fe
why dont we check for that value instead of length?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're not exactly the same between contracts, because constructor will push the length of the bytecode to the stack -> 61xxxx80
where xxxx is the length. This length will also change if some contract is modified (but not its constructor). We could calculate the length, insert it in the expected constructor code and compare to the actual one. But not sure if we gain much compared to this simple check
out of date |
Adds constructor size check to CI for certain contracts.
The reason why we perform constructor size check is because of atomic token bridge creator implementation. Due to contract size limits, we deploy child chain templates to the parent chain. When token bridge is being created, parent chain creator will fetch the runtime bytecode of the templates and send it to the child chain via retryable tickets. Child chain factory will then prepend the empty-constructor bytecode to the runtime code and use resulting bytecode for deployment. That's why we need to ensure that those impacted contracts don't have any logic in their constructors, as that logic can't be
executed when deploying to the child chain.
All impacted contracts have 32 bytes of constructor bytecode which look like this:
608060405234801561001057600080fd5b50615e7c806100206000396000f3fe
This constructor checks that there's no callvalue, copies the contract code to memory and returns it. The only place where constructor bytecode differs between contracts is in
61xxxx80
where xxxx is the length of the contract's bytecode.One exception is aeWETH, which has a constructor size of 348 bytes. This is because it inhertis from 'aeERC20' which has 'initializer' modifier in its constructor. This modifier will set the contract to the initialized state. When aeWETH is created on the child chain there will be no constructor code invoked as mentioned earlier, so we do the initialization of the logic contract explicitly in the child chain factory.