1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#![cfg_attr(feature = "external_doc", feature(external_doc))]
#![cfg_attr(feature = "external_doc", doc(include = "../README.md"))]
pub use vapory_types::{Address, H256, U256};
use tetsy_keccak_hash::keccak;
use tetsy_rlp::RlpStream;
use std::ops::Deref;
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct TetsyContractAddress(Address);
impl TetsyContractAddress {
pub fn from_sender_and_nonce(sender: &Address, nonce: &U256) -> Self {
let mut stream = RlpStream::new_list(2);
stream.append(sender);
stream.append(nonce);
TetsyContractAddress(Address::from(keccak(stream.as_raw())))
}
pub fn from_sender_salt_and_code(sender: &Address, salt: H256, code_hash: H256) -> Self {
let mut buffer = [0u8; 1 + 20 + 32 + 32];
buffer[0] = 0xff;
&mut buffer[1..(1 + 20)].copy_from_slice(&sender[..]);
&mut buffer[(1 + 20)..(1 + 20 + 32)].copy_from_slice(&salt[..]);
&mut buffer[(1 + 20 + 32)..].copy_from_slice(&code_hash[..]);
TetsyContractAddress(Address::from(keccak(&buffer[..])))
}
pub fn from_sender_and_code(sender: &Address, code_hash: H256) -> Self {
let mut buffer = [0u8; 20 + 32];
&mut buffer[..20].copy_from_slice(&sender[..]);
&mut buffer[20..].copy_from_slice(&code_hash[..]);
TetsyContractAddress(Address::from(keccak(&buffer[..])))
}
}
impl Deref for TetsyContractAddress {
type Target = Address;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<TetsyContractAddress> for Address {
fn from(tetsy_contract_address: TetsyContractAddress) -> Self {
tetsy_contract_address.0
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn test_from_sender_and_nonce() {
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let expected = Address::from_str("3f09c73a5ed19289fb9bdc72f1742566df146f56").unwrap();
let actual = TetsyContractAddress::from_sender_and_nonce(&sender, &U256::from(88));
assert_eq!(Address::from(actual), expected);
}
#[test]
fn test_from_sender_salt_and_code_hash() {
let sender = Address::zero();
let code_hash =
H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
.unwrap();
let expected_address =
Address::from_str("e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0").unwrap();
let tetsy_contract_address =
TetsyContractAddress::from_sender_salt_and_code(&sender, H256::zero(), code_hash);
assert_eq!(Address::from(tetsy_contract_address), expected_address);
}
#[test]
fn test_from_sender_and_code_hash() {
let sender = Address::from_str("0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d").unwrap();
let code_hash =
H256::from_str("d98f2e8134922f73748703c8e7084d42f13d2fa1439936ef5a3abcf5646fe83f")
.unwrap();
let expected_address =
Address::from_str("064417880f5680b141ed7fcac031aad40df080b0").unwrap();
let tetsy_contract_address = TetsyContractAddress::from_sender_and_code(&sender, code_hash);
assert_eq!(Address::from(tetsy_contract_address), expected_address);
}
}