-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
feat(cast) add creation-code method [#8973] #9029
Conversation
} | ||
} | ||
|
||
/// Fetches the creation code of a contract from Etherscan and RPC. |
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 should document whether or not this includes constructor args appended to initcode
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.
@mds1 right, I should probably strip them to make the bytecode useful for local deployment. Maybe worth returning constructor args separately?
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'm reading up there's is no a single unified convention for encoding constructor args with different solidity versions. So I think I'll just add a comment that they are appended.
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.
What is the use case for this method? I think that impacts whether or not you want to strip the constructor args. If you do want to strip them you'll likely need to use blockscout or etherscan to fetch constructor args
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 want to get bytecode that I can use for deploying contracts locally, without compiling them myself. So prefer creation code without constructor args appended. But, optionally knowing what were the args values is also useful.
Eventually I want to add artifact
method that will combine creation bytecode with JSON ABI, for simply use with sol!
Alloy macro.
I'm thinking to add --without-args
and --only-args
flags. I think it's possible to know the size of appended args from the ABI. WDYT?
I've added
|
e1df312
to
fd6ee4e
Compare
what's missing here @zerosnacks ? |
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.
Resolved some nits I found
I think it makes sense to change creation_args
to constructor_args
as that is the common way to refer to it
@zerosnacks applied the review fixes. I've also added
Showing both raw and decoded values can be helpful for Etherscan contract verification that requires raw argument values. |
} | ||
|
||
fn format_arg(ty: &str, arg: Vec<u8>) -> Result<String> { | ||
let arg_type: DynSolType = ty.parse().expect("Invalid ABI type."); |
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.
Elegant solution w/ DynSolType 👍
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.
Thanks @pawurb! Tiny nits related to documentation, implementation looks good 👍
Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com>
Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com>
Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com>
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.
pedantic style nits, otherwise lgtm
if abi.constructor.is_none() { | ||
return Err(eyre!("No constructor found.")); | ||
} | ||
|
||
let constructor = abi.constructor.unwrap(); |
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.
nit: this can be abi.constructor.ok_or_else?
I think
let bytes = Bytes::from(arg.clone()); | ||
let decoded = arg_type.abi_decode(&arg)?; |
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 alloc is likely not required and the function can also accept &[u8]
.chunks(32) | ||
.enumerate() | ||
.map(|(i, arg)| { | ||
let arg = arg.to_vec(); |
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.
then we also dont need the to_vec here I believe
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.
lgtm, thank you. I left a comment re using newly introduced sh_println
macro
Motivation
As described in #8973, currently there's no simple way to obtain contract creation code without compiling them locally. It is needed to deploy contracts with
sol!
macro.If this is accepted I'll add
artifact
method generating file that can be used directly withsol!
macro.Solution
This PR adds
cast creation-code
method. It outputs the contract creation code.Example usage