From 9733b16afc5c35be4409b72c172d8f7405f45d7c Mon Sep 17 00:00:00 2001 From: frankie <88221686+FrankieIsLost@users.noreply.github.com> Date: Sat, 18 Feb 2023 12:53:39 -0800 Subject: [PATCH] Include deployed bytecode in abigen output (#2163) * test * sanity check --- .../ethers-contract-abigen/src/contract.rs | 13 +++++++++++++ .../ethers-contract-abigen/src/contract/common.rs | 15 +++++++++++++++ ethers-contract/tests/it/abigen.rs | 11 +++++++++++ 3 files changed, 39 insertions(+) diff --git a/ethers-contract/ethers-contract-abigen/src/contract.rs b/ethers-contract/ethers-contract-abigen/src/contract.rs index 99e83c67..051fdb89 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract.rs @@ -110,6 +110,9 @@ pub struct Context { /// Bytecode extracted from the abi string input, if present. contract_bytecode: Option, + + /// Deployed bytecode extracted from the abi string input, if present. + contract_deployed_bytecode: Option, } impl Context { @@ -193,6 +196,9 @@ impl Context { // holds the bytecode parsed from the abi_str, if present 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(|| { 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 abi_str = serde_json::to_string(&obj.abi)?; contract_bytecode = obj.bytecode; + contract_deployed_bytecode = obj.deployed_bytecode; InternalStructs::new(obj.abi) } JsonAbi::Array(abi) => InternalStructs::new(abi), @@ -291,6 +298,7 @@ impl Context { contract_ident, contract_name: args.contract_name, contract_bytecode, + contract_deployed_bytecode, method_aliases, error_aliases: Default::default(), event_derives, @@ -313,6 +321,11 @@ impl Context { 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. pub fn internal_structs(&self) -> &InternalStructs { &self.internal_structs diff --git a/ethers-contract/ethers-contract-abigen/src/contract/common.rs b/ethers-contract/ethers-contract-abigen/src/contract/common.rs index 08178908..ed777d84 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract/common.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract/common.rs @@ -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! { // The `Lazy` ABI #abi @@ -79,6 +91,9 @@ pub(crate) fn struct_declaration(cx: &Context) -> TokenStream { // The static Bytecode, if present #bytecode + // The static deployed Bytecode, if present + #deployed_bytecode + // Struct declaration pub struct #name(#ethers_contract::Contract); diff --git a/ethers-contract/tests/it/abigen.rs b/ethers-contract/tests/it/abigen.rs index 7658a841..4c6093ee 100644 --- a/ethers-contract/tests/it/abigen.rs +++ b/ethers-contract/tests/it/abigen.rs @@ -769,3 +769,14 @@ fn convert_uses_correct_abi() { // is incorrectly using the `Foo` ABI internally). 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); + +}