Skip to content

ref: use Stylus Erc1155ReceiverMock in E2E tests #766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ members = [
"examples/uups-proxy",
"examples/erc721-holder",
"examples/erc1155-holder",
"examples/erc1155-receiver-mock",
]
default-members = [
"contracts",
Expand Down Expand Up @@ -71,6 +72,7 @@ default-members = [
"examples/uups-proxy",
"examples/erc721-holder",
"examples/erc1155-holder",
"examples/erc1155-receiver-mock",
]
exclude = ["fuzz"]

Expand Down
31 changes: 31 additions & 0 deletions examples/erc1155-receiver-mock/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "erc1155-receiver-mock-example"
edition.workspace = true
license.workspace = true
repository.workspace = true
publish = false
version.workspace = true

[dependencies]
openzeppelin-stylus.workspace = true
alloy-primitives.workspace = true
alloy-sol-macro.workspace = true
alloy-sol-types.workspace = true
stylus-sdk.workspace = true

[dev-dependencies]
alloy.workspace = true
e2e.workspace = true
tokio.workspace = true
eyre.workspace = true

[features]
e2e = []
export-abi = ["openzeppelin-stylus/export-abi"]

[lib]
crate-type = ["lib", "cdylib"]

[[bin]]
name = "erc1155-receiver-mock-example"
path = "src/main.rs"
187 changes: 187 additions & 0 deletions examples/erc1155-receiver-mock/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#![cfg_attr(not(any(test, feature = "export-abi")), no_main)]
extern crate alloc;

use alloc::vec::Vec;

use openzeppelin_stylus::{
token::erc1155::{
receiver::{
IErc1155Receiver, BATCH_TRANSFER_FN_SELECTOR,
SINGLE_TRANSFER_FN_SELECTOR,
},
utils::Erc1155Holder,
},
utils::introspection::erc165::IErc165,
};
pub use sol::*;
use stylus_sdk::{
abi::Bytes,
alloy_primitives::{
aliases::{B32, U8},
Address, U256,
},
evm,
prelude::*,
storage::StorageU8,
};

mod sol {
use alloy_sol_macro::sol;
sol! {
#[derive(Debug)]
#[allow(missing_docs)]
event Received(address operator, address from, uint256 id, uint256 value, bytes data);

#[derive(Debug)]
#[allow(missing_docs)]
event BatchReceived(address operator, address from, uint256[] ids, uint256[] values, bytes data);
}

sol! {
#[derive(Debug)]
#[allow(missing_docs)]
error CustomError(bytes4 data);
}
}

#[derive(SolidityError, Debug)]
pub enum Error {
MockCustomError(CustomError),
}

/// Enum representing different revert types for testing.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RevertType {
None,
CustomError,
Panic,
}

impl From<u8> for RevertType {
fn from(value: u8) -> Self {
match value {
1 => RevertType::CustomError,
2 => RevertType::Panic,
_ => RevertType::None,
}
}
}

impl From<U8> for RevertType {
fn from(value: U8) -> Self {
let revert_type: u8 = u8::try_from(value).expect("should be valid");
revert_type.into()
}
}

impl From<RevertType> for u8 {
fn from(value: RevertType) -> Self {
match value {
RevertType::None => 0,
RevertType::CustomError => 1,
RevertType::Panic => 2,
}
}
}

#[entrypoint]
#[storage]
struct Erc1155ReceiverMock {
error_type: StorageU8,
holder: Erc1155Holder,
}

#[public]
#[implements(IErc1155Receiver, IErc165)]
impl Erc1155ReceiverMock {
#[constructor]
fn constructor(&mut self, error_type: U8) {
self.error_type.set(error_type)
}
}

#[public]
impl IErc1155Receiver for Erc1155ReceiverMock {
#[selector(name = "onERC1155Received")]
fn on_erc1155_received(
&mut self,
operator: Address,
from: Address,
id: U256,
value: U256,
data: Bytes,
) -> Result<B32, Vec<u8>> {
let error_type: RevertType = self.error_type.get().into();

match error_type {
RevertType::CustomError => {
Err(Error::MockCustomError(CustomError {
data: SINGLE_TRANSFER_FN_SELECTOR,
})
.into())
}
RevertType::Panic => {
// simulate a panic by dividing by [`U256::ZERO`].
let _ = U256::from(0) / U256::from(0);
unreachable!()
}
RevertType::None => {
#[allow(deprecated)]
evm::log(Received {
operator,
from,
id,
value,
data: data.to_vec().into(),
});
self.holder.on_erc1155_received(operator, from, id, value, data)
}
}
}

#[selector(name = "onERC1155BatchReceived")]
fn on_erc1155_batch_received(
&mut self,
operator: Address,
from: Address,
ids: Vec<U256>,
values: Vec<U256>,
data: Bytes,
) -> Result<B32, Vec<u8>> {
let error_type: RevertType = self.error_type.get().into();

match error_type {
RevertType::CustomError => {
Err(Error::MockCustomError(CustomError {
data: BATCH_TRANSFER_FN_SELECTOR,
})
.into())
}
RevertType::Panic => {
// simulate a panic by dividing by [`U256::ZERO`].
let _ = U256::from(0) / U256::from(0);
unreachable!()
}
RevertType::None => {
#[allow(deprecated)]
evm::log(BatchReceived {
operator,
from,
ids: ids.clone(),
values: values.clone(),
data: data.to_vec().into(),
});
self.holder.on_erc1155_batch_received(
operator, from, ids, values, data,
)
}
}
}
}

#[public]
impl IErc165 for Erc1155ReceiverMock {
fn supports_interface(&self, interface_id: B32) -> bool {
self.holder.supports_interface(interface_id)
}
}
10 changes: 10 additions & 0 deletions examples/erc1155-receiver-mock/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![cfg_attr(not(any(test, feature = "export-abi")), no_main)]

#[cfg(not(any(test, feature = "export-abi")))]
#[no_mangle]
pub extern "C" fn main() {}

#[cfg(feature = "export-abi")]
fn main() {
erc1155_receiver_mock_example::print_from_args();
}
30 changes: 30 additions & 0 deletions examples/erc1155-receiver-mock/tests/abi/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#![allow(dead_code)]
use alloy::sol;

sol!(
#[sol(rpc)]
contract Erc1155ReceiverMock {
#[derive(Debug)]
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);

#[derive(Debug)]
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);

function supportsInterface(bytes4 interface_id) external view returns (bool supportsInterface);

#[derive(Debug, PartialEq)]
error CustomError(bytes4 data);
}
);
Loading
Loading