cfx_types/
contract_address.rs

1use super::{
2    Address, AddressSpaceUtil, AddressUtil, AddressWithSpace, Space, H256, U256,
3};
4use keccak_hash::keccak;
5use rlp::RlpStream;
6
7/// Specifies how an address is calculated for a new contract.
8#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
9pub enum CreateContractAddressType {
10    /// Address is calculated from sender and nonce. Ethereum
11    /// `create` scheme.
12    FromSenderNonce,
13    /// Address is calculated from sender, nonce, and code hash. Conflux
14    /// `create` scheme.
15    FromSenderNonceAndCodeHash,
16    /// Address is calculated from block_hash, sender, nonce and code_hash.
17    /// Potential new Conflux `create` scheme when kill_dust is enabled.
18    FromBlockNumberSenderNonceAndCodeHash,
19    /// Address is calculated from sender, salt and code hash. Conflux and
20    /// Ethereum `create2` scheme.
21    FromSenderSaltAndCodeHash(H256),
22}
23
24/// Calculate new contract address.
25pub fn cal_contract_address(
26    address_scheme: CreateContractAddressType, sender: &Address, nonce: &U256,
27    code: &[u8],
28) -> (Address, H256) {
29    let code_hash = keccak(code);
30    let (address, code_hash) = match address_scheme {
31        CreateContractAddressType::FromSenderNonce => {
32            let mut rlp = RlpStream::new_list(2);
33            rlp.append(sender);
34            rlp.append(nonce);
35            let h = Address::from(keccak(rlp.as_raw()));
36            (h, code_hash)
37        }
38        CreateContractAddressType::FromBlockNumberSenderNonceAndCodeHash => {
39            unreachable!("Inactive setting");
40            // let mut buffer = [0u8; 1 + 8 + 20 + 32 + 32];
41            // let (lead_bytes, rest) = buffer.split_at_mut(1);
42            // let (block_number_bytes, rest) = rest.split_at_mut(8);
43            // let (sender_bytes, rest) =
44            // rest.split_at_mut(Address::len_bytes());
45            // let (nonce_bytes, code_hash_bytes) =
46            //     rest.split_at_mut(H256::len_bytes());
47            // // In Conflux, we take block_number and CodeHash into address
48            // // calculation. This is required to enable us to clean
49            // // up unused user account in future.
50            // lead_bytes[0] = 0x0;
51            // block_number.to_little_endian(block_number_bytes);
52            // sender_bytes.copy_from_slice(&sender.address[..]);
53            // nonce.to_little_endian(nonce_bytes);
54            // code_hash_bytes.copy_from_slice(&code_hash[..]);
55            // // In Conflux, we use the first four bits to indicate the type of
56            // // the address. For contract address, the bits will be
57            // // set to 0x8.
58            // let mut h = Address::from(keccak(&buffer[..]));
59            // h.set_contract_type_bits();
60            // (h, code_hash)
61        }
62        CreateContractAddressType::FromSenderNonceAndCodeHash => {
63            let mut buffer = [0u8; 1 + 20 + 32 + 32];
64            // In Conflux, we append CodeHash to determine the address as well.
65            // This is required to enable us to clean up unused user account in
66            // future.
67            buffer[0] = 0x0;
68            buffer[1..(1 + 20)].copy_from_slice(&sender[..]);
69            nonce.to_little_endian(&mut buffer[(1 + 20)..(1 + 20 + 32)]);
70            buffer[(1 + 20 + 32)..].copy_from_slice(&code_hash[..]);
71            // In Conflux, we use the first four bits to indicate the type of
72            // the address. For contract address, the bits will be
73            // set to 0x8.
74            let h = Address::from(keccak(&buffer[..]));
75            (h, code_hash)
76        }
77        CreateContractAddressType::FromSenderSaltAndCodeHash(salt) => {
78            let mut buffer = [0u8; 1 + 20 + 32 + 32];
79            buffer[0] = 0xff;
80            buffer[1..(1 + 20)].copy_from_slice(&sender[..]);
81            buffer[(1 + 20)..(1 + 20 + 32)].copy_from_slice(&salt[..]);
82            buffer[(1 + 20 + 32)..].copy_from_slice(&code_hash[..]);
83            // In Conflux, we use the first bit to indicate the type of the
84            // address. For contract address, the bits will be set to 0x8.
85            let h = Address::from(keccak(&buffer[..]));
86            (h, code_hash)
87        }
88    };
89    return (address, code_hash);
90}
91
92pub fn cal_contract_address_with_space(
93    address_scheme: CreateContractAddressType, sender: &AddressWithSpace,
94    nonce: &U256, code: &[u8],
95) -> (AddressWithSpace, H256) {
96    let (mut address, code_hash) =
97        cal_contract_address(address_scheme, &sender.address, nonce, code);
98    if sender.space == Space::Native {
99        address.set_contract_type_bits();
100    }
101    (address.with_space(sender.space), code_hash)
102}