From e97acc9b9e8322c21e16664e3bf47acb24214ffb Mon Sep 17 00:00:00 2001 From: sveitser Date: Thu, 27 Oct 2022 18:02:10 +0200 Subject: [PATCH 01/21] WIP: use EIP1559 transactions --- contracts/rust/Cargo.toml | 6 +++--- contracts/rust/src/cape/submit_block.rs | 4 ---- contracts/rust/src/ethereum.rs | 2 +- contracts/rust/src/records_merkle_tree/mod.rs | 2 -- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/contracts/rust/Cargo.toml b/contracts/rust/Cargo.toml index 8986c28e..4e35bfce 100644 --- a/contracts/rust/Cargo.toml +++ b/contracts/rust/Cargo.toml @@ -42,9 +42,9 @@ commit = { git = "https://github.com/EspressoSystems/commit.git", tag = "0.1.0" espresso-macros = { git = "https://github.com/EspressoSystems/espresso-macros.git" } # We need the legacy feature in order to avoid gas estimation issues. See https://github.com/gakonst/ethers-rs/issues/825 -ethers = { features = ["legacy"], git = "https://github.com/gakonst/ethers-rs" } -ethers-contract = { features = ["legacy"], git = "https://github.com/gakonst/ethers-rs" } -ethers-core = { features = ["legacy"], git = "https://github.com/gakonst/ethers-rs" } +ethers = { git = "https://github.com/gakonst/ethers-rs" } +ethers-contract = { git = "https://github.com/gakonst/ethers-rs" } +ethers-core = { git = "https://github.com/gakonst/ethers-rs" } futures = "0.3.16" generic-array = { version = "0.14.4", features = ["serde"] } hex = "0.4.3" diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index 66675988..3bb284e9 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -87,10 +87,6 @@ pub async fn submit_cape_block_with_memos( .fill_transaction(&mut tx, Some(block_number.into())) .await?; - // Increase the gas price by 20% to increase the chances for the transaction - // to be mined. - tx.set_gas_price(tx.gas_price().unwrap() * 12 / 10); - // The estimated gas cost can be too low. For example, if a deposit is made // in an earlier transaction in the same block the estimate would not include // the cost for crediting the deposit. diff --git a/contracts/rust/src/ethereum.rs b/contracts/rust/src/ethereum.rs index b0cef5fe..7dd8155a 100644 --- a/contracts/rust/src/ethereum.rs +++ b/contracts/rust/src/ethereum.rs @@ -212,7 +212,7 @@ pub async fn deploy( link_unlinked_libraries(&mut bytecode, &client).await?; let factory = ContractFactory::new(abi.clone(), bytecode.into_bytes().unwrap(), client.clone()); - let contract = factory.deploy(constructor_args)?.legacy().send().await?; + let contract = factory.deploy(constructor_args)?.send().await?; Ok(contract) } diff --git a/contracts/rust/src/records_merkle_tree/mod.rs b/contracts/rust/src/records_merkle_tree/mod.rs index fcf23e83..dd53d74b 100644 --- a/contracts/rust/src/records_merkle_tree/mod.rs +++ b/contracts/rust/src/records_merkle_tree/mod.rs @@ -241,7 +241,6 @@ mod tests { let elems_u256 = insert_elements_into_jellyfish_mt(&mut mt, n_leaves_before); contract .update_records_merkle_tree(elems_u256) - .legacy() .send() .await .unwrap() @@ -254,7 +253,6 @@ mod tests { let elems_u256 = insert_elements_into_jellyfish_mt(&mut mt, n_leaves_after); contract .update_records_merkle_tree(elems_u256) - .legacy() .send() .await .unwrap() From c43ecd9b0cf1ce4ecf9524570ca69f606e167096 Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 28 Oct 2022 15:01:34 +0200 Subject: [PATCH 02/21] WIP: run all tests against arbitrum --- bin/run-tests-arbitrum | 28 +++++++++++++++++++++++ contracts/deploy/00_cape.ts | 2 +- contracts/hardhat.config.ts | 5 +++++ contracts/rust/src/cape/submit_block.rs | 30 +++++++++++++++++++++---- contracts/rust/src/deploy.rs | 28 ++++++++++++++++------- contracts/rust/src/ethereum.rs | 10 +++++++-- 6 files changed, 88 insertions(+), 15 deletions(-) create mode 100755 bin/run-tests-arbitrum diff --git a/bin/run-tests-arbitrum b/bin/run-tests-arbitrum new file mode 100755 index 00000000..c8f85eee --- /dev/null +++ b/bin/run-tests-arbitrum @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Copyright (c) 2022 Espresso Systems (espressosys.com) +# This file is part of the Configurable Asset Privacy for Ethereum (CAPE) library. +# +# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# You should have received a copy of the GNU General Public License along with this program. If not, see . + +set -euo pipefail + +# Deploy all the contracts. Reuse the stateless libraries to save gas and time. +# This currently fails at "Ensuring the CAPE faucet is initialized." on arbitrum +# but we only need RescueLib, VerifyingKeys and PlonkVerifier to be deployed. +# hardhat deploy --network arbitrum --reset || true + +function get_addr() { + cat contracts/deployments/arbitrum/$1.json | jq -r .address +} + +export VERIFYING_KEYS_LIB_ADDRESS=$(get_addr VerifyingKeys) +export RESCUE_LIB_ADDRESS=$(get_addr RescueLib) +export VERIFIER_ADDRESS=$(get_addr PlonkVerifier) + +export CAPE_WEB3_PROVIDER_URL=https://goerli-rollup.arbitrum.io/rpc +export ETH_MNEMONIC="$GOERLI_MNEMONIC" + +echo "Running tests..." +cargo test --release -- --test-threads 1 cape::submit_block::tests::test_block_height diff --git a/contracts/deploy/00_cape.ts b/contracts/deploy/00_cape.ts index 6c0c5041..97d4d5d7 100644 --- a/contracts/deploy/00_cape.ts +++ b/contracts/deploy/00_cape.ts @@ -28,7 +28,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { // Wait for 2 confirmations on public networks. waitConfirmations: hre.network.tags.public ? 2 : 1, // Avoid deployment failures due to potentially failing `estimateGas` calls. - gasLimit: 10_000_000, + // gasLimit: 10_000_000, // This is better set in hardhat config.networks..gas }; log("Deploy options:", opts); diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index fe6f983c..4055d263 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -83,6 +83,11 @@ const config: HardhatUserConfig = { accounts: { mnemonic: process.env.GOERLI_MNEMONIC }, tags: ["public"], }, + arbitrum: { + url: "https://goerli-rollup.arbitrum.io/rpc", + gasPrice: 100_000_000, + accounts: { mnemonic: process.env.GOERLI_MNEMONIC }, + }, localhost: { url: `http://localhost:${process.env.RPC_PORT || 8545}`, timeout: 120000, // when running against hardhat, some tests are very slow diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index 3bb284e9..86c5c69d 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -46,7 +46,7 @@ pub async fn submit_cape_block_with_memos( contract: &CAPE, block: BlockWithMemos, block_number: BlockNumber, - gas_limit: u64, + _gas_limit: u64, ) -> Result, SignerMiddlewareError, Wallet>> { let mut memos_bytes: Vec = vec![]; @@ -95,7 +95,15 @@ pub async fn submit_cape_block_with_memos( // gas usage of processing a burn note is potentially unbounded. Using // tokens whose transfer function far exceeds normal gas consumption is // currently not supported. - tx.set_gas(gas_limit); + // + // TODO: mathis: it's a bit wasteful to download the entire block for this + // but I don't know of another way to obtain the current block gas limit. + let block = contract + .client() + .get_block(BlockNumber::Latest) + .await? + .unwrap(); + tx.set_gas(std::cmp::min(tx.gas().unwrap() * 2, block.gas_limit)); contract.client().send_transaction(tx, None).await } @@ -218,21 +226,35 @@ mod tests { .await? ); + println!("adding root"); // Set the root contract .add_root(root.generic_into::().0) .send() .await? - .await?; + .await? + .ensure_mined(); + println!("submit"); // Submit to the contract - contract + let receipt = contract .submit_cape_block(cape_block.into()) .send() .await? .await?; + println!("{:?}", receipt); // Check that now the nullifier has been inserted + for _ in 0..2 { + if contract + .nullifiers(nf.generic_into::().0) + .call() + .await? + { + break; + }; + } + assert!( contract .nullifiers(nf.generic_into::().0) diff --git a/contracts/rust/src/deploy.rs b/contracts/rust/src/deploy.rs index f37852f3..bbb45a36 100644 --- a/contracts/rust/src/deploy.rs +++ b/contracts/rust/src/deploy.rs @@ -16,6 +16,8 @@ use crate::types::{ TestTranscript, TestVerifyingKeys, CAPE, }; use ethers::prelude::{k256::ecdsa::SigningKey, Http, Provider, SignerMiddleware, Wallet}; +use ethers::types::Address; +use std::env; use std::sync::Arc; // Middleware used for locally signing transactions @@ -35,13 +37,23 @@ pub async fn deploy_test_cape_with_deployer( deployer: Arc, ) -> TestCAPE { // deploy the PlonkVerifier - let verifier = deploy( - deployer.clone(), - &contract_abi_path("verifier/PlonkVerifier.sol/PlonkVerifier"), - (), - ) - .await - .unwrap(); + + // If VERIFIER_ADDRESS is set, use that address instead of deploying a new + // contract. + let verifier_address = match env::var("VERIFIER_ADDRESS") { + Ok(val) => { + println!("Using Verifier at {val}"); + val.parse::
().unwrap() + } + Err(_) => deploy( + deployer.clone(), + &contract_abi_path("verifier/PlonkVerifier.sol/PlonkVerifier"), + (), + ) + .await + .unwrap() + .address(), + }; let records_merkle_tree = deploy( deployer.clone(), @@ -57,7 +69,7 @@ pub async fn deploy_test_cape_with_deployer( &contract_abi_path("mocks/TestCAPE.sol/TestCAPE"), CAPEConstructorArgs::new( CAPE_NUM_ROOTS as u64, - verifier.address(), + verifier_address, records_merkle_tree.address(), ) .to_tuple(), diff --git a/contracts/rust/src/ethereum.rs b/contracts/rust/src/ethereum.rs index 7dd8155a..bd568f87 100644 --- a/contracts/rust/src/ethereum.rs +++ b/contracts/rust/src/ethereum.rs @@ -153,7 +153,10 @@ async fn link_unlinked_libraries( // Connect to linked library if env var with address is set // otherwise, deploy the library. let rescue_lib_address = match env::var("RESCUE_LIB_ADDRESS") { - Ok(val) => val.parse::
()?, + Ok(val) => { + println!("Using RescueLib library at {val}"); + val.parse::
()? + } Err(_) => deploy( client.clone(), &contract_abi_path("libraries/RescueLib.sol/RescueLib"), @@ -177,7 +180,10 @@ async fn link_unlinked_libraries( // Connect to linked library if env var with address is set // otherwise, deploy the library. let verifying_keys_lib_address = match env::var("VERIFYING_KEYS_LIB_ADDRESS") { - Ok(val) => val.parse::
()?, + Ok(val) => { + println!("Using VerifyingKeys library at {val}"); + val.parse::
()? + } Err(_) => deploy( client.clone(), &contract_abi_path("libraries/VerifyingKeys.sol/VerifyingKeys"), From a919d18009a06c3565dd1ea6252134fa26757140 Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 28 Oct 2022 15:28:23 +0200 Subject: [PATCH 03/21] Fix tests in cap-rust-sandbox - Specify manual gas limit where estimated value leads to transaction running out of gas. - Add some `.ensure_mined()` calls. - Replace some unwraps with `?`. --- contracts/rust/src/cape/submit_block.rs | 15 ++++-- contracts/rust/src/cape_e2e_test_mint.rs | 55 +++++++++----------- contracts/rust/src/cape_e2e_test_transfer.rs | 41 +++++++-------- 3 files changed, 55 insertions(+), 56 deletions(-) diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index 3bb284e9..9e4981d9 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -223,14 +223,17 @@ mod tests { .add_root(root.generic_into::().0) .send() .await? - .await?; + .await? + .ensure_mined(); // Submit to the contract contract .submit_cape_block(cape_block.into()) + .gas(10_000_000) // runs out of gas with estimate .send() .await? - .await?; + .await? + .ensure_mined(); // Check that now the nullifier has been inserted assert!( @@ -349,6 +352,7 @@ mod tests { contract .submit_cape_block(cape_block.into()) + .gas(10_000_000) .send() .await? .await? @@ -373,13 +377,16 @@ mod tests { .add_root(root.generic_into::().0) .send() .await? - .await?; + .await? + .ensure_mined(); contract .submit_cape_block(cape_block.into()) + .gas(10_000_000) .send() .await? - .await?; + .await? + .ensure_mined(); let logs = contract .block_committed_filter() diff --git a/contracts/rust/src/cape_e2e_test_mint.rs b/contracts/rust/src/cape_e2e_test_mint.rs index d28a1e74..b59d9e9e 100644 --- a/contracts/rust/src/cape_e2e_test_mint.rs +++ b/contracts/rust/src/cape_e2e_test_mint.rs @@ -8,6 +8,7 @@ #![cfg(test)] #![deny(warnings)] +use crate::assertion::EnsureMined; use crate::deploy::deploy_test_cape; use crate::{ cape::*, @@ -87,43 +88,38 @@ async fn test_mint_maybe_submit(should_submit: bool) -> Result<()> { let alice_rec_comm = RecordCommitment::from(&alice_rec1); let alice_rec_field_elem = alice_rec_comm.to_field_element(); t.push(alice_rec_field_elem); - let alice_rec_path = t.get_leaf(0).expect_ok().unwrap().1.path; + let alice_rec_path = t.get_leaf(0).expect_ok()?.1.path; assert_eq!( alice_rec_path.nodes.len(), CapeLedger::merkle_height() as usize ); if let Some(contract) = contract.as_ref() { - assert_eq!( - contract.get_root_value().call().await.unwrap(), - U256::from(0u64) - ); + assert_eq!(contract.get_root_value().call().await?, U256::from(0u64)); contract .set_initial_record_commitments(vec![field_to_u256(alice_rec_field_elem)]) + .gas(10_000_000) .send() - .await - .unwrap() - .await - .unwrap(); + .await? + .await? + .ensure_mined(); let first_root = t.commitment().root_value; - assert_eq!( - contract.get_num_leaves().call().await.unwrap(), - U256::from(1u64) - ); + assert_eq!(contract.get_num_leaves().call().await?, U256::from(1u64)); assert_eq!( - contract.get_root_value().call().await.unwrap(), + contract.get_root_value().call().await?, field_to_u256(first_root.to_scalar()) ); - assert!(contract - .contains_root(field_to_u256(first_root.to_scalar())) - .call() - .await - .unwrap()); + assert!( + contract + .contains_root(field_to_u256(first_root.to_scalar())) + .call() + .await? + ); } println!("Tree set up: {}s", now.elapsed().as_secs_f32()); @@ -162,9 +158,9 @@ async fn test_mint_maybe_submit(should_submit: bool) -> Result<()> { let description = "My Asset".as_bytes(); let code = AssetCode::new_domestic(seed, description); let policy = AssetPolicy::default(); - let new_coin = AssetDefinition::new(code, policy).unwrap(); + let new_coin = AssetDefinition::new(code, policy)?; - let (fee_info, _fee_ro) = TxnFeeInfo::new(&mut prng, fee_input, 1u64.into()).unwrap(); + let (fee_info, _fee_ro) = TxnFeeInfo::new(&mut prng, fee_input, 1u64.into())?; let mint_ro = RecordOpening::new( &mut prng, 1u64.into(), /* 1 less, for the transaction fee */ @@ -180,8 +176,7 @@ async fn test_mint_maybe_submit(should_submit: bool) -> Result<()> { description, fee_info, &prove_keys.mint, - ) - .unwrap() + )? }; println!("Mint generated: {}s", now.elapsed().as_secs_f32()); @@ -204,11 +199,9 @@ async fn test_mint_maybe_submit(should_submit: bool) -> Result<()> { let txn1_cape = CapeModelTxn::CAP(TransactionNote::Mint(Box::new(txn1))); - let (new_state, effects) = validator - .submit_operations(vec![CapeModelOperation::SubmitBlock(vec![ - txn1_cape.clone() - ])]) - .unwrap(); + let (new_state, effects) = validator.submit_operations(vec![ + CapeModelOperation::SubmitBlock(vec![txn1_cape.clone()]), + ])?; if let Some(contract) = contract.as_ref() { let miner = UserPubKey::default(); @@ -217,9 +210,11 @@ async fn test_mint_maybe_submit(should_submit: bool) -> Result<()> { // Submit to the contract contract .submit_cape_block(cape_block.into()) + .gas(10_000_000) .send() .await? - .await?; + .await? + .ensure_mined(); } println!("Mint validated & applied: {}s", now.elapsed().as_secs_f32()); @@ -250,7 +245,7 @@ async fn test_mint_maybe_submit(should_submit: bool) -> Result<()> { if let Some(contract) = contract.as_ref() { assert_eq!( - contract.get_root_value().call().await.unwrap(), + contract.get_root_value().call().await?, field_to_u256( new_state .ledger diff --git a/contracts/rust/src/cape_e2e_test_transfer.rs b/contracts/rust/src/cape_e2e_test_transfer.rs index 15c4ebac..dd432cd5 100644 --- a/contracts/rust/src/cape_e2e_test_transfer.rs +++ b/contracts/rust/src/cape_e2e_test_transfer.rs @@ -8,6 +8,7 @@ #![cfg(test)] #![deny(warnings)] +use crate::assertion::EnsureMined; use crate::deploy::deploy_test_cape; use crate::test_utils::keysets_for_test; use crate::{ @@ -85,43 +86,37 @@ async fn test_2user_maybe_submit(should_submit: bool) -> Result<()> { let alice_rec_comm = RecordCommitment::from(&alice_rec1); let alice_rec_field_elem = alice_rec_comm.to_field_element(); t.push(alice_rec_field_elem); - let alice_rec_path = t.get_leaf(0).expect_ok().unwrap().1.path; + let alice_rec_path = t.get_leaf(0).expect_ok()?.1.path; assert_eq!( alice_rec_path.nodes.len(), CapeLedger::merkle_height() as usize ); if let Some(contract) = contract.as_ref() { - assert_eq!( - contract.get_root_value().call().await.unwrap(), - U256::from(0u64) - ); + assert_eq!(contract.get_root_value().call().await?, U256::from(0u64)); contract .set_initial_record_commitments(vec![field_to_u256(alice_rec_field_elem)]) .send() - .await - .unwrap() - .await - .unwrap(); + .await? + .await? + .ensure_mined(); let first_root = t.commitment().root_value; - assert_eq!( - contract.get_num_leaves().call().await.unwrap(), - U256::from(1u64) - ); + assert_eq!(contract.get_num_leaves().call().await?, U256::from(1u64)); assert_eq!( - contract.get_root_value().call().await.unwrap(), + contract.get_root_value().call().await?, field_to_u256(first_root.to_scalar()) ); - assert!(contract - .contains_root(field_to_u256(first_root.to_scalar())) - .call() - .await - .unwrap()); + assert!( + contract + .contains_root(field_to_u256(first_root.to_scalar())) + .call() + .await? + ); } println!("Tree set up: {}s", now.elapsed().as_secs_f32()); @@ -211,9 +206,11 @@ async fn test_2user_maybe_submit(should_submit: bool) -> Result<()> { // Submit to the contract contract .submit_cape_block(cape_block.into()) + .gas(10_000_000) .send() .await? - .await?; + .await? + .ensure_mined(); } println!( @@ -248,7 +245,7 @@ async fn test_2user_maybe_submit(should_submit: bool) -> Result<()> { if let Some(contract) = contract.as_ref() { assert_eq!( - contract.get_root_value().call().await.unwrap(), + contract.get_root_value().call().await?, field_to_u256( new_state .ledger @@ -269,7 +266,7 @@ async fn test_2user_maybe_submit(should_submit: bool) -> Result<()> { } let ro = bob_rec; - let merkle_path = wallet_merkle_tree.get_leaf(2).expect_ok().unwrap().1.path; + let merkle_path = wallet_merkle_tree.get_leaf(2).expect_ok()?.1.path; let merkle_root = new_state.ledger.record_merkle_commitment.root_value; let uid = 2; From 9d7f67ec6df352c22cc9f5d6089f8deab6b655a9 Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 28 Oct 2022 15:45:41 +0200 Subject: [PATCH 04/21] Fix cap-rust-sandbox integration tests - Specify manual gas limit where transactions run out of gas. --- .../rust/tests/combined/smoke_tests_deployed_contract.rs | 1 + contracts/rust/tests/combined/unwrapping.rs | 9 +++++++-- .../rust/tests/combined/wrapped_assets_can_be_frozen.rs | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs b/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs index f119d0a6..787967d8 100644 --- a/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs +++ b/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs @@ -197,6 +197,7 @@ async fn smoke_tests() -> Result<()> { cape_contract .submit_cape_block(cape_block.clone().into()) + .gas(10_000_000) // out of gas with estimate .send() .await? .await? diff --git a/contracts/rust/tests/combined/unwrapping.rs b/contracts/rust/tests/combined/unwrapping.rs index 1d28a814..60b61fba 100644 --- a/contracts/rust/tests/combined/unwrapping.rs +++ b/contracts/rust/tests/combined/unwrapping.rs @@ -83,7 +83,8 @@ async fn integration_test_unwrapping() -> Result<()> { .approve(cape_contract_address, amount_u256) .send() .await? - .await?; + .await? + .ensure_mined(); let wrapped_ro = RecordOpening::new( rng, @@ -105,7 +106,8 @@ async fn integration_test_unwrapping() -> Result<()> { ) .send() .await? - .await?; + .await? + .ensure_mined(); // Submit empty block to trigger the inclusion of the pending deposit record commitment into the merkle tree let miner = UserPubKey::default(); @@ -113,6 +115,7 @@ async fn integration_test_unwrapping() -> Result<()> { cape_contract .submit_cape_block(empty_block.clone().into()) + .gas(10_000_000) // out of gas with estimate .send() .await? .await? @@ -160,9 +163,11 @@ async fn integration_test_unwrapping() -> Result<()> { cape_contract .submit_cape_block(cape_block.clone().into()) + .gas(10_000_000) // out of gas with estimate .send() .await? .await? + .ensure_mined() .print_gas("Burn transaction"); // The recipient has received the ERC20 tokens diff --git a/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs b/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs index 09a2f7a7..0edcc10c 100644 --- a/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs +++ b/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs @@ -127,6 +127,7 @@ async fn integration_test_wrapped_assets_can_be_frozen() -> Result<()> { cape_contract .submit_cape_block(empty_block.clone().into()) + .gas(10_000_000) // out of gas with estimate .send() .await? .await? @@ -194,6 +195,7 @@ async fn integration_test_wrapped_assets_can_be_frozen() -> Result<()> { // Submit the block with the freeze note cape_contract .submit_cape_block(block_with_freeze_note.clone().into()) + .gas(10_000_000) // out of gas with estimate .send() .await? .await? From 44b13152abdefce6dac61e3786e87587e51cf89f Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 28 Oct 2022 15:54:57 +0200 Subject: [PATCH 05/21] WIP: define constant for gas limit --- contracts/rust/src/cape/events.rs | 2 +- contracts/rust/src/cape/submit_block.rs | 6 +++--- contracts/rust/src/cape_e2e_test_mint.rs | 4 ++-- contracts/rust/src/cape_e2e_test_transfer.rs | 2 +- contracts/rust/src/ethereum.rs | 2 ++ .../rust/tests/combined/smoke_tests_deployed_contract.rs | 2 +- contracts/rust/tests/combined/unwrapping.rs | 4 ++-- .../rust/tests/combined/wrapped_assets_can_be_frozen.rs | 4 ++-- contracts/rust/tests/combined/wrapping.rs | 2 +- 9 files changed, 15 insertions(+), 13 deletions(-) diff --git a/contracts/rust/src/cape/events.rs b/contracts/rust/src/cape/events.rs index eec01dbd..c6f1a78f 100644 --- a/contracts/rust/src/cape/events.rs +++ b/contracts/rust/src/cape/events.rs @@ -96,7 +96,7 @@ mod tests { &connection.contract, block_with_memos.clone(), BlockNumber::Latest, - 10_000_000, // gas limit + GAS_LIMIT_OVERRIDE, // gas limit ) .await? .await?; diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index 9e4981d9..fc5bc276 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -229,7 +229,7 @@ mod tests { // Submit to the contract contract .submit_cape_block(cape_block.into()) - .gas(10_000_000) // runs out of gas with estimate + .gas(GAS_LIMIT_OVERRIDE) // runs out of gas with estimate .send() .await? .await? @@ -352,7 +352,7 @@ mod tests { contract .submit_cape_block(cape_block.into()) - .gas(10_000_000) + .gas(GAS_LIMIT_OVERRIDE) .send() .await? .await? @@ -382,7 +382,7 @@ mod tests { contract .submit_cape_block(cape_block.into()) - .gas(10_000_000) + .gas(GAS_LIMIT_OVERRIDE) .send() .await? .await? diff --git a/contracts/rust/src/cape_e2e_test_mint.rs b/contracts/rust/src/cape_e2e_test_mint.rs index b59d9e9e..3afc69b3 100644 --- a/contracts/rust/src/cape_e2e_test_mint.rs +++ b/contracts/rust/src/cape_e2e_test_mint.rs @@ -99,7 +99,7 @@ async fn test_mint_maybe_submit(should_submit: bool) -> Result<()> { contract .set_initial_record_commitments(vec![field_to_u256(alice_rec_field_elem)]) - .gas(10_000_000) + .gas(GAS_LIMIT_OVERRIDE) .send() .await? .await? @@ -210,7 +210,7 @@ async fn test_mint_maybe_submit(should_submit: bool) -> Result<()> { // Submit to the contract contract .submit_cape_block(cape_block.into()) - .gas(10_000_000) + .gas(GAS_LIMIT_OVERRIDE) .send() .await? .await? diff --git a/contracts/rust/src/cape_e2e_test_transfer.rs b/contracts/rust/src/cape_e2e_test_transfer.rs index dd432cd5..056130d9 100644 --- a/contracts/rust/src/cape_e2e_test_transfer.rs +++ b/contracts/rust/src/cape_e2e_test_transfer.rs @@ -206,7 +206,7 @@ async fn test_2user_maybe_submit(should_submit: bool) -> Result<()> { // Submit to the contract contract .submit_cape_block(cape_block.into()) - .gas(10_000_000) + .gas(GAS_LIMIT_OVERRIDE) .send() .await? .await? diff --git a/contracts/rust/src/ethereum.rs b/contracts/rust/src/ethereum.rs index 7dd8155a..932e9057 100644 --- a/contracts/rust/src/ethereum.rs +++ b/contracts/rust/src/ethereum.rs @@ -25,6 +25,8 @@ use ethers::{ use std::{convert::TryFrom, env, fs, path::Path, sync::Arc, time::Duration}; +pub const GAS_LIMIT_OVERRIDE: u64 = 10_000_000; + /// Utility to interact with the CAPE contract on some Ethereum blockchain #[derive(Clone, Debug)] pub struct EthConnection { diff --git a/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs b/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs index 787967d8..ea5dd11a 100644 --- a/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs +++ b/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs @@ -197,7 +197,7 @@ async fn smoke_tests() -> Result<()> { cape_contract .submit_cape_block(cape_block.clone().into()) - .gas(10_000_000) // out of gas with estimate + .gas(GAS_LIMIT_OVERRIDE) // out of gas with estimate .send() .await? .await? diff --git a/contracts/rust/tests/combined/unwrapping.rs b/contracts/rust/tests/combined/unwrapping.rs index 60b61fba..f5780ffe 100644 --- a/contracts/rust/tests/combined/unwrapping.rs +++ b/contracts/rust/tests/combined/unwrapping.rs @@ -115,7 +115,7 @@ async fn integration_test_unwrapping() -> Result<()> { cape_contract .submit_cape_block(empty_block.clone().into()) - .gas(10_000_000) // out of gas with estimate + .gas(GAS_LIMIT_OVERRIDE) // out of gas with estimate .send() .await? .await? @@ -163,7 +163,7 @@ async fn integration_test_unwrapping() -> Result<()> { cape_contract .submit_cape_block(cape_block.clone().into()) - .gas(10_000_000) // out of gas with estimate + .gas(GAS_LIMIT_OVERRIDE) // out of gas with estimate .send() .await? .await? diff --git a/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs b/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs index 0edcc10c..a89a77cb 100644 --- a/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs +++ b/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs @@ -127,7 +127,7 @@ async fn integration_test_wrapped_assets_can_be_frozen() -> Result<()> { cape_contract .submit_cape_block(empty_block.clone().into()) - .gas(10_000_000) // out of gas with estimate + .gas(GAS_LIMIT_OVERRIDE) // out of gas with estimate .send() .await? .await? @@ -195,7 +195,7 @@ async fn integration_test_wrapped_assets_can_be_frozen() -> Result<()> { // Submit the block with the freeze note cape_contract .submit_cape_block(block_with_freeze_note.clone().into()) - .gas(10_000_000) // out of gas with estimate + .gas(GAS_LIMIT_OVERRIDE) // out of gas with estimate .send() .await? .await? diff --git a/contracts/rust/tests/combined/wrapping.rs b/contracts/rust/tests/combined/wrapping.rs index cf61642d..3072b931 100644 --- a/contracts/rust/tests/combined/wrapping.rs +++ b/contracts/rust/tests/combined/wrapping.rs @@ -240,7 +240,7 @@ async fn integration_test_wrapping_erc20_tokens() -> Result<()> { // Submit to the contract cape_contract .submit_cape_block(cape_block.clone().into()) - .gas(U256::from(10_000_000)) + .gas(U256::from(GAS_LIMIT_OVERRIDE)) .send() .await? .await? From 0297e75e3dfb699e4abbd9f336839a5e6826f458 Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 28 Oct 2022 16:01:48 +0200 Subject: [PATCH 06/21] Extract constant for gas limit override --- contracts/rust/src/cape/events.rs | 2 +- contracts/rust/src/cape/submit_block.rs | 1 + contracts/rust/src/cape_e2e_test_mint.rs | 1 + contracts/rust/src/cape_e2e_test_transfer.rs | 1 + contracts/rust/src/ethereum.rs | 2 ++ contracts/rust/tests/combined/smoke_tests_deployed_contract.rs | 2 +- contracts/rust/tests/combined/unwrapping.rs | 2 +- contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs | 1 + contracts/rust/tests/combined/wrapping.rs | 3 ++- 9 files changed, 11 insertions(+), 4 deletions(-) diff --git a/contracts/rust/src/cape/events.rs b/contracts/rust/src/cape/events.rs index c6f1a78f..43b8a922 100644 --- a/contracts/rust/src/cape/events.rs +++ b/contracts/rust/src/cape/events.rs @@ -28,7 +28,7 @@ mod tests { submit_block::{fetch_cape_memos, submit_cape_block_with_memos}, BlockWithMemos, CapeBlock, }, - ethereum::EthConnection, + ethereum::{EthConnection, GAS_LIMIT_OVERRIDE}, ledger::CapeLedger, types::{GenericInto, MerkleRootSol}, }; diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index fc5bc276..82abd70a 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -107,6 +107,7 @@ mod tests { assertion::{EnsureMined, Matcher}, cape::CapeBlock, deploy::deploy_test_cape, + ethereum::GAS_LIMIT_OVERRIDE, ledger::CapeLedger, types::{GenericInto, MerkleRootSol, NullifierSol}, }; diff --git a/contracts/rust/src/cape_e2e_test_mint.rs b/contracts/rust/src/cape_e2e_test_mint.rs index 3afc69b3..8de6c7fb 100644 --- a/contracts/rust/src/cape_e2e_test_mint.rs +++ b/contracts/rust/src/cape_e2e_test_mint.rs @@ -10,6 +10,7 @@ use crate::assertion::EnsureMined; use crate::deploy::deploy_test_cape; +use crate::ethereum::GAS_LIMIT_OVERRIDE; use crate::{ cape::*, ledger::CapeLedger, diff --git a/contracts/rust/src/cape_e2e_test_transfer.rs b/contracts/rust/src/cape_e2e_test_transfer.rs index 056130d9..5270bbd1 100644 --- a/contracts/rust/src/cape_e2e_test_transfer.rs +++ b/contracts/rust/src/cape_e2e_test_transfer.rs @@ -10,6 +10,7 @@ use crate::assertion::EnsureMined; use crate::deploy::deploy_test_cape; +use crate::ethereum::GAS_LIMIT_OVERRIDE; use crate::test_utils::keysets_for_test; use crate::{ cape::*, diff --git a/contracts/rust/src/ethereum.rs b/contracts/rust/src/ethereum.rs index 932e9057..93544053 100644 --- a/contracts/rust/src/ethereum.rs +++ b/contracts/rust/src/ethereum.rs @@ -25,6 +25,8 @@ use ethers::{ use std::{convert::TryFrom, env, fs, path::Path, sync::Arc, time::Duration}; +/// Supply this gas limit when the automatically filled estimated gas value is +/// too low and the transaction runs out of gas. pub const GAS_LIMIT_OVERRIDE: u64 = 10_000_000; /// Utility to interact with the CAPE contract on some Ethereum blockchain diff --git a/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs b/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs index ea5dd11a..f75e4b28 100644 --- a/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs +++ b/contracts/rust/tests/combined/smoke_tests_deployed_contract.rs @@ -9,7 +9,7 @@ use anyhow::Result; use cap_rust_sandbox::assertion::EnsureMined; use cap_rust_sandbox::cape::CapeBlock; use cap_rust_sandbox::deploy::{deploy_cape, deploy_erc20_token}; -use cap_rust_sandbox::ethereum::get_funded_client; +use cap_rust_sandbox::ethereum::{get_funded_client, GAS_LIMIT_OVERRIDE}; use cap_rust_sandbox::helpers::compute_faucet_key_pair_from_mnemonic; use cap_rust_sandbox::ledger::CapeLedger; use cap_rust_sandbox::model::{erc20_asset_description, Erc20Code, EthereumAddr}; diff --git a/contracts/rust/tests/combined/unwrapping.rs b/contracts/rust/tests/combined/unwrapping.rs index f5780ffe..a2cff9cc 100644 --- a/contracts/rust/tests/combined/unwrapping.rs +++ b/contracts/rust/tests/combined/unwrapping.rs @@ -9,7 +9,7 @@ use anyhow::Result; use cap_rust_sandbox::assertion::{EnsureMined, Matcher}; use cap_rust_sandbox::cape::CapeBlock; use cap_rust_sandbox::deploy::{deploy_cape, deploy_erc20_token}; -use cap_rust_sandbox::ethereum::get_funded_client; +use cap_rust_sandbox::ethereum::{get_funded_client, GAS_LIMIT_OVERRIDE}; use cap_rust_sandbox::ledger::CapeLedger; use cap_rust_sandbox::model::{erc20_asset_description, Erc20Code, EthereumAddr}; use cap_rust_sandbox::test_utils::{ diff --git a/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs b/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs index a89a77cb..7d06a496 100644 --- a/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs +++ b/contracts/rust/tests/combined/wrapped_assets_can_be_frozen.rs @@ -9,6 +9,7 @@ use anyhow::Result; use cap_rust_sandbox::assertion::EnsureMined; use cap_rust_sandbox::cape::CapeBlock; use cap_rust_sandbox::deploy::{deploy_cape, deploy_erc20_token}; +use cap_rust_sandbox::ethereum::GAS_LIMIT_OVERRIDE; use cap_rust_sandbox::ledger::CapeLedger; use cap_rust_sandbox::model::{erc20_asset_description, Erc20Code, EthereumAddr}; use cap_rust_sandbox::test_utils::{ diff --git a/contracts/rust/tests/combined/wrapping.rs b/contracts/rust/tests/combined/wrapping.rs index 3072b931..13694ebb 100644 --- a/contracts/rust/tests/combined/wrapping.rs +++ b/contracts/rust/tests/combined/wrapping.rs @@ -9,6 +9,7 @@ use anyhow::Result; use cap_rust_sandbox::assertion::EnsureMined; use cap_rust_sandbox::cape::CapeBlock; use cap_rust_sandbox::deploy::{deploy_erc20_token, deploy_test_cape}; +use cap_rust_sandbox::ethereum::GAS_LIMIT_OVERRIDE; use cap_rust_sandbox::helpers::compare_merkle_root_from_contract_and_jf_tree; use cap_rust_sandbox::ledger::CapeLedger; use cap_rust_sandbox::model::{erc20_asset_description, Erc20Code, EthereumAddr}; @@ -240,7 +241,7 @@ async fn integration_test_wrapping_erc20_tokens() -> Result<()> { // Submit to the contract cape_contract .submit_cape_block(cape_block.clone().into()) - .gas(U256::from(GAS_LIMIT_OVERRIDE)) + .gas(GAS_LIMIT_OVERRIDE) .send() .await? .await? From 353aea01382da064fedb05ec41d60e3b1ef46f45 Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 28 Oct 2022 16:09:11 +0200 Subject: [PATCH 07/21] fixup --- contracts/rust/src/cape/submit_block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index 53625a85..061e375c 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -238,7 +238,7 @@ mod tests { println!("submit"); // Submit to the contract - let receipt = contract + contract .submit_cape_block(cape_block.into()) .gas(GAS_LIMIT_OVERRIDE) // runs out of gas with estimate .send() From 365179f408d0f4e620fcb84c6a46044f16cdbb8f Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 28 Oct 2022 16:15:36 +0200 Subject: [PATCH 08/21] Undo retry --- contracts/rust/src/cape/submit_block.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index 061e375c..3f79b063 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -246,17 +246,6 @@ mod tests { .await? .ensure_mined(); - // Check that now the nullifier has been inserted - for _ in 0..2 { - if contract - .nullifiers(nf.generic_into::().0) - .call() - .await? - { - break; - }; - } - assert!( contract .nullifiers(nf.generic_into::().0) From ae238df0ec2013f55f6c6007bde2cbba9112ad97 Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 28 Oct 2022 16:17:55 +0200 Subject: [PATCH 09/21] Higher gas limit override for arbitrum --- bin/run-tests-arbitrum | 2 +- contracts/rust/src/ethereum.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/run-tests-arbitrum b/bin/run-tests-arbitrum index c8f85eee..76ae6c55 100755 --- a/bin/run-tests-arbitrum +++ b/bin/run-tests-arbitrum @@ -25,4 +25,4 @@ export CAPE_WEB3_PROVIDER_URL=https://goerli-rollup.arbitrum.io/rpc export ETH_MNEMONIC="$GOERLI_MNEMONIC" echo "Running tests..." -cargo test --release -- --test-threads 1 cape::submit_block::tests::test_block_height +cargo test --release -- --test-threads 1 diff --git a/contracts/rust/src/ethereum.rs b/contracts/rust/src/ethereum.rs index 45b3e18f..651257b8 100644 --- a/contracts/rust/src/ethereum.rs +++ b/contracts/rust/src/ethereum.rs @@ -27,7 +27,7 @@ use std::{convert::TryFrom, env, fs, path::Path, sync::Arc, time::Duration}; /// Supply this gas limit when the automatically filled estimated gas value is /// too low and the transaction runs out of gas. -pub const GAS_LIMIT_OVERRIDE: u64 = 10_000_000; +pub const GAS_LIMIT_OVERRIDE: u64 = 25_000_000; /// Utility to interact with the CAPE contract on some Ethereum blockchain #[derive(Clone, Debug)] From e4447726bb8712720f3700b2f6aa4925e4125778 Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 09:49:49 +0100 Subject: [PATCH 10/21] Remove hardcoded provider URL Fixes `cape::events::tests::test_fetch_cape_memos_from_event` --- bin/run-tests-arbitrum | 2 +- contracts/rust/src/cape/events.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/run-tests-arbitrum b/bin/run-tests-arbitrum index 76ae6c55..6973d2ab 100755 --- a/bin/run-tests-arbitrum +++ b/bin/run-tests-arbitrum @@ -25,4 +25,4 @@ export CAPE_WEB3_PROVIDER_URL=https://goerli-rollup.arbitrum.io/rpc export ETH_MNEMONIC="$GOERLI_MNEMONIC" echo "Running tests..." -cargo test --release -- --test-threads 1 +cargo test --release -- --test-threads 1 "$@" diff --git a/contracts/rust/src/cape/events.rs b/contracts/rust/src/cape/events.rs index 43b8a922..4fc33349 100644 --- a/contracts/rust/src/cape/events.rs +++ b/contracts/rust/src/cape/events.rs @@ -104,7 +104,10 @@ mod tests { // A connection with a random wallet (for queries only) let query_connection = EthConnection::from_config_for_query( &format!("{:?}", connection.contract.address()), // 0x123...cdf - "http://localhost:8545", + &match std::env::var("CAPE_WEB3_PROVIDER_URL") { + Ok(url) => url, + Err(_) => "http://localhost:8545".to_string(), + }, ); let events = query_connection From e410ebb1951bcacdab0cf6fce83fcc2861871c91 Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 09:51:00 +0100 Subject: [PATCH 11/21] Ensure non-deployer is not deployer If `CAPE_WEB3_PROVIDER_URL` is `get_funded_client()` returns the same client each time its called. Use a `call` instead of a `send` to avoid requiring a funded client. This still ensures that the call fails for the right reason (the function was called from the wrong account) because we match against the revert reason. --- contracts/rust/src/cape/faucet.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/contracts/rust/src/cape/faucet.rs b/contracts/rust/src/cape/faucet.rs index 6a07f75e..fc8a929c 100644 --- a/contracts/rust/src/cape/faucet.rs +++ b/contracts/rust/src/cape/faucet.rs @@ -12,23 +12,27 @@ mod test { use crate::{ assertion::Matcher, deploy::deploy_test_cape_with_deployer, - ethereum::get_funded_client, + ethereum::{get_funded_client, get_provider}, model::CAPE_MERKLE_HEIGHT, types::{self as sol, field_to_u256, GenericInto, TestCAPE}, }; use anyhow::Result; - use ethers::abi::AbiDecode; + use ethers::{abi::AbiDecode, prelude::SignerMiddleware, signers::LocalWallet}; use jf_cap::{ keys::UserKeyPair, structs::{AssetDefinition, BlindFactor, FreezeFlag, RecordCommitment, RecordOpening}, BaseField, MerkleTree, }; + use std::sync::Arc; #[tokio::test] async fn test_faucet() -> Result<()> { let rng = &mut ark_std::test_rng(); let deployer = get_funded_client().await?; - let non_deployer = get_funded_client().await?; + let non_deployer = Arc::new(SignerMiddleware::new( + get_provider(), + LocalWallet::new(&mut rand::thread_rng()), + )); let contract = deploy_test_cape_with_deployer(deployer.clone()).await; let faucet_manager = UserKeyPair::generate(rng); @@ -43,7 +47,7 @@ mod test { faucet_manager.address().into(), faucet_manager.pub_key().enc_key().into(), ) - .send() + .call() .await .should_revert_with_message("Only invocable by deployer"); From 790d8cd199211ac8ab7935343e8c07cbfb03a4b5 Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 11:04:06 +0100 Subject: [PATCH 12/21] Enable running wallet tests on arbitrum --- wallet/src/backend.rs | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/wallet/src/backend.rs b/wallet/src/backend.rs index 048636e6..59182d1d 100644 --- a/wallet/src/backend.rs +++ b/wallet/src/backend.rs @@ -713,7 +713,9 @@ mod test { ui::AssetInfo, }; use crate::{CapeWallet, CapeWalletExt}; - use cap_rust_sandbox::{deploy::deploy_erc20_token, universal_param::UNIVERSAL_PARAM}; + use cap_rust_sandbox::{ + deploy::deploy_erc20_token, ethereum::get_funded_client, universal_param::UNIVERSAL_PARAM, + }; use ethers::types::{TransactionRequest, U256}; use jf_cap::structs::AssetCode; use rand_chacha::{rand_core::SeedableRng, ChaChaRng}; @@ -932,19 +934,34 @@ mod test { // Fund the Ethereum wallets for contract calls. let provider = EthRpc::provider(&rpc_url_for_test()).interval(Duration::from_millis(100u64)); + + let deployer = get_funded_client().await.unwrap(); let accounts = provider.get_accounts().await.unwrap(); - assert!(!accounts.is_empty()); + for wallet in [&sponsor, &wrapper] { - let tx = TransactionRequest::new() - .to(Address::from(wallet.eth_address().await.unwrap())) - .value(ethers::utils::parse_ether(U256::from(1u64)).unwrap()) - .from(accounts[0]); - provider - .send_transaction(tx, None) - .await - .unwrap() - .await - .unwrap(); + if accounts.is_empty() { + // On public testnets we don't have unlocked accounts + let tx = TransactionRequest::new() + .to(Address::from(wallet.eth_address().await.unwrap())) + .value(ethers::utils::parse_ether("0.01").unwrap()); + deployer + .send_transaction(tx, None) + .await + .unwrap() + .await + .unwrap(); + } else { + // On private testnets use the unlocked account + let tx = TransactionRequest::new() + .to(Address::from(wallet.eth_address().await.unwrap())) + .value(ethers::utils::parse_ether("1").unwrap()); + provider + .send_transaction(tx, None) + .await + .unwrap() + .await + .unwrap(); + } } let erc20_contract = deploy_erc20_token().await; From 048c02a5dbf1e74ea9261d198d9e1bbd66092903 Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 11:05:24 +0100 Subject: [PATCH 13/21] Update docs for arbitrum testing --- README.md | 22 ++++++++++++++++++++-- bin/run-tests-arbitrum | 11 +++-------- contracts/hardhat.config.ts | 2 +- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 685a5110..14eefde7 100644 --- a/README.md +++ b/README.md @@ -676,14 +676,32 @@ env MY_FAUCET_MANAGER_MNEMONIC="$TEST_MNEMONIC" smoke-test-goerli --reset To run the tests against Arbitrum Goerli follow these steps: -- Install [Metamask](https://metamask.io/) in your browser and copy the mnemonic. +- Install [Metamask](https://metamask.io/) in your browser and restore with + your GOERLI_MNEMONIC. - Switch metamask to the Goerli network. - Get some Goerli ethers at some faucet (see Goerli section above) - Go to the [Arbitrum bridge](https://bridge.arbitrum.io/) and deposit your Goerli eth. Leave a bit for the ethereum gas fees. Wait a few minutes until your account is funded. +- Deploy the contracts + +``` +hardhat deploy --tags CAPE --network arbitrum_goerli --reset +``` + - Run the tests ``` -> env ETH_MNEMONIC="$YOUR_ETH_MNEMONIC" CAPE_WEB3_PROVIDER_URL=https://goerli-rollup.arbitrum.io/rpc cargo test --release test_2user_and_submit -- --nocapture +run-tests-arbitrum +``` + +This script will re-use the stateless libraries in order to save gas and speed +up test execution. To run a single test, pass the test name to the script as +argument, e.g. `run-tests-arbitrum backend::test::test_transfer`. + +If you are getting `Too Many Requests` errors, you may want to set up an infura +project and use their arbitrum goerli RPC and use it via + +``` +CAPE_WEB3_PROVIDER_URL=https://arbitrum-goerli.infura.io/v3/... run-tests-arbitrum ``` diff --git a/bin/run-tests-arbitrum b/bin/run-tests-arbitrum index 6973d2ab..4fd6bd6e 100755 --- a/bin/run-tests-arbitrum +++ b/bin/run-tests-arbitrum @@ -8,11 +8,6 @@ set -euo pipefail -# Deploy all the contracts. Reuse the stateless libraries to save gas and time. -# This currently fails at "Ensuring the CAPE faucet is initialized." on arbitrum -# but we only need RescueLib, VerifyingKeys and PlonkVerifier to be deployed. -# hardhat deploy --network arbitrum --reset || true - function get_addr() { cat contracts/deployments/arbitrum/$1.json | jq -r .address } @@ -21,8 +16,8 @@ export VERIFYING_KEYS_LIB_ADDRESS=$(get_addr VerifyingKeys) export RESCUE_LIB_ADDRESS=$(get_addr RescueLib) export VERIFIER_ADDRESS=$(get_addr PlonkVerifier) -export CAPE_WEB3_PROVIDER_URL=https://goerli-rollup.arbitrum.io/rpc -export ETH_MNEMONIC="$GOERLI_MNEMONIC" +export CAPE_WEB3_PROVIDER_URL=${CAPE_WEB3_PROVIDER_URL:-https://goerli-rollup.arbitrum.io/rpc} +export ETH_MNEMONIC="${ETH_MNEMONIC:-$GOERLI_MNEMONIC}" echo "Running tests..." -cargo test --release -- --test-threads 1 "$@" +cargo test -p faucet --release -- --test-threads 1 "$@" diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 4055d263..0e77d173 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -83,7 +83,7 @@ const config: HardhatUserConfig = { accounts: { mnemonic: process.env.GOERLI_MNEMONIC }, tags: ["public"], }, - arbitrum: { + arbitrum_goerli: { url: "https://goerli-rollup.arbitrum.io/rpc", gasPrice: 100_000_000, accounts: { mnemonic: process.env.GOERLI_MNEMONIC }, From 3023322dff174b8aed4cfef4b9244e398d0467a8 Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 11:09:03 +0100 Subject: [PATCH 14/21] arbitrum: run all tests by default --- bin/run-tests-arbitrum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/run-tests-arbitrum b/bin/run-tests-arbitrum index 4fd6bd6e..b4677c1c 100755 --- a/bin/run-tests-arbitrum +++ b/bin/run-tests-arbitrum @@ -20,4 +20,4 @@ export CAPE_WEB3_PROVIDER_URL=${CAPE_WEB3_PROVIDER_URL:-https://goerli-rollup.ar export ETH_MNEMONIC="${ETH_MNEMONIC:-$GOERLI_MNEMONIC}" echo "Running tests..." -cargo test -p faucet --release -- --test-threads 1 "$@" +cargo test --release -- --test-threads 1 "$@" From c5099b090a75f3ef6e5bbe9f55092cf32228b87d Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 11:49:54 +0100 Subject: [PATCH 15/21] Set `from` address when funding wallet --- wallet/src/backend.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wallet/src/backend.rs b/wallet/src/backend.rs index 59182d1d..830cf8e3 100644 --- a/wallet/src/backend.rs +++ b/wallet/src/backend.rs @@ -954,7 +954,8 @@ mod test { // On private testnets use the unlocked account let tx = TransactionRequest::new() .to(Address::from(wallet.eth_address().await.unwrap())) - .value(ethers::utils::parse_ether("1").unwrap()); + .value(ethers::utils::parse_ether("1").unwrap()) + .from(accounts[0]); provider .send_transaction(tx, None) .await From 58a2d9eb198d570678ebcbc6f89f6df6ae3b9dbd Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 13:22:41 +0100 Subject: [PATCH 16/21] relayer: add extra gas to transaction We previously set the limit manually but this is tricky because gas cost is different on arbitrum. By adding the 10M to the estimate instead it should work for both L1's and arbitrum. Remove the test that tests if the extra gas has effect. The test would be a bit involved to rewrite right now because we can't set a too low gas limit directly anymore. --- contracts/rust/src/cape/submit_block.rs | 7 ++- relayer/src/bin/minimal-relayer.rs | 8 ++-- relayer/src/lib.rs | 63 +++++-------------------- 3 files changed, 21 insertions(+), 57 deletions(-) diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index 3f79b063..e6936da4 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -46,7 +46,7 @@ pub async fn submit_cape_block_with_memos( contract: &CAPE, block: BlockWithMemos, block_number: BlockNumber, - _gas_limit: u64, + extra_gas: u64, ) -> Result, SignerMiddlewareError, Wallet>> { let mut memos_bytes: Vec = vec![]; @@ -103,7 +103,10 @@ pub async fn submit_cape_block_with_memos( .get_block(BlockNumber::Latest) .await? .unwrap(); - tx.set_gas(std::cmp::min(tx.gas().unwrap() * 2, block.gas_limit)); + tx.set_gas(std::cmp::min( + tx.gas().unwrap() + extra_gas, + block.gas_limit, + )); contract.client().send_transaction(tx, None).await } diff --git a/relayer/src/bin/minimal-relayer.rs b/relayer/src/bin/minimal-relayer.rs index d076c1ab..aa8a06b8 100644 --- a/relayer/src/bin/minimal-relayer.rs +++ b/relayer/src/bin/minimal-relayer.rs @@ -14,7 +14,7 @@ use ethers::prelude::{ coins_bip39::English, Address, Middleware, MnemonicBuilder, Signer, SignerMiddleware, }; use relayer::{ - init_web_server, submit_empty_block_loop, NonceCountRule, WebState, DEFAULT_RELAYER_GAS_LIMIT, + init_web_server, submit_empty_block_loop, NonceCountRule, WebState, DEFAULT_RELAYER_EXTRA_GAS, DEFAULT_RELAYER_MAX_RETRIES, DEFAULT_RELAYER_PORT, DEFAULT_RELAYER_RETRY_INTERVAL_MS, }; use std::{num::NonZeroU64, sync::Arc, time::Duration}; @@ -73,8 +73,8 @@ struct MinimalRelayerOptions { /// /// The default of 10M is enough to cover the gas cost of submitting one note /// and crediting up to 10 pending deposits in the smart contract. - #[structopt(long, env = "CAPE_RELAYER_GAS_LIMIT", default_value = DEFAULT_RELAYER_GAS_LIMIT)] - gas_limit: NonZeroU64, + #[structopt(long, env = "CAPE_RELAYER_EXTRA_GAS", default_value = DEFAULT_RELAYER_EXTRA_GAS)] + extra_gas: NonZeroU64, /// Maximum number of times to retry transaction submission. /// @@ -121,7 +121,7 @@ async fn main() -> std::io::Result<()> { let web_state = WebState::new( contract, opt.nonce_count_rule, - opt.gas_limit.into(), + opt.extra_gas.into(), opt.max_retries, Duration::from_millis(opt.retry_interval), ); diff --git a/relayer/src/lib.rs b/relayer/src/lib.rs index b7903acb..5cdcc2de 100644 --- a/relayer/src/lib.rs +++ b/relayer/src/lib.rs @@ -30,7 +30,11 @@ use tide::{ use tracing::{event, Level}; pub const DEFAULT_RELAYER_PORT: &str = "50077"; -pub const DEFAULT_RELAYER_GAS_LIMIT: &str = "10000000"; // 10M + +/// The extra gas added to the gas estimate to account for the gas cost of +/// crediting deposits. +pub const DEFAULT_RELAYER_EXTRA_GAS: &str = "10000000"; // 10M + pub const DEFAULT_RELAYER_RETRY_INTERVAL_MS: &str = "500"; pub const DEFAULT_RELAYER_MAX_RETRIES: &str = "2"; @@ -88,7 +92,7 @@ fn server_error>(err: E) -> tide::Error { pub struct WebState { contract: CAPE, nonce_count_rule: NonceCountRule, - gas_limit: u64, + extra_gas: u64, max_retries: u64, retry_interval: Duration, block_submission_mutex: Arc>, @@ -98,14 +102,14 @@ impl WebState { pub fn new( contract: CAPE, nonce_count_rule: NonceCountRule, - gas_limit: u64, + extra_gas: u64, max_retries: u64, retry_interval: Duration, ) -> Self { Self { contract, nonce_count_rule, - gas_limit, + extra_gas, max_retries, retry_interval, block_submission_mutex: Arc::new(Mutex::new(())), @@ -237,7 +241,7 @@ async fn submit_block(web_state: &WebState, block: BlockWithMemos) -> Result surf::Client { let client: surf::Client = surf::Config::new() .set_base_url(Url::parse(&format!("http://localhost:{}", port)).unwrap()) @@ -707,7 +668,7 @@ mod test { let web_state = WebState::new( contract, NonceCountRule::Pending, - DEFAULT_RELAYER_GAS_LIMIT.parse().unwrap(), + DEFAULT_RELAYER_EXTRA_GAS.parse().unwrap(), DEFAULT_RELAYER_MAX_RETRIES.parse().unwrap(), Duration::from_millis(DEFAULT_RELAYER_RETRY_INTERVAL_MS.parse().unwrap()), ); From aa2b055e0f63402e880a7c326a2e5c4a00fc6709 Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 13:27:26 +0100 Subject: [PATCH 17/21] Remove unused import --- relayer/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/src/lib.rs b/relayer/src/lib.rs index 5cdcc2de..1a4d656a 100644 --- a/relayer/src/lib.rs +++ b/relayer/src/lib.rs @@ -438,7 +438,7 @@ pub mod testing { mod test { use super::*; use async_std::sync::{Arc, Mutex}; - use cap_rust_sandbox::assertion::{EnsureMined, EnsureRejected}; + use cap_rust_sandbox::assertion::EnsureMined; use cap_rust_sandbox::cape::RecordsMerkleTreeConstructorArgs; use cap_rust_sandbox::model::CAPE_MERKLE_HEIGHT; use cap_rust_sandbox::test_utils::upcast_test_cape_to_cape; From 6d585b11be9ed400f311037391ea1af6e5f4d043 Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 14:18:45 +0100 Subject: [PATCH 18/21] Abort early if transactions fail to mine --- contracts/rust/src/cape/events.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/rust/src/cape/events.rs b/contracts/rust/src/cape/events.rs index 4fc33349..7a850805 100644 --- a/contracts/rust/src/cape/events.rs +++ b/contracts/rust/src/cape/events.rs @@ -23,6 +23,7 @@ pub fn decode_cape_block_from_event(block: BlockCommittedFilter) -> Result().0) .send() .await? - .await?; + .await? + .ensure_mined(); // Adapted from seahorse // https://github.com/EspressoSystems/seahorse/blob/ace20bc5f1bcf5b88ca0562799b8e80e6c52e933/src/persistence.rs#L574 @@ -99,7 +101,8 @@ mod tests { GAS_LIMIT_OVERRIDE, // gas limit ) .await? - .await?; + .await? + .ensure_mined(); // A connection with a random wallet (for queries only) let query_connection = EthConnection::from_config_for_query( From e525a0a2919d24f1aa5e1f9d92796277b9bbc91a Mon Sep 17 00:00:00 2001 From: sveitser Date: Tue, 1 Nov 2022 15:58:47 +0100 Subject: [PATCH 19/21] Add 1M extra gas for tx that sometimes runs out --- contracts/rust/src/cape/events.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/rust/src/cape/events.rs b/contracts/rust/src/cape/events.rs index 7a850805..4e02c297 100644 --- a/contracts/rust/src/cape/events.rs +++ b/contracts/rust/src/cape/events.rs @@ -29,7 +29,7 @@ mod tests { submit_block::{fetch_cape_memos, submit_cape_block_with_memos}, BlockWithMemos, CapeBlock, }, - ethereum::{EthConnection, GAS_LIMIT_OVERRIDE}, + ethereum::EthConnection, ledger::CapeLedger, types::{GenericInto, MerkleRootSol}, }; @@ -98,7 +98,7 @@ mod tests { &connection.contract, block_with_memos.clone(), BlockNumber::Latest, - GAS_LIMIT_OVERRIDE, // gas limit + 1_000_000, // extra gas. This transaction sometimes runs out of gas, reason unclear. ) .await? .await? From bdace3725592dbb3dce81ec06ff44b24e26a82d8 Mon Sep 17 00:00:00 2001 From: sveitser Date: Wed, 2 Nov 2022 14:43:44 +0100 Subject: [PATCH 20/21] Remove debug print statements --- contracts/rust/src/cape/submit_block.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index e6936da4..b092be05 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -230,7 +230,6 @@ mod tests { .await? ); - println!("adding root"); // Set the root contract .add_root(root.generic_into::().0) @@ -239,7 +238,6 @@ mod tests { .await? .ensure_mined(); - println!("submit"); // Submit to the contract contract .submit_cape_block(cape_block.into()) From 3480fd8650fc9fd337399184b366787bd398a87b Mon Sep 17 00:00:00 2001 From: sveitser Date: Thu, 3 Nov 2022 16:31:54 +0100 Subject: [PATCH 21/21] Return errors instead of unwrapping --- contracts/rust/src/cape/submit_block.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contracts/rust/src/cape/submit_block.rs b/contracts/rust/src/cape/submit_block.rs index b092be05..be281f5c 100644 --- a/contracts/rust/src/cape/submit_block.rs +++ b/contracts/rust/src/cape/submit_block.rs @@ -14,6 +14,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ethers::prelude::signer::SignerMiddlewareError; use ethers::prelude::{BlockNumber, Provider, Wallet}; use ethers::prelude::{Bytes, Http, Middleware, PendingTransaction, TxHash}; +use ethers::providers::ProviderError; use ethers_core::k256::ecdsa::SigningKey; use super::{BlockMemos, BlockWithMemos}; @@ -102,9 +103,14 @@ pub async fn submit_cape_block_with_memos( .client() .get_block(BlockNumber::Latest) .await? - .unwrap(); + .ok_or_else(|| { + SignerMiddlewareError::MiddlewareError(ProviderError::CustomError( + "Did not receive a block".to_string(), + )) + })?; + tx.set_gas(std::cmp::min( - tx.gas().unwrap() + extra_gas, + tx.gas().ok_or(SignerMiddlewareError::GasMissing)? + extra_gas, block.gas_limit, ));