-
-
Notifications
You must be signed in to change notification settings - Fork 77
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
disasm: Detect init code #23
Conversation
Thanks for the quick fix. Not sure about the best solution, either modify the |
Great point, I forgot to adjust that. I originally wrote the code assuming input comes from getCode rather than piped in compiled contracts, so I need to update some assumptions. |
src.ts/disasm.ts
Outdated
@@ -298,6 +299,33 @@ export function disasm(bytecode: string): Program { | |||
} | |||
} | |||
|
|||
// Did we just hit the end of init code? | |||
// CODECOPY PUSH1 0x00 RETURN |
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.
Upon further investigation, this won't generalize.
For example, using immutable
adds a bunch of code between CODECOPY
and RETURN
. We'll need to add another mini state machine.
(via https://twitter.com/RenanRSouza35/status/1644308118375915523)
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.
Sample contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;
contract Foo {
uint public immutable a;
constructor(uint _a) {
a = _a;
}
}
[00] PUSH1 a0
[02] PUSH1 40
[04] MSTORE
[05] CALLVALUE
[06] DUP1
[07] ISZERO
[08] PUSH2 0010
[0b] JUMPI
[0c] PUSH1 00
[0e] DUP1
[0f] REVERT
[10] JUMPDEST
[11] POP
[12] PUSH1 40
[14] MLOAD
[15] PUSH2 0191
[18] CODESIZE
[19] SUB
[1a] DUP1
[1b] PUSH2 0191
[1e] DUP4
[1f] CODECOPY
[20] DUP2
[21] DUP2
[22] ADD
[23] PUSH1 40
[25] MSTORE
[26] DUP2
[27] ADD
[28] SWAP1
[29] PUSH2 0032
[2c] SWAP2
[2d] SWAP1
[2e] PUSH2 007b
[31] JUMP
[32] JUMPDEST
[33] DUP1
[34] PUSH1 80
[36] DUP2
[37] DUP2
[38] MSTORE
[39] POP
[3a] POP
[3b] POP
[3c] PUSH2 00a8
[3f] JUMP
[40] JUMPDEST
[41] PUSH1 00
[43] DUP1
[44] REVERT
[45] JUMPDEST
[46] PUSH1 00
[48] DUP2
[49] SWAP1
[4a] POP
[4b] SWAP2
[4c] SWAP1
[4d] POP
[4e] JUMP
[4f] JUMPDEST
[50] PUSH2 0058
[53] DUP2
[54] PUSH2 0045
[57] JUMP
[58] JUMPDEST
[59] DUP2
[5a] EQ
[5b] PUSH2 0063
[5e] JUMPI
[5f] PUSH1 00
[61] DUP1
[62] REVERT
[63] JUMPDEST
[64] POP
[65] JUMP
[66] JUMPDEST
[67] PUSH1 00
[69] DUP2
[6a] MLOAD
[6b] SWAP1
[6c] POP
[6d] PUSH2 0075
[70] DUP2
[71] PUSH2 004f
[74] JUMP
[75] JUMPDEST
[76] SWAP3
[77] SWAP2
[78] POP
[79] POP
[7a] JUMP
[7b] JUMPDEST
[7c] PUSH1 00
[7e] PUSH1 20
[80] DUP3
[81] DUP5
[82] SUB
[83] SLT
[84] ISZERO
[85] PUSH2 0091
[88] JUMPI
[89] PUSH2 0090
[8c] PUSH2 0040
[8f] JUMP
[90] JUMPDEST
[91] JUMPDEST
[92] PUSH1 00
[94] PUSH2 009f
[97] DUP5
[98] DUP3
[99] DUP6
[9a] ADD
[9b] PUSH2 0066
[9e] JUMP
[9f] JUMPDEST
[a0] SWAP2
[a1] POP
[a2] POP
[a3] SWAP3
[a4] SWAP2
[a5] POP
[a6] POP
[a7] JUMP
[a8] JUMPDEST
[a9] PUSH1 80
[ab] MLOAD
[ac] PUSH1 d1
[ae] PUSH2 00c0
[b1] PUSH1 00
[b3] CODECOPY
[b4] PUSH1 00
[b6] PUSH1 49
[b8] ADD
[b9] MSTORE
[ba] PUSH1 d1
[bc] PUSH1 00
[be] RETURN
[bf] INVALID
[c0] PUSH1 80
[c2] PUSH1 40
[c4] MSTORE
[c5] CALLVALUE
...
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.
Or we could parse the CODECOPY arguments to find where the runtime code begins
Immutable case still fails, but otherwise we have the |
Okay, this isn't perfect, since I'm not sure we could reliably detect non-static init code without dynamic analysis, but the examples we have so far are passing now! |
Test case code:
60806040526000805534801561001457600080fd5b50610178806100246000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806329e46078146100675780634e148ce11461009a57806368e5c066146100cd578063a87d942c146100e4575b600080fd5b34801561007357600080fd5b50610098600480360381019080803563ffffffff16906020019092919050505061010f565b005b3480156100a657600080fd5b506100cb600480360381019080803563ffffffff169060200190929190505050610122565b005b3480156100d957600080fd5b506100e2610135565b005b3480156100f057600080fd5b506100f9610143565b6040518082815260200191505060405180910390f35b8060020263ffffffff1660008190555050565b8060010263ffffffff1660008190555050565b600160005401600081905550565b600080549050905600a165627a7a72305820946aaa67044121e8026c839756e8dc0bcd00731a5c7239ace3524046974de6720029
Now returns selectors: "0x29e46078" "0x4e148ce1" "0x68e5c066" "0xa87d942c"
We also tack on the init code as a separate sub-program onto the program object.
TODO:
CC: #19 @Taryax