cfx_executor/internal_contract/contracts/
cross_space.rs

1// Copyright 2021 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use 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            /* admin */ &Address::zero(),
260            /* balance */ 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}