test: move over eip712 test from ethers-contract

This commit is contained in:
Georgios Konstantopoulos 2023-03-21 11:05:51 -07:00
parent 3286469b38
commit 464ae1458a
6 changed files with 173 additions and 26 deletions

1
Cargo.lock generated
View File

@ -1219,6 +1219,7 @@ dependencies = [
"ethers-providers",
"ethers-signers",
"ethers-solc",
"serde",
"tokio",
]

View File

@ -26,14 +26,7 @@ all-features = true
[features]
default = ["abigen", "rustls"]
celo = [
"ethers-core/celo",
"ethers-providers/celo",
"ethers-signers/celo",
"ethers-contract/celo",
"ethers-middleware/celo",
"legacy",
]
celo = ["ethers-core/celo", "ethers-providers/celo", "ethers-signers/celo", "ethers-contract/celo", "ethers-middleware/celo", "legacy"]
legacy = ["ethers-core/legacy", "ethers-contract/legacy"]
@ -43,20 +36,8 @@ eip712 = ["ethers-contract/eip712", "ethers-core/eip712"]
## providers
ws = ["ethers-providers/ws"]
ipc = ["ethers-providers/ipc"]
rustls = [
"ethers-middleware/rustls",
"ethers-providers/rustls",
"ethers-etherscan/rustls",
"ethers-contract/rustls",
"ethers-solc/rustls",
]
openssl = [
"ethers-middleware/openssl",
"ethers-providers/openssl",
"ethers-etherscan/openssl",
"ethers-contract/openssl",
"ethers-solc/openssl",
]
rustls = ["ethers-middleware/rustls", "ethers-providers/rustls", "ethers-etherscan/rustls", "ethers-contract/rustls", "ethers-solc/rustls"]
openssl = ["ethers-middleware/openssl", "ethers-providers/openssl", "ethers-etherscan/openssl", "ethers-contract/openssl", "ethers-solc/openssl"]
dev-rpc = ["ethers-providers/dev-rpc"]
## signers
ledger = ["ethers-signers/ledger"]
@ -86,4 +67,6 @@ ethers-signers.workspace = true
ethers-solc = { workspace = true, optional = true }
[dev-dependencies]
serde.workspace = true
tokio = { workspace = true, features = ["macros", "rt"] }
ethers-contract = { workspace = true, features = ["eip712"] }

View File

@ -1,7 +1,8 @@
use crate::simple_storage::SimpleStorage;
use ethers::prelude::*;
use std::{sync::Arc, time::Duration};
ethers::contract::abigen!(SimpleStorage, "../testdata/SimpleStorage.json");
static CELO_TESTNET_URL: &str = "https://alfajores-forno.celo-testnet.org";
#[tokio::test]

164
ethers/tests/eip712.rs Normal file
View File

