fix mergings
This commit is contained in:
parent
0ff8d6942c
commit
5752aa0260
|
@ -6,7 +6,7 @@ use ethers_core::{
|
||||||
utils::keccak256,
|
utils::keccak256,
|
||||||
};
|
};
|
||||||
use inflector::Inflector;
|
use inflector::Inflector;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::{Literal, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{spanned::Spanned, Data, DeriveInput, Error, Fields, LitInt, LitStr, Result, Token};
|
use syn::{spanned::Spanned, Data, DeriveInput, Error, Fields, LitInt, LitStr, Result, Token};
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ pub(crate) fn impl_derive_eip712(input: &DeriveInput) -> Result<TokenStream> {
|
||||||
// Instantiate domain from parsed attributes
|
// Instantiate domain from parsed attributes
|
||||||
let domain = parse_attributes(input)?;
|
let domain = parse_attributes(input)?;
|
||||||
|
|
||||||
let domain_separator = hex::encode(domain.separator());
|
let domain_separator = into_tokens(domain.separator());
|
||||||
|
|
||||||
let domain_str = serde_json::to_string(&domain).unwrap();
|
let domain_str = serde_json::to_string(&domain).unwrap();
|
||||||
|
|
||||||
|
@ -25,43 +25,38 @@ pub(crate) fn impl_derive_eip712(input: &DeriveInput) -> Result<TokenStream> {
|
||||||
let parsed_fields = parse_fields(input)?;
|
let parsed_fields = parse_fields(input)?;
|
||||||
|
|
||||||
// Compute the type hash for the derived struct using the parsed fields from above.
|
// Compute the type hash for the derived struct using the parsed fields from above.
|
||||||
let type_hash = hex::encode(make_type_hash(primary_type.to_string(), &parsed_fields));
|
let type_hash = into_tokens(make_type_hash(primary_type.to_string(), &parsed_fields));
|
||||||
|
|
||||||
// Use reference to ethers_core instead of directly using the crate itself.
|
// Use reference to ethers_core instead of directly using the crate itself.
|
||||||
let ethers_core = ethers_core_crate();
|
let ethers_core = ethers_core_crate();
|
||||||
|
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
impl Eip712 for #primary_type {
|
impl #ethers_core::types::transaction::eip712::Eip712 for #primary_type {
|
||||||
type Error = #ethers_core::types::transaction::eip712::Eip712Error;
|
type Error = #ethers_core::types::transaction::eip712::Eip712Error;
|
||||||
|
|
||||||
fn type_hash() -> Result<[u8; 32], Self::Error> {
|
#[inline]
|
||||||
use std::convert::TryFrom;
|
fn type_hash() -> ::core::result::Result<[u8; 32], Self::Error> {
|
||||||
let decoded = #ethers_core::utils::hex::decode(#type_hash)?;
|
Ok([#(#type_hash),*])
|
||||||
let byte_array: [u8; 32] = <[u8; 32]>::try_from(&decoded[..])?;
|
|
||||||
Ok(byte_array)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the pre-computed domain separator from compile time;
|
#[inline]
|
||||||
fn domain_separator(&self) -> Result<[u8; 32], Self::Error> {
|
fn domain_separator(&self) -> ::core::result::Result<[u8; 32], Self::Error> {
|
||||||
use std::convert::TryFrom;
|
Ok([#(#domain_separator),*])
|
||||||
let decoded = #ethers_core::utils::hex::decode(#domain_separator)?;
|
|
||||||
let byte_array: [u8; 32] = <[u8; 32]>::try_from(&decoded[..])?;
|
|
||||||
Ok(byte_array)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domain(&self) -> Result<#ethers_core::types::transaction::eip712::EIP712Domain, Self::Error> {
|
fn domain(&self) -> ::core::result::Result<#ethers_core::types::transaction::eip712::EIP712Domain, Self::Error> {
|
||||||
let domain: #ethers_core::types::transaction::eip712::EIP712Domain = # ethers_core::utils::__serde_json::from_str(#domain_str)?;
|
#ethers_core::utils::__serde_json::from_str(#domain_str).map_err(::core::convert::Into::into)
|
||||||
|
|
||||||
Ok(domain)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_hash(&self) -> Result<[u8; 32], Self::Error> {
|
fn struct_hash(&self) -> ::core::result::Result<[u8; 32], Self::Error> {
|
||||||
use #ethers_core::abi::Tokenizable;
|
|
||||||
let mut items = vec![#ethers_core::abi::Token::Uint(
|
let mut items = vec![#ethers_core::abi::Token::Uint(
|
||||||
#ethers_core::types::U256::from(&Self::type_hash()?[..]),
|
#ethers_core::types::U256::from(&Self::type_hash()?[..]),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
if let #ethers_core::abi::Token::Tuple(tokens) = self.clone().into_token() {
|
if let #ethers_core::abi::Token::Tuple(tokens) =
|
||||||
|
#ethers_core::abi::Tokenizable::into_token(::core::clone::Clone::clone(self))
|
||||||
|
{
|
||||||
|
items.reserve(tokens.len());
|
||||||
for token in tokens {
|
for token in tokens {
|
||||||
match &token {
|
match &token {
|
||||||
#ethers_core::abi::Token::Tuple(t) => {
|
#ethers_core::abi::Token::Tuple(t) => {
|
||||||
|
@ -163,10 +158,24 @@ fn parse_fields(input: &DeriveInput) -> Result<Vec<(String, ParamType)>> {
|
||||||
|
|
||||||
/// Convert hash map of field names and types into a type hash corresponding to enc types;
|
/// Convert hash map of field names and types into a type hash corresponding to enc types;
|
||||||
fn make_type_hash(primary_type: String, fields: &[(String, ParamType)]) -> [u8; 32] {
|
fn make_type_hash(primary_type: String, fields: &[(String, ParamType)]) -> [u8; 32] {
|
||||||
let parameters =
|
let mut sig = String::with_capacity(256);
|
||||||
fields.iter().map(|(k, v)| format!("{v} {k}")).collect::<Vec<String>>().join(",");
|
|
||||||
|
|
||||||
let sig = format!("{primary_type}({parameters})");
|
sig.push_str(&primary_type);
|
||||||
|
|
||||||
|
sig.push('(');
|
||||||
|
for (i, (name, ty)) in fields.iter().enumerate() {
|
||||||
|
sig.push_str(&ty.to_string());
|
||||||
|
sig.push(' ');
|
||||||
|
sig.push_str(name);
|
||||||
|
if i < fields.len() - 1 {
|
||||||
|
sig.push(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sig.push(')');
|
||||||
|
|
||||||
keccak256(sig)
|
keccak256(sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_tokens(bytes: [u8; 32]) -> impl Iterator<Item = Literal> {
|
||||||
|
bytes.into_iter().map(Literal::u8_suffixed)
|
||||||
|
}
|
||||||
|
|
|
@ -140,8 +140,11 @@ pub fn find_parameter_type(ty: &Type) -> Result<ParamType, Error> {
|
||||||
let ty = find_parameter_type(&arr.elem)?;
|
let ty = find_parameter_type(&arr.elem)?;
|
||||||
if let Expr::Lit(ref expr) = arr.len {
|
if let Expr::Lit(ref expr) = arr.len {
|
||||||
if let Lit::Int(ref len) = expr.lit {
|
if let Lit::Int(ref len) = expr.lit {
|
||||||
if let Ok(size) = len.base10_parse::<usize>() {
|
if let Ok(len) = len.base10_parse::<usize>() {
|
||||||
return Ok(ParamType::FixedArray(Box::new(ty), size))
|
return match (ty, len) {
|
||||||
|
(ParamType::Uint(8), 32) => Ok(ParamType::FixedBytes(32)),
|
||||||
|
(ty, len) => Ok(ParamType::FixedArray(Box::new(ty), len)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,10 @@ use ethers_contract::{
|
||||||
};
|
};
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
abi::{encode, AbiEncode, Token, Tokenizable},
|
abi::{encode, AbiEncode, Token, Tokenizable},
|
||||||
types::{Address, BlockId, Bytes, Filter, ValueOrArray, H160, H256, U256},
|
types::{
|
||||||
|
transaction::eip712::*, Address, BlockId, Bytes, Filter, ValueOrArray, H160, H256, I256,
|
||||||
|
U256,
|
||||||
|
},
|
||||||
utils::{keccak256, Anvil},
|
utils::{keccak256, Anvil},
|
||||||
};
|
};
|
||||||
use ethers_providers::{Http, Middleware, MiddlewareError, Provider, StreamExt, Ws};
|
use ethers_providers::{Http, Middleware, MiddlewareError, Provider, StreamExt, Ws};
|
||||||
|
@ -787,7 +790,7 @@ async fn test_derive_eip712() {
|
||||||
mod contract {
|
mod contract {
|
||||||
ethers_contract::abigen!(
|
ethers_contract::abigen!(
|
||||||
DeriveEip712Test,
|
DeriveEip712Test,
|
||||||
"./ethers-contract/tests/solidity-contracts/derive_eip712_abi.json",
|
"./ethers-contract/tests/solidity-contracts/DeriveEip712Test.json",
|
||||||
derives(serde::Deserialize, serde::Serialize)
|
derives(serde::Deserialize, serde::Serialize)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -811,33 +814,17 @@ async fn test_derive_eip712() {
|
||||||
out: Address,
|
out: Address,
|
||||||
}
|
}
|
||||||
|
|
||||||
// get ABI and bytecode for the DeriveEip712Test contract
|
|
||||||
let (abi, bytecode) = compile_contract("DeriveEip712Test", "DeriveEip712Test.sol");
|
|
||||||
|
|
||||||
// launch the network & connect to it
|
// launch the network & connect to it
|
||||||
let anvil = Anvil::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let from = anvil.addresses()[0];
|
let wallet: LocalWallet = anvil.keys()[0].clone().into();
|
||||||
let provider = Provider::try_from(anvil.endpoint())
|
let provider = Provider::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_sender(from)
|
.with_sender(wallet.address())
|
||||||
.interval(std::time::Duration::from_millis(10));
|
.interval(std::time::Duration::from_millis(10));
|
||||||
let client = Arc::new(provider);
|
let client = Arc::new(provider);
|
||||||
|
|
||||||
let wallet: LocalWallet = anvil.keys()[0].clone().into();
|
let contract: contract::DeriveEip712Test<_> =
|
||||||
|
contract::DeriveEip712Test::deploy(client.clone(), ()).unwrap().send().await.unwrap();
|
||||||
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 = contract::DeriveEip712Test::new(addr, client.clone());
|
|
||||||
|
|
||||||
let foo_bar = FooBar {
|
let foo_bar = FooBar {
|
||||||
foo: I256::from(10u64),
|
foo: I256::from(10u64),
|
||||||
|
@ -845,7 +832,7 @@ async fn test_derive_eip712() {
|
||||||
fizz: b"fizz".into(),
|
fizz: b"fizz".into(),
|
||||||
buzz: keccak256("buzz"),
|
buzz: keccak256("buzz"),
|
||||||
far: String::from("space"),
|
far: String::from("space"),
|
||||||
out: Address::from([0; 20]),
|
out: Address::zero(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let derived_foo_bar = contract::FooBar {
|
let derived_foo_bar = contract::FooBar {
|
||||||
|
@ -859,11 +846,11 @@ async fn test_derive_eip712() {
|
||||||
|
|
||||||
let sig = wallet.sign_typed_data(&foo_bar).await.expect("failed to sign typed data");
|
let sig = wallet.sign_typed_data(&foo_bar).await.expect("failed to sign typed data");
|
||||||
|
|
||||||
let r = <[u8; 32]>::try_from(sig.r)
|
let mut r = [0; 32];
|
||||||
.expect("failed to parse 'r' value from signature into [u8; 32]");
|
sig.r.to_big_endian(&mut r);
|
||||||
let s = <[u8; 32]>::try_from(sig.s)
|
let mut s = [0; 32];
|
||||||
.expect("failed to parse 's' value from signature into [u8; 32]");
|
sig.s.to_big_endian(&mut s);
|
||||||
let v = u8::try_from(sig.v).expect("failed to parse 'v' value from signature into u8");
|
let v = sig.v as u8;
|
||||||
|
|
||||||
let domain_separator = contract
|
let domain_separator = contract
|
||||||
.domain_separator()
|
.domain_separator()
|
||||||
|
|
|
@ -9,8 +9,8 @@ mod contract_call;
|
||||||
|
|
||||||
mod eip712;
|
mod eip712;
|
||||||
|
|
||||||
#[cfg(all(not(target_arch = "wasm32"), not(feature = "celo")))]
|
// #[cfg(all(not(target_arch = "wasm32"), not(feature = "celo")))]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[cfg(all(not(target_arch = "wasm32"), not(feature = "celo")))]
|
// #[cfg(all(not(target_arch = "wasm32"), not(feature = "celo")))]
|
||||||
mod contract;
|
mod contract;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2,6 +2,7 @@
|
||||||
pragma solidity >=0.6.0;
|
pragma solidity >=0.6.0;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
// note that this file is not synced with DeriveEip712Test.json
|
||||||
contract DeriveEip712Test {
|
contract DeriveEip712Test {
|
||||||
uint256 constant chainId = 1;
|
uint256 constant chainId = 1;
|
||||||
bytes32 constant salt = keccak256("eip712-test-75F0CCte");
|
bytes32 constant salt = keccak256("eip712-test-75F0CCte");
|
|
@ -1,206 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"inputs": [],
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "constructor"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inputs": [],
|
|
||||||
"name": "domainSeparator",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "",
|
|
||||||
"type": "bytes32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stateMutability": "pure",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"components": [
|
|
||||||
{
|
|
||||||
"internalType": "int256",
|
|
||||||
"name": "foo",
|
|
||||||
"type": "int256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "uint256",
|
|
||||||
"name": "bar",
|
|
||||||
"type": "uint256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes",
|
|
||||||
"name": "fizz",
|
|
||||||
"type": "bytes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "buzz",
|
|
||||||
"type": "bytes32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "string",
|
|
||||||
"name": "far",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "address",
|
|
||||||
"name": "out",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"internalType": "struct DeriveEip712Test.FooBar",
|
|
||||||
"name": "fooBar",
|
|
||||||
"type": "tuple"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "encodeEip712",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "",
|
|
||||||
"type": "bytes32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stateMutability": "pure",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"components": [
|
|
||||||
{
|
|
||||||
"internalType": "int256",
|
|
||||||
"name": "foo",
|
|
||||||
"type": "int256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "uint256",
|
|
||||||
"name": "bar",
|
|
||||||
"type": "uint256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes",
|
|
||||||
"name": "fizz",
|
|
||||||
"type": "bytes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "buzz",
|
|
||||||
"type": "bytes32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "string",
|
|
||||||
"name": "far",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "address",
|
|
||||||
"name": "out",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"internalType": "struct DeriveEip712Test.FooBar",
|
|
||||||
"name": "fooBar",
|
|
||||||
"type": "tuple"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "structHash",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "",
|
|
||||||
"type": "bytes32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stateMutability": "pure",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inputs": [],
|
|
||||||
"name": "typeHash",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "",
|
|
||||||
"type": "bytes32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stateMutability": "pure",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"internalType": "address",
|
|
||||||
"name": "signer",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"components": [
|
|
||||||
{
|
|
||||||
"internalType": "int256",
|
|
||||||
"name": "foo",
|
|
||||||
"type": "int256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "uint256",
|
|
||||||
"name": "bar",
|
|
||||||
"type": "uint256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes",
|
|
||||||
"name": "fizz",
|
|
||||||
"type": "bytes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "buzz",
|
|
||||||
"type": "bytes32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "string",
|
|
||||||
"name": "far",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "address",
|
|
||||||
"name": "out",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"internalType": "struct DeriveEip712Test.FooBar",
|
|
||||||
"name": "fooBar",
|
|
||||||
"type": "tuple"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "r",
|
|
||||||
"type": "bytes32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "s",
|
|
||||||
"type": "bytes32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "uint8",
|
|
||||||
"name": "v",
|
|
||||||
"type": "uint8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "verifyFooBar",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"internalType": "bool",
|
|
||||||
"name": "",
|
|
||||||
"type": "bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stateMutability": "pure",
|
|
||||||
"type": "function"
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,158 +0,0 @@
|
||||||
use ethers::{
|
|
||||||
contract::{abigen, ContractFactory, Eip712, EthAbiType},
|
|
||||||
core::{
|
|
||||||
types::{transaction::eip712::Eip712, Address, Bytes, I256, U256},
|
|
||||||
utils::{keccak256, Anvil},
|
|
||||||
},
|
|
||||||
providers::Provider,
|
|
||||||
signers::LocalWallet,
|
|
||||||
solc::Solc,
|
|
||||||
};
|
|
||||||
use std::{path::PathBuf, sync::Arc};
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
|
||||||
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");
|
|
||||||
Solc::find_or_install_svm_version("0.6.0").unwrap(); // install solc
|
|
||||||
let result = 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!");
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
//! Ethers integration tests.
|
|
||||||
#![cfg(not(target_arch = "wasm32"))]
|
|
||||||
|
|
||||||
mod eip712;
|
|
Loading…
Reference in New Issue