Add selector collisions to the IERC20 lib

This commit is contained in:
Luke Parker
2025-01-23 08:22:41 -05:00
parent 7e53eff642
commit e922264ebf
4 changed files with 47 additions and 4 deletions

View File

@@ -18,3 +18,17 @@ interface IERC20 {
function approve(address spender, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256);
} }
interface SeraiIERC20 {
function transferWithInInstruction01BB244A8A(
address to,
uint256 value,
bytes calldata inInstruction
) external returns (bool);
function transferFromWithInInstruction00081948E0(
address from,
address to,
uint256 value,
bytes calldata inInstruction
) external returns (bool);
}

View File

@@ -28,8 +28,15 @@ mod abi {
alloy_sol_macro::sol!("contracts/IERC20.sol"); alloy_sol_macro::sol!("contracts/IERC20.sol");
} }
use abi::IERC20::{IERC20Calls, transferCall, transferFromCall}; use abi::IERC20::{IERC20Calls, transferCall, transferFromCall};
use abi::SeraiIERC20::{
SeraiIERC20Calls, transferWithInInstruction01BB244A8ACall as transferWithInInstructionCall,
transferFromWithInInstruction00081948E0Call as transferFromWithInInstructionCall,
};
pub use abi::IERC20::Transfer; pub use abi::IERC20::Transfer;
#[cfg(test)]
mod tests;
/// A top-level ERC20 transfer /// A top-level ERC20 transfer
/// ///
/// This does not include `token`, `to` fields. Those are assumed contextual to the creation of /// This does not include `token`, `to` fields. Those are assumed contextual to the creation of
@@ -139,8 +146,18 @@ impl Erc20 {
} }
// Read the data appended after // Read the data appended after
let encoded = call.abi_encode(); let data = if let Ok(call) = SeraiIERC20Calls::abi_decode(transaction.inner.input(), true) {
let data = transaction.inner.input().as_ref()[encoded.len() ..].to_vec(); match call {
SeraiIERC20Calls::transferWithInInstruction01BB244A8A(
transferWithInInstructionCall { inInstruction, .. },
) |
SeraiIERC20Calls::transferFromWithInInstruction00081948E0(
transferFromWithInInstructionCall { inInstruction, .. },
) => Vec::from(inInstruction),
}
} else {
vec![]
};
return Ok(Some(TopLevelTransfer { return Ok(Some(TopLevelTransfer {
id: LogIndex { block_hash: *block_hash, index_within_block: log_index }, id: LogIndex { block_hash: *block_hash, index_within_block: log_index },

View File

@@ -0,0 +1,13 @@
use alloy_sol_types::SolCall;
#[test]
fn selector_collisions() {
assert_eq!(
crate::abi::IERC20::transferCall::SELECTOR,
crate::abi::SeraiIERC20::transferWithInInstruction01BB244A8ACall::SELECTOR
);
assert_eq!(
crate::abi::IERC20::transferFromCall::SELECTOR,
crate::abi::SeraiIERC20::transferFromWithInInstruction00081948E0Call::SELECTOR
);
}

View File

@@ -29,8 +29,7 @@ contract Router is IRouterWithoutCollisions {
bytes32 constant ACCOUNT_WITHOUT_CODE_CODEHASH = keccak256(""); bytes32 constant ACCOUNT_WITHOUT_CODE_CODEHASH = keccak256("");
/// @dev The address in transient storage used for the reentrancy guard /// @dev The address in transient storage used for the reentrancy guard
bytes32 constant REENTRANCY_GUARD_SLOT = bytes32 constant REENTRANCY_GUARD_SLOT = bytes32(uint256(keccak256("ReentrancyGuard Router")) - 1);
bytes32(uint256(keccak256("ReentrancyGuard Router")) - 1);
/** /**
* @dev The next nonce used to determine the address of contracts deployed with CREATE. This is * @dev The next nonce used to determine the address of contracts deployed with CREATE. This is