matter-labs / era-test-node

In-memory node that can be used for integration testing and debugging.
https://matter-labs.github.io/era-test-node
Apache License 2.0
310 stars 75 forks source link

[FEAT] Add examples of using era-test-node with alloy #300

Open mm-zk opened 3 weeks ago

mm-zk commented 3 weeks ago

🌟 Feature Request

📝 Description

Alloy is the replacement for ethers.rs - and we should make sure that it is nicely integrated with era-test-node.

Make sure that we expose the rich wallets, and that transactions confirmations work correctly.

Rationale

We had reports that code below doesn't work well:

sol!(
    #[sol(rpc)]
    Counter,
    "out/Counter.sol/Counter.json"
);

async fn call_contract(rpc_url: &str, wallet_pk: &str, contract_addr: &str) -> Result<()> {
    // We assume that anvil/era-test-node are running externally and we've deployed the contract there.
    let wallet = EthereumWallet::new(PrivateKeySigner::from_str(wallet_pk)?);
    let provider = ProviderBuilder::new()
        .with_recommended_fillers()
        .wallet(wallet)
        .on_http(rpc_url.parse()?);

    let counter = Counter::new(contract_addr.parse()?, provider);
    let tx_hash = counter
        .setNumber(U256::from(42))
        .send()
        .await?
        .watch()
        .await?;
    println!("Tx hash is {tx_hash}");

    let number = counter.number().call().await?._0.to_string();
    println!("Number is {number}");

    Ok(())
}
MexicanAce commented 3 weeks ago

(remark): I guess the bug in the test node is here, probably we should not use Defult::default() to unconditionally fill the remaining fields.

Posting from other notes

MexicanAce commented 3 weeks ago

The concern here is that if it works with anvil, I’d expect it to work with era-test-node. Also above I’ve wrote that I specifically tried with .with_required_confirmations(0) — still didn’t work.

It could be some issue with alloy, I’m not sure, but again — it works with anvil just fine.

Added another internal note here

vbar commented 3 weeks ago
let tx_hash = counter
        .setNumber(U256::from(42))
        .send()
        .await?
        .watch()
        .await?;

does hang, apparently inside watch, but isn't that to be expected, given that watch "waits for the transaction to confirm with the given number of confirmations"? Shouldn't the code be

let receipt = counter
        .setNumber(U256::from(42))
        .send()
        .await?
        .get_receipt()
        .await?;
vbar commented 2 weeks ago

So, for a complete example: Counter.sol can be placed into the e2e-tests/contracts directory of https://github.com/matter-labs/era-test-node/ , which enables its compilation and deployment by depl.ts (placed in the e2e-tests directory) by the npx hardhat run depl.ts command. For this command to succeed, Era test node of course has to be running on the same machine. The deployment script outputs the contract address:

e2e-tests$ npx hardhat run depl.ts
deployed Counter at 0x111C3E89Ce80e62EE88318C2804920D4c96f92bb
result BigNumber { _hex: '0x00', _isBigNumber: true }

main.rs can be used as the only source file of a new Rust project - except the out/Counter.sol/Counter.json file, which can be copied from e2e-tests/artifacts-zk/contracts/Counter.sol directory. Running the program requires 2 command-line arguments: a private key of a rich wallet, and the deployed contract address:

Tx hash is 0x38fa20d8ccbe37725c335fc38fdecfe90860479273678c1c563f4d6e56bfd311
Number is 42

example.zip

popzxc commented 1 week ago

@vbar watch by default waits for no confirmations, e.g. just for block to be mined, but it turned out to be a bug in alloy. I've fixed it, so now watch should work.