From 04ac018e72b83dd12a089538d3b43c5aa997c182 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 14 Oct 2021 21:28:31 +0200 Subject: [PATCH 1/2] test: add underscore test --- ethers-contract/tests/abigen.rs | 25 ++++++++++++++++++- .../solidity-contracts/SimpleStorage.sol | 2 ++ .../solidity-contracts/simplestorage_abi.json | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 ethers-contract/tests/solidity-contracts/simplestorage_abi.json diff --git a/ethers-contract/tests/abigen.rs b/ethers-contract/tests/abigen.rs index 801df914d..edafd9977 100644 --- a/ethers-contract/tests/abigen.rs +++ b/ethers-contract/tests/abigen.rs @@ -2,7 +2,7 @@ //! Test cases to validate the `abigen!` macro use ethers_contract::{abigen, AbiDecode, AbiEncode, EthEvent}; use ethers_core::abi::{Address, Tokenizable}; -use ethers_core::types::U256; +use ethers_core::types::{H256, U256}; use ethers_providers::Provider; use std::sync::Arc; @@ -266,3 +266,26 @@ fn can_handle_overloaded_functions() { assert_eq!(contract_call, decoded_enum); assert_eq!(encoded_call, contract_call.encode().unwrap()); } + +#[test] +fn can_handle_underscore_functions() { + abigen!( + MyContract, + r#"[ + _hashPuzzle() (uint256) + ]"# + ); + abigen!( + SimpleStorage, + "ethers-contract/tests/solidity-contracts/simplestorage_abi.json", + ); + + let (provider, _) = Provider::mocked(); + let client = Arc::new(provider); + let contract = MyContract::new(Address::zero(), client.clone()); + // ensure both functions are callable + let _ = contract.hash_puzzle(); + let _fun = contract.method::<_, H256>("_hashPuzzle", ()).unwrap(); + let contract = SimpleStorage::new(Address::zero(), client); + let _fun = contract.method::<_, H256>("_hashPuzzle", ()).unwrap(); +} diff --git a/ethers-contract/tests/solidity-contracts/SimpleStorage.sol b/ethers-contract/tests/solidity-contracts/SimpleStorage.sol index 52f781cd9..4db4a5564 100644 --- a/ethers-contract/tests/solidity-contracts/SimpleStorage.sol +++ b/ethers-contract/tests/solidity-contracts/SimpleStorage.sol @@ -28,4 +28,6 @@ contract SimpleStorage { _otherValue = value2; lastSender = msg.sender; } + + function _hashPuzzle() public {} } diff --git a/ethers-contract/tests/solidity-contracts/simplestorage_abi.json b/ethers-contract/tests/solidity-contracts/simplestorage_abi.json new file mode 100644 index 000000000..b70bc5c85 --- /dev/null +++ b/ethers-contract/tests/solidity-contracts/simplestorage_abi.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"string","name":"value","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"author","type":"address"},{"indexed":true,"internalType":"address","name":"oldAuthor","type":"address"},{"indexed":false,"internalType":"string","name":"oldValue","type":"string"},{"indexed":false,"internalType":"string","name":"newValue","type":"string"}],"name":"ValueChanged","type":"event"},{"inputs":[],"name":"_hashPuzzle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getValue","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"},{"internalType":"string","name":"value2","type":"string"}],"name":"setValues","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file From f156b0624623358ad7b1f12172c02bcce9ad31a9 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Fri, 22 Oct 2021 13:48:49 +0300 Subject: [PATCH 2/2] test: ensure underscore fn names are correctly encoded against live contract --- ethers-contract/tests/abigen.rs | 84 +++++++++++++++---- .../solidity-contracts/SimpleStorage.sol | 4 +- .../solidity-contracts/simplestorage_abi.json | 78 ++++++++++++++++- 3 files changed, 148 insertions(+), 18 deletions(-) diff --git a/ethers-contract/tests/abigen.rs b/ethers-contract/tests/abigen.rs index edafd9977..49eb6811d 100644 --- a/ethers-contract/tests/abigen.rs +++ b/ethers-contract/tests/abigen.rs @@ -2,8 +2,10 @@ //! Test cases to validate the `abigen!` macro use ethers_contract::{abigen, AbiDecode, AbiEncode, EthEvent}; use ethers_core::abi::{Address, Tokenizable}; -use ethers_core::types::{H256, U256}; +use ethers_core::types::{transaction::eip2718::TypedTransaction, Eip1559TransactionRequest, U256}; +use ethers_core::utils::Solc; use ethers_providers::Provider; +use std::convert::TryFrom; use std::sync::Arc; #[test] @@ -267,25 +269,75 @@ fn can_handle_overloaded_functions() { assert_eq!(encoded_call, contract_call.encode().unwrap()); } -#[test] -fn can_handle_underscore_functions() { - abigen!( - MyContract, - r#"[ - _hashPuzzle() (uint256) - ]"# - ); +#[tokio::test] +async fn can_handle_underscore_functions() { abigen!( SimpleStorage, + r#"[ + _hashPuzzle() (uint256) + ]"#; + + SimpleStorage2, "ethers-contract/tests/solidity-contracts/simplestorage_abi.json", ); - let (provider, _) = Provider::mocked(); + // launcht the network & connect to it + let ganache = ethers_core::utils::Ganache::new().spawn(); + let from = ganache.addresses()[0].clone(); + let provider = Provider::try_from(ganache.endpoint()) + .unwrap() + .with_sender(from) + .interval(std::time::Duration::from_millis(10)); let client = Arc::new(provider); - let contract = MyContract::new(Address::zero(), client.clone()); - // ensure both functions are callable - let _ = contract.hash_puzzle(); - let _fun = contract.method::<_, H256>("_hashPuzzle", ()).unwrap(); - let contract = SimpleStorage::new(Address::zero(), client); - let _fun = contract.method::<_, H256>("_hashPuzzle", ()).unwrap(); + + let compiled = Solc::new("./tests/solidity-contracts/SimpleStorage.sol") + .build() + .unwrap(); + let compiled = compiled.get("SimpleStorage").unwrap(); + let factory = ethers_contract::ContractFactory::new( + compiled.abi.clone(), + compiled.bytecode.clone(), + client.clone(), + ); + let addr = factory + .deploy("hi".to_string()) + .unwrap() + .legacy() + .send() + .await + .unwrap() + .address(); + + // connect to the contract + let contract = SimpleStorage::new(addr, client.clone()); + let contract2 = SimpleStorage2::new(addr, client.clone()); + + let res = contract.hash_puzzle().call().await.unwrap(); + let res2 = contract2.hash_puzzle().call().await.unwrap(); + let res3 = contract + .method::<_, U256>("_hashPuzzle", ()) + .unwrap() + .call() + .await + .unwrap(); + let res4 = contract2 + .method::<_, U256>("_hashPuzzle", ()) + .unwrap() + .call() + .await + .unwrap(); + + // Manual call construction + use ethers_providers::Middleware; + // TODO: How do we handle underscores for calls here? + let data = simplestorage_mod::HashPuzzleCall.encode().unwrap(); + let tx = Eip1559TransactionRequest::new().data(data).to(addr); + let tx = TypedTransaction::Eip1559(tx); + let res5 = client.call(&tx, None).await.unwrap(); + let res5 = U256::from(res5.as_ref()); + assert_eq!(res, 100.into()); + assert_eq!(res, res2); + assert_eq!(res, res3); + assert_eq!(res, res4); + assert_eq!(res, res5); } diff --git a/ethers-contract/tests/solidity-contracts/SimpleStorage.sol b/ethers-contract/tests/solidity-contracts/SimpleStorage.sol index 4db4a5564..85f92db68 100644 --- a/ethers-contract/tests/solidity-contracts/SimpleStorage.sol +++ b/ethers-contract/tests/solidity-contracts/SimpleStorage.sol @@ -29,5 +29,7 @@ contract SimpleStorage { lastSender = msg.sender; } - function _hashPuzzle() public {} + function _hashPuzzle() public view returns (uint256) { + return 100; + } } diff --git a/ethers-contract/tests/solidity-contracts/simplestorage_abi.json b/ethers-contract/tests/solidity-contracts/simplestorage_abi.json index b70bc5c85..6e5edf3fa 100644 --- a/ethers-contract/tests/solidity-contracts/simplestorage_abi.json +++ b/ethers-contract/tests/solidity-contracts/simplestorage_abi.json @@ -1 +1,77 @@ -[{"inputs":[{"internalType":"string","name":"value","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"author","type":"address"},{"indexed":true,"internalType":"address","name":"oldAuthor","type":"address"},{"indexed":false,"internalType":"string","name":"oldValue","type":"string"},{"indexed":false,"internalType":"string","name":"newValue","type":"string"}],"name":"ValueChanged","type":"event"},{"inputs":[],"name":"_hashPuzzle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getValue","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"},{"internalType":"string","name":"value2","type":"string"}],"name":"setValues","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[ + { + "inputs": [{ "internalType": "string", "name": "value", "type": "string" }], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "author", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldAuthor", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldValue", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newValue", + "type": "string" + } + ], + "name": "ValueChanged", + "type": "event" + }, + { + "inputs": [], + "name": "_hashPuzzle", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValue", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastSender", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "string", "name": "value", "type": "string" }], + "name": "setValue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "string", "name": "value", "type": "string" }, + { "internalType": "string", "name": "value2", "type": "string" } + ], + "name": "setValues", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] +