use alloy_primitives::{Address, Bytes, U256};
use alloy_sol_types::{SolCall, sol};
use crate::Call;
sol! {
interface IERC20 {
function approve(address spender, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount) external returns (bool);
}
}
pub fn approve(token: Address, spender: Address, amount: U256) -> Call {
let data = Bytes::from(IERC20::approveCall { spender, amount }.abi_encode());
Call::builder().to(token).data(data).build()
}
pub fn transfer(token: Address, recipient: Address, amount: U256) -> Call {
let data = Bytes::from(IERC20::transferCall { recipient, amount }.abi_encode());
Call::builder().to(token).data(data).build()
}
#[cfg(test)]
mod tests {
use alloy_primitives::{Bytes, U256, address};
use super::*;
const APPROVE_TOKEN: Address = address!("1111111111111111111111111111111111111111");
const APPROVE_SPENDER: Address = address!("2222222222222222222222222222222222222222");
const APPROVE_AMOUNT: u64 = 42;
const APPROVE_EXPECTED: &str = "095ea7b30000000000000000000000002222222222222222222222222222222222222222000000000000000000000000000000000000000000000000000000000000002a";
const TRANSFER_TOKEN: Address = address!("3333333333333333333333333333333333333333");
const TRANSFER_RECIPIENT: Address = address!("4444444444444444444444444444444444444444");
const TRANSFER_AMOUNT: u64 = 7;
const TRANSFER_EXPECTED: &str = "a9059cbb00000000000000000000000044444444444444444444444444444444444444440000000000000000000000000000000000000000000000000000000000000007";
const VALID_CALLDATA_FIXTURE: &str = "valid calldata fixture";
#[test]
fn approve_encodes_expected_calldata() {
let token = APPROVE_TOKEN;
let spender = APPROVE_SPENDER;
let amount = U256::from(APPROVE_AMOUNT);
let expected = bytes(APPROVE_EXPECTED);
let call = approve(token, spender, amount);
assert_eq!(call.to(), token);
assert_eq!(call.value(), U256::ZERO);
assert_eq!(call.data(), &expected);
}
#[test]
fn transfer_encodes_expected_calldata() {
let token = TRANSFER_TOKEN;
let recipient = TRANSFER_RECIPIENT;
let amount = U256::from(TRANSFER_AMOUNT);
let expected = bytes(TRANSFER_EXPECTED);
let call = transfer(token, recipient, amount);
assert_eq!(call.to(), token);
assert_eq!(call.value(), U256::ZERO);
assert_eq!(call.data(), &expected);
}
fn bytes(hex: &str) -> Bytes {
let decoded = alloy_primitives::hex::decode(hex).expect(VALID_CALLDATA_FIXTURE);
Bytes::from(decoded)
}
}