@ -0,0 +1,164 @@
use ethers::{
contract::{
abigen, ContractFactory, ContractInstance, Eip712, EthAbiType, EthEvent, LogMeta,
Multicall, MulticallError, MulticallVersion,
},
core::{
abi::{encode, AbiEncode, Token, Tokenizable},
types::{
transaction::eip712::Eip712, Address, BlockId, Bytes, Filter, ValueOrArray, H160, H256,
I256, U256,
},
utils::{keccak256, Anvil},
},
providers::{Http, Middleware, MiddlewareError, Provider, StreamExt},
signers::LocalWallet,
};
use ethers_solc::CompilerInput;
use std::{path::PathBuf, sync::Arc};
#[tokio::test]
async fn test_derive_eip712() {
// Generate Contract ABI Bindings
abigen!(
DeriveEip712Test,
"./ethers-contract/tests/solidity-contracts/derive_eip712_abi.json",
event_derives(serde::Deserialize, serde::Serialize)
);
// Create derived structs
#[derive(Debug, Clone, Eip712, EthAbiType)]
#[eip712(
name = "Eip712Test",
version = "1",
chain_id = 1,
verifying_contract = "0x0000000000000000000000000000000000000001",
salt = "eip712-test-75F0CCte"
)]
struct FooBar {
foo: I256,
bar: U256,
fizz: Bytes,
buzz: [u8; 32],
far: String,
out: Address,
}
// get ABI and bytecode for the DeriveEip712Test contract
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests");
let result = ethers::solc::Solc::default().compile_source(path).unwrap();
let (abi, bytecode, _) = result
.find("DeriveEip712Test")
.expect("failed to get DeriveEip712Test contract")
.into_parts_or_default();
// launch the network & connect to it
let anvil = Anvil::new().spawn();
let from = anvil.addresses()[0];
let provider = Provider::try_from(anvil.endpoint())
.unwrap()
.with_sender(from)
.interval(std::time::Duration::from_millis(10));
let client = Arc::new(provider);
let factory = ContractFactory::new(abi.clone(), bytecode.clone(), client.clone());
let contract = factory
.deploy(())
.expect("failed to deploy DeriveEip712Test contract")
.legacy()
.send()
.await
.expect("failed to instantiate factory for DeriveEip712 contract");
let addr = contract.address();
let contract = DeriveEip712Test::new(addr, client.clone());
let foo_bar = FooBar {
foo: I256::from(10u64),
bar: U256::from(20u64),
fizz: b"fizz".into(),
buzz: keccak256("buzz"),
far: String::from("space"),
out: Address::from([0; 20]),
};
let derived_foo_bar = derive_eip_712_test::FooBar {
foo: foo_bar.foo,
bar: foo_bar.bar,
fizz: foo_bar.fizz.clone(),
buzz: foo_bar.buzz,
far: foo_bar.far.clone(),
out: foo_bar.out,
};
use ethers::signers::Signer;
let wallet: LocalWallet = anvil.keys()[0].clone().into();
let sig = wallet.sign_typed_data(&foo_bar).await.expect("failed to sign typed data");
let r = <[u8; 32]>::try_from(sig.r)
.expect("failed to parse 'r' value from signature into [u8; 32]");
let s = <[u8; 32]>::try_from(sig.s)
.expect("failed to parse 's' value from signature into [u8; 32]");
let v = u8::try_from(sig.v).expect("failed to parse 'v' value from signature into u8");
let domain_separator = contract
.domain_separator()
.call()
.await
.expect("failed to retrieve domain_separator from contract");
let type_hash =
contract.type_hash().call().await.expect("failed to retrieve type_hash from contract");
let struct_hash = contract
.struct_hash(derived_foo_bar.clone())
.call()
.await
.expect("failed to retrieve struct_hash from contract");
let encoded = contract
.encode_eip_712(derived_foo_bar.clone())
.call()
.await
.expect("failed to retrieve eip712 encoded hash from contract");
let verify = contract
.verify_foo_bar(wallet.address(), derived_foo_bar, r, s, v)
.call()
.await
.expect("failed to verify signed typed data eip712 payload");
assert_eq!(
domain_separator,
foo_bar
.domain()
.expect("failed to return domain_separator from Eip712 implemented struct")
.separator(),
"domain separator does not match contract domain separator!"
);
assert_eq!(
type_hash,
FooBar::type_hash().expect("failed to return type_hash from Eip712 implemented struct"),
"type hash does not match contract struct type hash!"
);
assert_eq!(
struct_hash,
foo_bar
.clone()
.struct_hash()
.expect("failed to return struct_hash from Eip712 implemented struct"),
"struct hash does not match contract struct hash!"
);
assert_eq!(
encoded,
foo_bar
.encode_eip712()
.expect("failed to return domain_separator from Eip712 implemented struct"),
"Encoded value does not match!"
);
assert!(verify, "typed data signature failed!");
}

View File

@ -4,6 +4,4 @@
#[cfg(feature = "celo")]
mod celo;
pub(crate) mod simple_storage {
ethers::contract::abigen!(SimpleStorage, "../testdata/SimpleStorage.json");
}
mod eip712;