use crate::eips::eip2612::IERC2612;
use alloy_contract::private::{Network, Provider};
use alloy_dyn_abi::{PropertyDef, Resolver, TypeDef, TypedData};
use alloy_primitives::{Address, U256};
use alloy_sol_types::{Eip712Domain, sol};
sol!(
#[sol(rpc)]
interface IERC7597 {
function permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature) external;
}
);
pub struct EIP7597PermitMessage {
pub owner: Address,
pub spender: Address,
pub value: U256,
pub nonce: U256,
pub deadline: U256,
}
pub struct EIP7597;
impl EIP7597 {
pub async fn get_nonce<N: Network, P: Provider<N>>(
provider: P,
token: Address,
owner: Address,
) -> alloy_contract::Result<U256> {
let eip = IERC2612::new(token, provider);
eip.nonces(owner).call().await
}
pub fn permit_typed_data(
eip712_domain: Eip712Domain,
message: EIP7597PermitMessage,
) -> TypedData {
let mut types = Resolver::default();
types.ingest(TypeDef::new_unchecked(
"EIP712Domain".to_string(),
vec![
PropertyDef::new_unchecked("string", "name"),
PropertyDef::new_unchecked("string", "version"),
PropertyDef::new_unchecked("uint256", "chainId"),
PropertyDef::new_unchecked("address", "verifyingContract"),
],
));
types.ingest(TypeDef::new_unchecked(
"Permit".to_string(),
vec![
PropertyDef::new_unchecked("address", "owner"),
PropertyDef::new_unchecked("address", "spender"),
PropertyDef::new_unchecked("uint256", "value"),
PropertyDef::new_unchecked("uint256", "nonce"),
PropertyDef::new_unchecked("uint256", "deadline"),
],
));
let message = serde_json::json!({
"owner": message.owner,
"spender": message.spender,
"value": message.value,
"nonce": message.nonce,
"deadline": message.deadline,
});
TypedData {
domain: eip712_domain,
resolver: types,
primary_type: "Permit".to_string(),
message,
}
}
}