diff --git a/ethers-core/src/utils/mod.rs b/ethers-core/src/utils/mod.rs index b93a7715..189535c5 100644 --- a/ethers-core/src/utils/mod.rs +++ b/ethers-core/src/utils/mod.rs @@ -117,10 +117,23 @@ pub fn get_contract_address(sender: impl Into
, nonce: impl Into) Address::from(bytes) } -/// Returns the CREATE2 of a smart contract as specified in +/// Returns the CREATE2 address of a smart contract as specified in /// [EIP1014](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md) /// /// keccak256( 0xff ++ senderAddress ++ salt ++ keccak256(init_code))[12..] +pub fn get_create2_address( + from: impl Into
, + salt: impl Into, + init_code: impl Into, +) -> Address { + get_create2_address_from_hash(from, salt, keccak256(init_code.into().as_ref()).to_vec()) +} + +/// Returns the CREATE2 address of a smart contract as specified in +/// [EIP1014](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md), +/// taking the pre-computed hash of the init code as input. +/// +/// keccak256( 0xff ++ senderAddress ++ salt ++ keccak256(init_code))[12..] /// /// # Example /// @@ -131,13 +144,12 @@ pub fn get_contract_address(sender: impl Into
, nonce: impl Into) /// abi, /// abi::Token, /// types::{Address, Bytes, U256}, -/// utils::{get_create2_address, keccak256}, +/// utils::{get_create2_address_from_hash, keccak256}, /// }; /// -/// // We substitute some arbitrary short init code for brevity. The real -/// // pool init code can be found under "Contract Creation Code" on etherscan: -/// // https://etherscan.io/address/0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640/advanced#code -/// let UNISWAP_V3_POOL_INIT_CODE = Bytes::from(hex::decode("610160604052").unwrap()); +/// let UNISWAP_V3_POOL_INIT_CODE_HASH = Bytes::from( +/// hex::decode("e34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54").unwrap(), +/// ); /// let factory: Address = "0x1F98431c8aD98523631AE4a59f267346ea31F984" /// .parse() /// .unwrap(); @@ -149,6 +161,7 @@ pub fn get_contract_address(sender: impl Into
, nonce: impl Into) /// .unwrap(); /// let fee = 500; /// +/// // abi.encode(token0 as address, token1 as address, fee as uint256) /// let input = abi::encode(&vec![ /// Token::Address(token0), /// Token::Address(token1), @@ -157,27 +170,26 @@ pub fn get_contract_address(sender: impl Into
, nonce: impl Into) /// /// // keccak256(abi.encode(token0, token1, fee)) /// let salt = keccak256(&input); -/// let pool_address = get_create2_address(factory, salt.to_vec(), UNISWAP_V3_POOL_INIT_CODE); +/// let pool_address = +/// get_create2_address_from_hash(factory, salt.to_vec(), UNISWAP_V3_POOL_INIT_CODE_HASH); /// -/// // Actual USDC/ETH pool address (created with proper init code): -/// // 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 /// assert_eq!( /// pool_address, -/// "0x43953f76983c3ee678bb7a23b4e9eb813d6508b4" +/// "0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640" // USDC/ETH pool address /// .parse() /// .unwrap() /// ); /// ``` -pub fn get_create2_address( +pub fn get_create2_address_from_hash( from: impl Into
, salt: impl Into, - init_code: impl Into, + init_code_hash: impl Into, ) -> Address { let bytes = [ &[0xff], from.into().as_bytes(), salt.into().as_ref(), - &keccak256(init_code.into().as_ref()), + init_code_hash.into().as_ref(), ] .concat(); @@ -532,11 +544,16 @@ mod tests { "E33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0", ), ] { + // get_create2_address() let from = from.parse::
().unwrap(); let salt = hex::decode(salt).unwrap(); let init_code = hex::decode(init_code).unwrap(); let expected = expected.parse::
().unwrap(); - assert_eq!(expected, get_create2_address(from, salt, init_code)) + assert_eq!(expected, get_create2_address(from, salt.clone(), init_code.clone())); + + // get_create2_address_from_hash() + let init_code_hash = keccak256(init_code).to_vec(); + assert_eq!(expected, get_create2_address_from_hash(from, salt, init_code_hash)) } }