cfx_types/
contract_address.rs

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