Include deployed bytecode in abigen output (#2163)

* test

* sanity check
This commit is contained in:
frankie 2023-02-18 12:53:39 -08:00 committed by GitHub
parent 228f944726
commit 9733b16afc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 0 deletions

View File

@ -110,6 +110,9 @@ pub struct Context {
/// Bytecode extracted from the abi string input, if present. /// Bytecode extracted from the abi string input, if present.
contract_bytecode: Option<Bytes>, contract_bytecode: Option<Bytes>,
/// Deployed bytecode extracted from the abi string input, if present.
contract_deployed_bytecode: Option<Bytes>,
} }
impl Context { impl Context {
@ -193,6 +196,9 @@ impl Context {
// holds the bytecode parsed from the abi_str, if present // holds the bytecode parsed from the abi_str, if present
let mut contract_bytecode = None; let mut contract_bytecode = None;
// holds the deployed bytecode parsed from the abi_str, if present
let mut contract_deployed_bytecode = None;
let (abi, human_readable, abi_parser) = parse_abi(&abi_str).wrap_err_with(|| { let (abi, human_readable, abi_parser) = parse_abi(&abi_str).wrap_err_with(|| {
eyre::eyre!("error parsing abi for contract: {}", args.contract_name) eyre::eyre!("error parsing abi for contract: {}", args.contract_name)
})?; })?;
@ -220,6 +226,7 @@ impl Context {
// part of the json object in the contract binding // part of the json object in the contract binding
abi_str = serde_json::to_string(&obj.abi)?; abi_str = serde_json::to_string(&obj.abi)?;
contract_bytecode = obj.bytecode; contract_bytecode = obj.bytecode;
contract_deployed_bytecode = obj.deployed_bytecode;
InternalStructs::new(obj.abi) InternalStructs::new(obj.abi)
} }
JsonAbi::Array(abi) => InternalStructs::new(abi), JsonAbi::Array(abi) => InternalStructs::new(abi),
@ -291,6 +298,7 @@ impl Context {
contract_ident, contract_ident,
contract_name: args.contract_name, contract_name: args.contract_name,
contract_bytecode, contract_bytecode,
contract_deployed_bytecode,
method_aliases, method_aliases,
error_aliases: Default::default(), error_aliases: Default::default(),
event_derives, event_derives,
@ -313,6 +321,11 @@ impl Context {
format_ident!("{}_BYTECODE", self.contract_name.to_uppercase()) format_ident!("{}_BYTECODE", self.contract_name.to_uppercase())
} }
/// Name of the `Lazy` that stores the Deployed Bytecode.
pub(crate) fn inline_deployed_bytecode_ident(&self) -> Ident {
format_ident!("{}_DEPLOYED_BYTECODE", self.contract_name.to_uppercase())
}
/// Returns a reference to the internal ABI struct mapping table. /// Returns a reference to the internal ABI struct mapping table.
pub fn internal_structs(&self) -> &InternalStructs { pub fn internal_structs(&self) -> &InternalStructs {
&self.internal_structs &self.internal_structs

View File

@ -72,6 +72,18 @@ pub(crate) fn struct_declaration(cx: &Context) -> TokenStream {
} }
}); });
let deployed_bytecode = cx.contract_deployed_bytecode.as_ref().map(|bytecode| {
let bytecode = bytecode.iter().copied().map(Literal::u8_unsuffixed);
let bytecode_name = cx.inline_deployed_bytecode_ident();
quote! {
#[rustfmt::skip]
const __DEPLOYED_BYTECODE: &[u8] = &[ #( #bytecode ),* ];
#[doc = "The deployed bytecode of the contract."]
pub static #bytecode_name: #ethers_core::types::Bytes = #ethers_core::types::Bytes::from_static(__DEPLOYED_BYTECODE);
}
});
quote! { quote! {
// The `Lazy` ABI // The `Lazy` ABI
#abi #abi
@ -79,6 +91,9 @@ pub(crate) fn struct_declaration(cx: &Context) -> TokenStream {
// The static Bytecode, if present // The static Bytecode, if present
#bytecode #bytecode
// The static deployed Bytecode, if present
#deployed_bytecode
// Struct declaration // Struct declaration
pub struct #name<M>(#ethers_contract::Contract<M>); pub struct #name<M>(#ethers_contract::Contract<M>);

View File

@ -769,3 +769,14 @@ fn convert_uses_correct_abi() {
// is incorrectly using the `Foo` ABI internally). // is incorrectly using the `Foo` ABI internally).
bar.bar().call(); bar.bar().call();
} }
#[test]
fn generates_non_zero_bytecode() {
abigen!(Greeter, "ethers-contract/tests/solidity-contracts/greeter_with_struct.json");
//check that the bytecode is not empty
assert!(GREETER_BYTECODE.len() > 0);
assert!(GREETER_DEPLOYED_BYTECODE.len() > 0);
//sanity check that the bytecode is not the same
assert_ne!(GREETER_BYTECODE, GREETER_DEPLOYED_BYTECODE);
}