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}