1use std::marker::PhantomData;
6
7use cfx_parameters::internal_contract_addresses::CROSS_SPACE_CONTRACT_ADDRESS;
8use cfx_types::{Address, AddressSpaceUtil, AddressWithSpace, H160, U256};
9use primitives::storage::STORAGE_LAYOUT_REGULAR_V0;
10
11use cfx_vm_types::CallType;
12
13use super::{super::impls::cross_space::*, preludes::*};
14
15type Bytes = Vec<u8>;
16type Bytes20 = [u8; 20];
17
18make_solidity_contract! {
19 pub struct CrossSpaceCall(CROSS_SPACE_CONTRACT_ADDRESS, generate_fn_table, initialize: |params: &CommonParams| params.transition_numbers.cip90b, is_active: |spec: &Spec| spec.cip90);
20}
21
22fn generate_fn_table() -> SolFnTable {
23 make_function_table!(
24 CreateToEVM,
25 TransferToEVM,
26 CallToEVM,
27 StaticCallToEVM,
28 Withdraw,
29 MappedBalance,
30 MappedNonce,
31 DeployEip1820
32 )
33}
34
35group_impl_is_active!(
36 |spec: &Spec| spec.cip90,
37 CreateToEVM,
38 TransferToEVM,
39 CallToEVM,
40 StaticCallToEVM,
41 Withdraw,
42 MappedBalance,
43 MappedNonce,
44 DeployEip1820,
45);
46
47make_solidity_event! {
48 pub struct CallEvent("Call(bytes20,bytes20,uint256,uint256,bytes)", indexed: (Bytes20, Bytes20), non_indexed: (U256, U256, Bytes));
49}
50
51make_solidity_event! {
52 pub struct CreateEvent("Create(bytes20,bytes20,uint256,uint256,bytes)", indexed: (Bytes20, Bytes20), non_indexed: (U256, U256, Bytes));
53}
54
55make_solidity_event! {
56 pub struct WithdrawEvent("Withdraw(bytes20,address,uint256,uint256)", indexed: (Bytes20, Address), non_indexed: (U256,U256));
57}
58
59make_solidity_event! {
60 pub struct ReturnEvent("Outcome(bool)", indexed: (), non_indexed: bool);
61}
62
63pub mod events {
64 pub use super::{CallEvent, CreateEvent, ReturnEvent, WithdrawEvent};
65}
66
67make_solidity_function! {
68 pub struct CreateToEVM(Bytes, "createEVM(bytes)", Bytes20);
69}
70
71impl_function_type!(CreateToEVM, "payable_write");
72
73impl UpfrontPaymentTrait for CreateToEVM {
74 fn upfront_gas_payment(
75 &self, init: &Bytes, _params: &ActionParams,
76 context: &InternalRefContext,
77 ) -> DbResult<U256> {
78 create_gas(context, init.as_ref())
79 }
80}
81
82impl ExecutionTrait for CreateToEVM {
83 fn execute_inner(
84 &self, init: Bytes, params: &ActionParams, gas_left: U256,
85 context: &mut InternalRefContext,
86 ) -> InternalTrapResult<Bytes20> {
87 let trap = create_to_evmcore(init, None, params, gas_left, context);
88 process_trap(trap, PhantomData)
89 }
90}
91
92make_solidity_function! {
93 pub struct TransferToEVM(Bytes20, "transferEVM(bytes20)", Bytes);
94}
95
96impl_function_type!(TransferToEVM, "payable_write");
97
98impl UpfrontPaymentTrait for TransferToEVM {
99 fn upfront_gas_payment(
100 &self, receiver: &Bytes20, params: &ActionParams,
101 context: &InternalRefContext,
102 ) -> DbResult<U256> {
103 call_gas(H160(*receiver), params, context, &vec![])
104 }
105}
106
107impl ExecutionTrait for TransferToEVM {
108 fn execute_inner(
109 &self, to: Bytes20, params: &ActionParams, gas_left: U256,
110 context: &mut InternalRefContext,
111 ) -> InternalTrapResult<Bytes> {
112 let trap = call_to_evmcore(
113 H160(to),
114 vec![],
115 CallType::Call,
116 params,
117 gas_left,
118 context,
119 );
120 process_trap(trap, PhantomData)
121 }
122}
123
124make_solidity_function! {
125 pub struct CallToEVM((Bytes20,Bytes), "callEVM(bytes20,bytes)", Bytes);
126}
127
128impl_function_type!(CallToEVM, "payable_write");
129
130impl UpfrontPaymentTrait for CallToEVM {
131 fn upfront_gas_payment(
132 &self, (ref receiver, ref data): &(Bytes20, Bytes),
133 params: &ActionParams, context: &InternalRefContext,
134 ) -> DbResult<U256> {
135 call_gas(H160(*receiver), params, context, data)
136 }
137}
138
139impl ExecutionTrait for CallToEVM {
140 fn execute_inner(
141 &self, (to, data): (Bytes20, Bytes), params: &ActionParams,
142 gas_left: U256, context: &mut InternalRefContext,
143 ) -> InternalTrapResult<Bytes> {
144 let trap = call_to_evmcore(
145 H160(to),
146 data,
147 CallType::Call,
148 params,
149 gas_left,
150 context,
151 );
152 process_trap(trap, PhantomData)
153 }
154}
155
156make_solidity_function! {
157 struct StaticCallToEVM((Bytes20,Bytes), "staticCallEVM(bytes20,bytes)", Bytes);
158}
159
160impl_function_type!(StaticCallToEVM, "query");
161
162impl UpfrontPaymentTrait for StaticCallToEVM {
163 fn upfront_gas_payment(
164 &self, _: &(Bytes20, Bytes), _params: &ActionParams,
165 context: &InternalRefContext,
166 ) -> DbResult<U256> {
167 Ok(static_call_gas(context.spec))
168 }
169}
170
171impl ExecutionTrait for StaticCallToEVM {
172 fn execute_inner(
173 &self, (to, data): (Bytes20, Bytes), params: &ActionParams,
174 gas_left: U256, context: &mut InternalRefContext,
175 ) -> InternalTrapResult<Bytes> {
176 let trap = call_to_evmcore(
177 H160(to),
178 data,
179 CallType::StaticCall,
180 params,
181 gas_left,
182 context,
183 );
184 process_trap(trap, PhantomData)
185 }
186}
187
188make_solidity_function! {
189 pub struct Withdraw(U256, "withdrawFromMapped(uint256)");
190}
191
192impl_function_type!(Withdraw, "non_payable_write");
193
194impl UpfrontPaymentTrait for Withdraw {
195 fn upfront_gas_payment(
196 &self, _: &U256, _params: &ActionParams, context: &InternalRefContext,
197 ) -> DbResult<U256> {
198 Ok(withdraw_gas(context.spec))
199 }
200}
201
202impl SimpleExecutionTrait for Withdraw {
203 fn execute_inner(
204 &self, value: U256, params: &ActionParams,
205 context: &mut InternalRefContext,
206 ) -> vm::Result<()> {
207 withdraw_from_evmcore(params.sender, value, params, context)
208 }
209}
210
211make_solidity_function! {
212 struct MappedBalance(Address, "mappedBalance(address)", U256);
213}
214
215impl_function_type!(MappedBalance, "query", gas: |spec: &Spec| spec.balance_gas + spec.sha3_gas);
216
217impl SimpleExecutionTrait for MappedBalance {
218 fn execute_inner(
219 &self, addr: Address, _params: &ActionParams,
220 context: &mut InternalRefContext,
221 ) -> vm::Result<U256> {
222 mapped_balance(addr, context)
223 }
224}
225
226make_solidity_function! {
227 struct MappedNonce(Address, "mappedNonce(address)", U256);
228}
229
230impl_function_type!(MappedNonce, "query", gas: |spec: &Spec| spec.balance_gas + spec.sha3_gas);
231
232impl SimpleExecutionTrait for MappedNonce {
233 fn execute_inner(
234 &self, addr: Address, _params: &ActionParams,
235 context: &mut InternalRefContext,
236 ) -> vm::Result<U256> {
237 mapped_nonce(addr, context)
238 }
239}
240
241make_solidity_function! {
242 struct DeployEip1820((), "deployEip1820()");
243}
244
245impl_function_type!(DeployEip1820, "non_payable_write", gas: |spec:&Spec| spec.eip1820_gas);
246
247impl SimpleExecutionTrait for DeployEip1820 {
248 fn execute_inner(
249 &self, _: (), _params: &ActionParams, context: &mut InternalRefContext,
250 ) -> vm::Result<()> {
251 let address: AddressWithSpace = eip_1820::ADDRESS.with_evm_space();
252 if context.state.is_contract_with_code(&address)? {
253 return Err(vm::Error::InternalContract(
254 "eip-1820 contract has been deployed.".to_string(),
255 ));
256 }
257 context.state.new_contract_with_admin(
258 &address,
259 &Address::zero(),
260 U256::zero(),
261 Some(STORAGE_LAYOUT_REGULAR_V0),
262 context.spec.cip107,
263 )?;
264 context.state.init_code(
265 &address,
266 eip_1820::BYTE_CODE.clone(),
267 Address::zero(),
268 context.env.transaction_hash,
269 )?;
270 context.substate.record_contract_create(address);
271 Ok(())
272 }
273}
274
275pub fn is_call_create_sig(data: &[u8]) -> bool {
276 data == TransferToEVM::FUNC_SIG
277 || data == CreateToEVM::FUNC_SIG
278 || data == CallToEVM::FUNC_SIG
279}
280
281pub fn is_withdraw_sig(data: &[u8]) -> bool { data == Withdraw::FUNC_SIG }
282
283#[test]
284fn test_cross_space_contract_sig() {
285 check_func_signature!(CreateToEVM, "ff311601");
286 check_func_signature!(TransferToEVM, "da8d5daf");
287 check_func_signature!(CallToEVM, "bea05ee3");
288 check_func_signature!(StaticCallToEVM, "30b4ef7d");
289 check_func_signature!(Withdraw, "c23ef031");
290 check_func_signature!(MappedBalance, "142b37c7");
291 check_func_signature!(MappedNonce, "b5914944");
292 check_func_signature!(DeployEip1820, "36201722");
293
294 check_event_signature!(
295 CallEvent,
296 "124d1efd3ac32fa6aadb7a06e066c113471e0411fb56a5079cedbc3cdf7796e4"
297 );
298 check_event_signature!(
299 CreateEvent,
300 "d4f6dc315981682d51417b7092f1a151bfc6ebc3f637532f97ac479b86c4076d"
301 );
302 check_event_signature!(
303 WithdrawEvent,
304 "31328e08abcc622b23d8be96d45b371b10e42989dafc8ac56c85b33bb3584b92"
305 );
306 check_event_signature!(
307 ReturnEvent,
308 "bc11eabb6efd378a0a489b58a574c6e0d0403060e8a8c7b8eab45db47900edfe"
309 );
310}
311
312mod eip_1820 {
313 pub use rustc_hex::FromHex;
314
315 use super::Address;
316
317 const HEX_ADDRESS: &'static str =
318 "1820a4b7618bde71dce8cdc73aab6c95905fad24";
319 const HEX_BYTE_CODE: &'static str = "608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063a41e7d5111610078578063a41e7d51146101d4578063aabbb8ca1461020a578063b705676514610236578063f712f3e814610280576100a5565b806329965a1d146100aa5780633d584063146100e25780635df8122f1461012457806365ba36c114610152575b600080fd5b6100e0600480360360608110156100c057600080fd5b50600160a060020a038135811691602081013591604090910135166102b6565b005b610108600480360360208110156100f857600080fd5b5035600160a060020a0316610570565b60408051600160a060020a039092168252519081900360200190f35b6100e06004803603604081101561013a57600080fd5b50600160a060020a03813581169160200135166105bc565b6101c26004803603602081101561016857600080fd5b81019060208101813564010000000081111561018357600080fd5b82018360208201111561019557600080fd5b803590602001918460018302840111640100000000831117156101b757600080fd5b5090925090506106b3565b60408051918252519081900360200190f35b6100e0600480360360408110156101ea57600080fd5b508035600160a060020a03169060200135600160e060020a0319166106ee565b6101086004803603604081101561022057600080fd5b50600160a060020a038135169060200135610778565b61026c6004803603604081101561024c57600080fd5b508035600160a060020a03169060200135600160e060020a0319166107ef565b604080519115158252519081900360200190f35b61026c6004803603604081101561029657600080fd5b508035600160a060020a03169060200135600160e060020a0319166108aa565b6000600160a060020a038416156102cd57836102cf565b335b9050336102db82610570565b600160a060020a031614610339576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b6103428361092a565b15610397576040805160e560020a62461bcd02815260206004820152601a60248201527f4d757374206e6f7420626520616e204552433136352068617368000000000000604482015290519081900360640190fd5b600160a060020a038216158015906103b85750600160a060020a0382163314155b156104ff5760405160200180807f455243313832305f4143434550545f4d4147494300000000000000000000000081525060140190506040516020818303038152906040528051906020012082600160a060020a031663249cb3fa85846040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083815260200182600160a060020a0316600160a060020a031681526020019250505060206040518083038186803b15801561047e57600080fd5b505afa158015610492573d6000803e3d6000fd5b505050506040513d60208110156104a857600080fd5b5051146104ff576040805160e560020a62461bcd02815260206004820181905260248201527f446f6573206e6f7420696d706c656d656e742074686520696e74657266616365604482015290519081900360640190fd5b600160a060020a03818116600081815260208181526040808320888452909152808220805473ffffffffffffffffffffffffffffffffffffffff19169487169485179055518692917f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db15391a450505050565b600160a060020a03818116600090815260016020526040812054909116151561059a5750806105b7565b50600160a060020a03808216600090815260016020526040902054165b919050565b336105c683610570565b600160a060020a031614610624576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b81600160a060020a031681600160a060020a0316146106435780610646565b60005b600160a060020a03838116600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169585169590951790945592519184169290917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43509190a35050565b600082826040516020018083838082843780830192505050925050506040516020818303038152906040528051906020012090505b92915050565b6106f882826107ef565b610703576000610705565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b600080600160a060020a038416156107905783610792565b335b905061079d8361092a565b156107c357826107ad82826108aa565b6107b85760006107ba565b815b925050506106e8565b600160a060020a0390811660009081526020818152604080832086845290915290205416905092915050565b6000808061081d857f01ffc9a70000000000000000000000000000000000000000000000000000000061094c565b909250905081158061082d575080155b1561083d576000925050506106e8565b61084f85600160e060020a031961094c565b909250905081158061086057508015155b15610870576000925050506106e8565b61087a858561094c565b909250905060018214801561088f5750806001145b1561089f576001925050506106e8565b506000949350505050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff1615156108f2576108eb83836107ef565b90506106e8565b50600160a060020a03808316600081815260208181526040808320600160e060020a0319871684529091529020549091161492915050565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6040517f01ffc9a7000000000000000000000000000000000000000000000000000000008082526004820183905260009182919060208160248189617530fa90519096909550935050505056fea165627a7a72305820377f4a2d4301ede9949f163f319021a6e9c687c292a5e2b2c4734c126b524e6c0029";
320
321 lazy_static! {
322 pub static ref ADDRESS: Address = HEX_ADDRESS.parse().unwrap();
323 pub static ref BYTE_CODE: Vec<u8> = HEX_BYTE_CODE.from_hex().unwrap();
324 }
325}