Skip to content

Commit

Permalink
fix(e2e): properly check errors match (#110)
Browse files Browse the repository at this point in the history
Follow-up work to #80 

We were previously just checking that an error's signature was contained
in the JSON-RPC response, but now we check the revert data fully.

Also polished the API.
  • Loading branch information
alexfertel authored Jun 7, 2024
1 parent 58a7163 commit 2f98bef
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 66 deletions.
16 changes: 9 additions & 7 deletions examples/erc721/tests/erc721.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

use alloy::{
primitives::{Address, U256},
rpc::types::eth::TransactionReceipt,
sol,
sol_types::SolConstructor,
};
use e2e::{receipt, send, watch, Assert, Emits, User};
use e2e::{receipt, send, watch, ErrorExt, EventExt, User};

use crate::abi::Erc721;

Expand Down Expand Up @@ -68,9 +67,10 @@ async fn errors_when_reusing_token_id(alice: User) -> eyre::Result<()> {
let alice_addr = alice.address();
let token_id = random_token_id();
let _ = watch!(contract.mint(alice_addr, token_id))?;

let err = send!(contract.mint(alice_addr, token_id))
.expect_err("should not mint a token id twice");
err.assert(Erc721::ERC721InvalidSender { sender: Address::ZERO });
assert!(err.is(Erc721::ERC721InvalidSender { sender: Address::ZERO }));
Ok(())
}

Expand All @@ -84,7 +84,7 @@ async fn transfers(alice: User, bob: User) -> eyre::Result<()> {
let token_id = random_token_id();
let _ = watch!(contract.mint(alice_addr, token_id).from(alice_addr))?;

let receipt: TransactionReceipt = receipt!(contract
let receipt = receipt!(contract
.transferFrom(alice_addr, bob_addr, token_id)
.from(alice_addr))?;

Expand Down Expand Up @@ -113,8 +113,9 @@ async fn errors_when_transfer_nonexistent_token(
let tx = contract
.transferFrom(alice_addr, bob.address(), token_id)
.from(alice_addr);

let err = send!(tx).expect_err("should not transfer a non-existent token");
err.assert(Erc721::ERC721NonexistentToken { tokenId: token_id });
assert!(err.is(Erc721::ERC721NonexistentToken { tokenId: token_id }));
Ok(())
}

Expand Down Expand Up @@ -156,10 +157,11 @@ async fn errors_when_transfer_unapproved_token(
let contract = Erc721::new(contract_addr, &bob.signer);
let tx =
contract.transferFrom(alice_addr, bob_addr, token_id).from(bob_addr);

let err = send!(tx).expect_err("should not transfer unapproved token");
err.assert(Erc721::ERC721InsufficientApproval {
assert!(err.is(Erc721::ERC721InsufficientApproval {
operator: bob_addr,
tokenId: token_id,
});
}));
Ok(())
}
57 changes: 0 additions & 57 deletions lib/e2e/src/assertions.rs

This file was deleted.

23 changes: 23 additions & 0 deletions lib/e2e/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use alloy::{contract::Error, sol_types::SolError};

pub trait ErrorExt<E> {
/// Checks that `Self` corresponds to the typed abi-encoded error
/// `expected`.
fn is(&self, expected: E) -> bool;
}

impl<E: SolError> ErrorExt<E> for Error {
fn is(&self, expected: E) -> bool {
let Self::TransportError(e) = self else {
return false;
};

let raw_value = e
.as_error_resp()
.and_then(|payload| payload.data.clone())
.expect("should extract the error");
let actual = &raw_value.get().trim_matches('"')[2..];
let expected = alloy::hex::encode(expected.abi_encode());
return expected == actual;
}
}
26 changes: 26 additions & 0 deletions lib/e2e/src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use alloy::{rpc::types::eth::TransactionReceipt, sol_types::SolEvent};

pub trait EventExt<E> {
/// Asserts the contract emitted the `expected` event.
fn emits(&self, expected: E);
}

impl<E> EventExt<E> for TransactionReceipt
where
E: SolEvent,
E: PartialEq,
E: std::fmt::Debug,
{
fn emits(&self, expected: E) {
// Extract all events that are the expected type.
let emitted = self
.inner
.logs()
.iter()
.filter_map(|log| log.log_decode().ok())
.map(|log| log.inner.data)
.any(|event| expected == event);

assert!(emitted, "Event {:?} not emitted", expected);
}
}
6 changes: 4 additions & 2 deletions lib/e2e/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
mod assertions;
mod deploy;
mod environment;
mod error;
mod event;
mod project;
mod system;
mod user;

pub use assertions::{Assert, Emits};
pub use deploy::deploy;
pub use e2e_proc::test;
pub use error::ErrorExt;
pub use event::EventExt;
pub use system::{provider, Provider, Signer};
pub use user::User;

Expand Down

0 comments on commit 2f98bef

Please sign in to comment.