-
Notifications
You must be signed in to change notification settings - Fork 102
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
eth: Compare on chain bytecode with local copy #1203
Conversation
Add a shell script that generates go code containing the runtime bytecode of the ETHSwap contract. Add a function to rpcclient to retrieve the on chain bytecode, and add a test that compares them.
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.
This is pretty perfect. Quick work of it.
Is it possible to have the github cli download the correct version of solc, run genruntime.sh and compare those files, so we would know if something changed in the hex bin? Maybe also a good idea for contract.go in that case, although that also requires a certain version of abigen I believe. Can be a different pr if others think it's a good idea.
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.
Even though we're not going to be using ethClient.getCodeAt
on the first iteration, it's a good method to have.
How do you guys control solc versions? I have 0.8.7 and this was a pain for me. Maybe we can allow different patch versions, at least until we are ready to lock it down?
|
||
package eth | ||
|
||
const ETHSwapRuntimeBin = "60806040526004361061004a5760003560e01c80637249fbb61461004f57806376467cbd14610071578063ae052147146100a7578063b31597ad146100ba578063eb84e7f2146100da575b600080fd5b34801561005b57600080fd5b5061006f61006a36600461057d565b61015c565b005b34801561007d57600080fd5b5061009161008c36600461057d565b61025e565b60405161009e9190610673565b60405180910390f35b61006f6100b53660046105d1565b610349565b3480156100c657600080fd5b5061006f6100d53660046105af565b61040e565b3480156100e657600080fd5b506101486100f536600461057d565b6000602081905290815260409020805460018201546002830154600384015460048501546005860154600687015460079097015495969495939492936001600160a01b0392831693919092169160ff1688565b60405161009e9897969594939291906106e3565b32331461016857600080fd5b80600160008281526020819052604090206007015460ff16600381111561019157610191610738565b1461019b57600080fd5b6000818152602081905260409020600401546001600160a01b031633146101c157600080fd5b600081815260208190526040902060010154428111156101e057600080fd5b60008381526020819052604080822060078101805460ff191660031790556006015490513391908381818185875af1925050503d806000811461023f576040519150601f19603f3d011682016040523d82523d6000602084013e610244565b606091505b509091505060018115151461025857600080fd5b50505050565b6102a36040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529060e082015290565b6000828152602081815260409182902082516101008101845281548152600182015492810192909252600281015492820192909252600380830154606083015260048301546001600160a01b03908116608084015260058401541660a0830152600683015460c0830152600783015491929160e084019160ff9091169081111561032f5761032f610738565b600381111561034057610340610738565b90525092915050565b826000341161035757600080fd5b6000811161036457600080fd5b32331461037057600080fd5b826000808281526020819052604090206007015460ff16600381111561039857610398610738565b146103a257600080fd5b6000848152602081905260409020438155600180820187905560028201869055600482018054336001600160a01b0319918216179091556005830180549091166001600160a01b0387161790553460068301556007909101805460ff1916828002179055505050505050565b32331461041a57600080fd5b8082600160008381526020819052604090206007015460ff16600381111561044457610444610738565b1461044e57600080fd5b6000828152602081905260409020600501546001600160a01b0316331461047457600080fd5b8160028260405160200161048a91815260200190565b60408051601f19818403018152908290526104a491610638565b602060405180830381855afa1580156104c1573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104e49190610596565b146104ee57600080fd5b60008381526020819052604080822060078101805460ff191660021790556006015490513391908381818185875af1925050503d806000811461054d576040519150601f19603f3d011682016040523d82523d6000602084013e610552565b606091505b509091505060018115151461056657600080fd5b505050600090815260208190526040902060030155565b60006020828403121561058f57600080fd5b5035919050565b6000602082840312156105a857600080fd5b5051919050565b600080604083850312156105c257600080fd5b50508035926020909101359150565b6000806000606084860312156105e657600080fd5b833592506020840135915060408401356001600160a01b038116811461060b57600080fd5b809150509250925092565b6004811061063457634e487b7160e01b600052602160045260246000fd5b9052565b6000825160005b81811015610659576020818601810151858301520161063f565b81811115610668576000828501525b509190910192915050565b60006101008201905082518252602083015160208301526040830151604083015260608301516060830152608083015160018060a01b0380821660808501528060a08601511660a0850152505060c083015160c083015260e08301516106dc60e0840182610616565b5092915050565b8881526020810188905260408101879052606081018690526001600160a01b038581166080830152841660a082015260c08101839052610100810161072b60e0830184610616565b9998505050505050505050565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220f5008532d651b31b24a7d133ff5dd0c4461e5f6339f32c9d551cb9cf81107e6b64736f6c63430008060033" |
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.
We can leave this, but it's really a job for //go:embed
.
e.g.
import _ "embed"
//go:embed contracts/ETHSwap.bin.dat
var ETHSwapRuntimeBin []byte
In the above I'm loading a []byte
instead of string
because I converted the output of solc into an actual binary, so you don't have to do DecodeString
, but it can load the hex text too. But even with a hex string, we won't actually need to generate this file.
To make an binary file, not hexadecimal text I did solc --bin-runtime --optimize ETHSwapV0.sol | xxd -r -p > ETHSwap.bin.dat
, but maybe solc can be coaxed into writing a bin file.
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.
That is definitely nicer, but the only reason I prefer the current technique is that it's consistent with what the abigen does (this is what generates contract.go
). There's a really long string in there as well.
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.
That's fine. Either we check in a ~2kb binary file to use go:embed, or we put the string right in the .go file with a shell script. No biggie to me either way.
The contract bindings are actual code though, not just variables, so I see that a little differently. It's fine this way, just a little unfortunate that it's a string when we really want bytes (any conceivable use for this would have to hex.DecodeString).
exit 1 | ||
fi | ||
|
||
solc --bin-runtime --optimize ${SOLIDITY_FILE} -o . |
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.
It's not clear to me what switches to use here. These are the output options I see:
--asm EVM assembly of the contracts.
--asm-json EVM assembly of the contracts in JSON format.
--opcodes Opcodes of the contracts.
--bin Binary of the contracts in hex.
--bin-runtime Binary of the runtime part of the contracts in hex.
--abi ABI specification of the contracts.
The output of --bin
is larger than --bin-runtime
. Which one is better to compare? I mean CodeAt
worked with bin-runtime obviously, but what's the difference between these two?
Also I'm wondering if the use of optimize (and specific compiler version) are going to make this extremely fragile.
Asking for no changes here... just a conversation.
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.
--bin
returns the creation bytecode. This is what has to be sent in a transaction when you initialize a new smart contract. --bin-runtime
returns the runtime bytecode, which is the code that ends up being stored on chain. This includes everything in the creation bytecode, except the constructor function and constructor arguments, as they will not need to be used again after initialization.
Why do you say that using a specific compiler version would make this fragile? I would think that not having a specific version would make it fragile. Optimize just applies some simplification rules to the unoptimized bytecode. This is a deterministic operation. If the same compiler version is used to optimize both what is deployed and what is used to compare, then we will get the same results.
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.
Why do you say that using a specific compiler version would make this fragile?
Ah I was thinking about optimize and how there are different levels, but you are right, the same considerations apply there as with compiler version. I was just referring to how identical contracts compiled with newer solc versions probably would get rejected, but I guess that's the point.
I haven't really thought much about managing the solidity version. I think the whole point of locking down the version was in order to be able to do these comparisons. It definitely was a pain to work with for me as well, since 0.8.6 is no longer the most recent version. Maybe a script that downloads the correct abigen and solc versions would be nice? This could be used in the github workflow that @JoeGruffins was talking about too. I think it's a good idea to do that too, since they might patch the released version which causes a diff. |
@chappjc I know you use arch, |
I was thinking a less system-wide approach, but that's probably fine for my purposes. Thanks |
K.I.S.S. But it can maybe be made better if one to were make the golang-cli script ,which would also download the correct solc to a temp location I suppose, and we could just use that to regenerate. |
Add a shell script that generates go code containing the runtime
bytecode of the ETHSwap contract. Add a function to rpcclient to
retrieve the on chain bytecode, and add a test that compares them.
Closes #1198