From 1a8929c1a05a3e83b5cd2798e780ae582fbb0207 Mon Sep 17 00:00:00 2001 From: Nicholas Rodrigues Lordello Date: Mon, 30 Mar 2020 13:41:45 +0200 Subject: [PATCH 1/2] libraries type --- examples/linked.rs | 16 +++++--- generate/src/contract/deployment.rs | 61 ++++++++++++++++------------- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/examples/linked.rs b/examples/linked.rs index 83bc9e53..61f4826f 100644 --- a/examples/linked.rs +++ b/examples/linked.rs @@ -17,11 +17,17 @@ async fn run() { .deploy() .await .expect("library deployment failure"); - let instance = LinkedContract::builder(&web3, library.address(), 1337.into()) - .gas(4_712_388.into()) - .deploy() - .await - .expect("contract deployment failure"); + let instance = LinkedContract::builder( + &web3, + linked_contract::Libraries { + simple_library: library.address(), + }, + 1337.into(), + ) + .gas(4_712_388.into()) + .deploy() + .await + .expect("contract deployment failure"); println!( "The value is {}", diff --git a/generate/src/contract/deployment.rs b/generate/src/contract/deployment.rs index bd76f2e5..2e93f1f8 100644 --- a/generate/src/contract/deployment.rs +++ b/generate/src/contract/deployment.rs @@ -1,7 +1,6 @@ use crate::contract::{methods, Context}; use crate::util; use anyhow::{Context as _, Result}; -use ethcontract_common::abi::{Param, ParamType}; use ethcontract_common::Address; use inflector::Inflector; use proc_macro2::{Literal, TokenStream}; @@ -99,41 +98,49 @@ fn expand_deploy(cx: &Context) -> Result { None => (quote! {}, quote! {()}), }; - let lib_params: Vec<_> = cx - .artifact - .bytecode - .undefined_libraries() - .map(|name| Param { - name: name.to_snake_case(), - kind: ParamType::Address, - }) - .collect(); - let lib_input = methods::expand_inputs(&lib_params)?; - - let link = if !lib_params.is_empty() { - let link_libraries = cx - .artifact - .bytecode - .undefined_libraries() - .zip(lib_params.iter()) - .map(|(name, lib_param)| { - let name = Literal::string(&name); - let address = util::ident(&lib_param.name); + let libs: Vec<_> = cx.artifact.bytecode.undefined_libraries().collect(); + let (lib_struct, lib_input, link) = if !libs.is_empty() { + let lib_struct = { + let lib_struct_fields = libs.iter().map(|name| { + let doc = util::expand_doc(&format!("Address of the `{}` library.", name)); + let field = util::safe_ident(&name.to_snake_case()); + + quote! { #doc pub #field: self::ethcontract::Address } + }); + + quote! { + /// Undefinied libraries in the contract bytecode that are + /// required for linking in order to deploy. + pub struct Libraries { + #( #lib_struct_fields, )* + } + } + }; + + let link = { + let link_libraries = libs.iter().map(|name| { + let name_lit = Literal::string(&name); + let field = util::safe_ident(&name.to_snake_case()); quote! { - bytecode.link(#name, #address).expect("valid library"); + bytecode.link(#name_lit, libs.#field).expect("valid library"); } }); - quote! { - let mut bytecode = bytecode; - #( #link_libraries )* - } + quote! { + let mut bytecode = bytecode; + #( #link_libraries )* + } + }; + + (lib_struct, quote! { , libs: Libraries }, link) } else { - quote! {} + Default::default() }; Ok(quote! { + #lib_struct + impl Contract { #doc pub fn builder( From c55997673f1494172828d6b15e06a1d149c3e829 Mon Sep 17 00:00:00 2001 From: Nicholas Rodrigues Lordello Date: Tue, 31 Mar 2020 07:48:01 +0200 Subject: [PATCH 2/2] generate field identifier in one place --- generate/src/contract/deployment.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/generate/src/contract/deployment.rs b/generate/src/contract/deployment.rs index 2e93f1f8..d0ee3cbb 100644 --- a/generate/src/contract/deployment.rs +++ b/generate/src/contract/deployment.rs @@ -98,14 +98,20 @@ fn expand_deploy(cx: &Context) -> Result { None => (quote! {}, quote! {()}), }; - let libs: Vec<_> = cx.artifact.bytecode.undefined_libraries().collect(); + let libs: Vec<_> = cx + .artifact + .bytecode + .undefined_libraries() + .map(|name| (name, util::safe_ident(&name.to_snake_case()))) + .collect(); let (lib_struct, lib_input, link) = if !libs.is_empty() { let lib_struct = { - let lib_struct_fields = libs.iter().map(|name| { + let lib_struct_fields = libs.iter().map(|(name, field)| { let doc = util::expand_doc(&format!("Address of the `{}` library.", name)); - let field = util::safe_ident(&name.to_snake_case()); - quote! { #doc pub #field: self::ethcontract::Address } + quote! { + #doc pub #field: self::ethcontract::Address + } }); quote! { @@ -118,9 +124,8 @@ fn expand_deploy(cx: &Context) -> Result { }; let link = { - let link_libraries = libs.iter().map(|name| { + let link_libraries = libs.iter().map(|(name, field)| { let name_lit = Literal::string(&name); - let field = util::safe_ident(&name.to_snake_case()); quote! { bytecode.link(#name_lit, libs.#field).expect("valid library");