core: add utils::get_create2_address_from_hash() (#444)
This commit is contained in:
parent
b54f8b7d45
commit
90df511704
|
@ -117,10 +117,23 @@ pub fn get_contract_address(sender: impl Into<Address>, nonce: impl Into<U256>)
|
||||||
Address::from(bytes)
|
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)
|
/// [EIP1014](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md)
|
||||||
///
|
///
|
||||||
/// keccak256( 0xff ++ senderAddress ++ salt ++ keccak256(init_code))[12..]
|
/// keccak256( 0xff ++ senderAddress ++ salt ++ keccak256(init_code))[12..]
|
||||||
|
pub fn get_create2_address(
|
||||||
|
from: impl Into<Address>,
|
||||||
|
salt: impl Into<Bytes>,
|
||||||
|
init_code: impl Into<Bytes>,
|
||||||
|
) -> 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
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -131,13 +144,12 @@ pub fn get_contract_address(sender: impl Into<Address>, nonce: impl Into<U256>)
|
||||||
/// abi,
|
/// abi,
|
||||||
/// abi::Token,
|
/// abi::Token,
|
||||||
/// types::{Address, Bytes, U256},
|
/// 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
|
/// let UNISWAP_V3_POOL_INIT_CODE_HASH = Bytes::from(
|
||||||
/// // pool init code can be found under "Contract Creation Code" on etherscan:
|
/// hex::decode("e34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54").unwrap(),
|
||||||
/// // https://etherscan.io/address/0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640/advanced#code
|
/// );
|
||||||
/// let UNISWAP_V3_POOL_INIT_CODE = Bytes::from(hex::decode("610160604052").unwrap());
|
|
||||||
/// let factory: Address = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
|
/// let factory: Address = "0x1F98431c8aD98523631AE4a59f267346ea31F984"
|
||||||
/// .parse()
|
/// .parse()
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
|
@ -149,6 +161,7 @@ pub fn get_contract_address(sender: impl Into<Address>, nonce: impl Into<U256>)
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
/// let fee = 500;
|
/// let fee = 500;
|
||||||
///
|
///
|
||||||
|
/// // abi.encode(token0 as address, token1 as address, fee as uint256)
|
||||||
/// let input = abi::encode(&vec![
|
/// let input = abi::encode(&vec![
|
||||||
/// Token::Address(token0),
|
/// Token::Address(token0),
|
||||||
/// Token::Address(token1),
|
/// Token::Address(token1),
|
||||||
|
@ -157,27 +170,26 @@ pub fn get_contract_address(sender: impl Into<Address>, nonce: impl Into<U256>)
|
||||||
///
|
///
|
||||||
/// // keccak256(abi.encode(token0, token1, fee))
|
/// // keccak256(abi.encode(token0, token1, fee))
|
||||||
/// let salt = keccak256(&input);
|
/// 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!(
|
/// assert_eq!(
|
||||||
/// pool_address,
|
/// pool_address,
|
||||||
/// "0x43953f76983c3ee678bb7a23b4e9eb813d6508b4"
|
/// "0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640" // USDC/ETH pool address
|
||||||
/// .parse()
|
/// .parse()
|
||||||
/// .unwrap()
|
/// .unwrap()
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get_create2_address(
|
pub fn get_create2_address_from_hash(
|
||||||
from: impl Into<Address>,
|
from: impl Into<Address>,
|
||||||
salt: impl Into<Bytes>,
|
salt: impl Into<Bytes>,
|
||||||
init_code: impl Into<Bytes>,
|
init_code_hash: impl Into<Bytes>,
|
||||||
) -> Address {
|
) -> Address {
|
||||||
let bytes = [
|
let bytes = [
|
||||||
&[0xff],
|
&[0xff],
|
||||||
from.into().as_bytes(),
|
from.into().as_bytes(),
|
||||||
salt.into().as_ref(),
|
salt.into().as_ref(),
|
||||||
&keccak256(init_code.into().as_ref()),
|
init_code_hash.into().as_ref(),
|
||||||
]
|
]
|
||||||
.concat();
|
.concat();
|
||||||
|
|
||||||
|
@ -532,11 +544,16 @@ mod tests {
|
||||||
"E33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0",
|
"E33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0",
|
||||||
),
|
),
|
||||||
] {
|
] {
|
||||||
|
// get_create2_address()
|
||||||
let from = from.parse::<Address>().unwrap();
|
let from = from.parse::<Address>().unwrap();
|
||||||
let salt = hex::decode(salt).unwrap();
|
let salt = hex::decode(salt).unwrap();
|
||||||
let init_code = hex::decode(init_code).unwrap();
|
let init_code = hex::decode(init_code).unwrap();
|
||||||
let expected = expected.parse::<Address>().unwrap();
|
let expected = expected.parse::<Address>().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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue