@@ -3,71 +3,75 @@ use pallet_evm::{
3
3
BalanceConverter , ExitError , ExitSucceed , PrecompileFailure , PrecompileHandle ,
4
4
PrecompileOutput , PrecompileResult ,
5
5
} ;
6
+ use precompile_utils:: prelude:: RuntimeHelper ;
6
7
use sp_core:: U256 ;
7
8
use sp_runtime:: traits:: { Dispatchable , UniqueSaturatedInto } ;
8
9
use sp_std:: vec;
9
10
10
- use crate :: { Runtime , RuntimeCall } ;
11
-
12
11
use crate :: precompiles:: { bytes_to_account_id, get_method_id, get_slice} ;
12
+ use crate :: { Runtime , RuntimeCall } ;
13
13
14
14
pub const BALANCE_TRANSFER_INDEX : u64 = 2048 ;
15
15
16
+ // This is a hardcoded hashed address mapping of 0x0000000000000000000000000000000000000800 to an
17
+ // ss58 public key i.e., the contract sends funds it received to the destination address from the
18
+ // method parameter.
19
+ const CONTRACT_ADDRESS_SS58 : [ u8 ; 32 ] = [
20
+ 0x07 , 0xec , 0x71 , 0x2a , 0x5d , 0x38 , 0x43 , 0x4d , 0xdd , 0x03 , 0x3f , 0x8f , 0x02 , 0x4e , 0xcd , 0xfc ,
21
+ 0x4b , 0xb5 , 0x95 , 0x1c , 0x13 , 0xc3 , 0x08 , 0x5c , 0x39 , 0x9c , 0x8a , 0x5f , 0x62 , 0x93 , 0x70 , 0x5d ,
22
+ ] ;
23
+
16
24
pub struct BalanceTransferPrecompile ;
17
25
18
26
impl BalanceTransferPrecompile {
19
27
pub fn execute ( handle : & mut impl PrecompileHandle ) -> PrecompileResult {
20
28
let txdata = handle. input ( ) ;
21
29
22
30
// Match method ID: keccak256("transfer(bytes32)")
23
- let method: & [ u8 ] = get_slice ( txdata, 0 , 4 ) ?;
24
- if get_method_id ( "transfer(bytes32)" ) == method {
25
- // Forward all received value to the destination address
26
- let amount: U256 = handle. context ( ) . apparent_value ;
31
+ let method = get_slice ( txdata, 0 , 4 ) ?;
32
+ if get_method_id ( "transfer(bytes32)" ) != method {
33
+ return Ok ( PrecompileOutput {
34
+ exit_status : ExitSucceed :: Returned ,
35
+ output : vec ! [ ] ,
36
+ } ) ;
37
+ }
27
38
28
- // Use BalanceConverter to convert EVM amount to Substrate balance
29
- let amount_sub =
30
- <Runtime as pallet_evm:: Config >:: BalanceConverter :: into_substrate_balance ( amount)
31
- . ok_or ( ExitError :: OutOfFund ) ?;
39
+ // Forward all received value to the destination address
40
+ let amount: U256 = handle. context ( ) . apparent_value ;
32
41
33
- if amount_sub. is_zero ( ) {
34
- return Ok ( PrecompileOutput {
35
- exit_status : ExitSucceed :: Returned ,
36
- output : vec ! [ ] ,
37
- } ) ;
38
- }
42
+ // Use BalanceConverter to convert EVM amount to Substrate balance
43
+ let amount_sub =
44
+ <Runtime as pallet_evm:: Config >:: BalanceConverter :: into_substrate_balance ( amount)
45
+ . ok_or ( ExitError :: OutOfFund ) ?;
39
46
40
- // This is a hardcoded hashed address mapping of
41
- // 0x0000000000000000000000000000000000000800 to an ss58 public key
42
- // i.e., the contract sends funds it received to the destination address
43
- // from the method parameter.
44
- const ADDRESS_BYTES_SRC : [ u8 ; 32 ] = [
45
- 0x07 , 0xec , 0x71 , 0x2a , 0x5d , 0x38 , 0x43 , 0x4d , 0xdd , 0x03 , 0x3f , 0x8f , 0x02 , 0x4e ,
46
- 0xcd , 0xfc , 0x4b , 0xb5 , 0x95 , 0x1c , 0x13 , 0xc3 , 0x08 , 0x5c , 0x39 , 0x9c , 0x8a , 0x5f ,
47
- 0x62 , 0x93 , 0x70 , 0x5d ,
48
- ] ;
49
- let address_bytes_dst: & [ u8 ] = get_slice ( txdata, 4 , 36 ) ?;
50
- let account_id_src = bytes_to_account_id ( & ADDRESS_BYTES_SRC ) ?;
51
- let account_id_dst = bytes_to_account_id ( address_bytes_dst) ?;
47
+ if amount_sub. is_zero ( ) {
48
+ return Ok ( PrecompileOutput {
49
+ exit_status : ExitSucceed :: Returned ,
50
+ output : vec ! [ ] ,
51
+ } ) ;
52
+ }
52
53
53
- let call =
54
- RuntimeCall :: Balances ( pallet_balances:: Call :: < Runtime > :: transfer_allow_death {
55
- dest : account_id_dst. into ( ) ,
56
- value : amount_sub. unique_saturated_into ( ) ,
57
- } ) ;
54
+ let address_bytes_dst = get_slice ( txdata, 4 , 36 ) ?;
55
+ let account_id_src = bytes_to_account_id ( & CONTRACT_ADDRESS_SS58 ) ?;
56
+ let account_id_dst = bytes_to_account_id ( address_bytes_dst) ?;
58
57
59
- // Dispatch the call
60
- let result = call. dispatch ( RawOrigin :: Signed ( account_id_src) . into ( ) ) ;
61
- if result. is_err ( ) {
62
- return Err ( PrecompileFailure :: Error {
63
- exit_status : ExitError :: OutOfFund ,
64
- } ) ;
65
- }
66
- }
58
+ let call = RuntimeCall :: Balances ( pallet_balances:: Call :: < Runtime > :: transfer_allow_death {
59
+ dest : account_id_dst. into ( ) ,
60
+ value : amount_sub. unique_saturated_into ( ) ,
61
+ } ) ;
67
62
68
- Ok ( PrecompileOutput {
63
+ // Dispatch the call
64
+ RuntimeHelper :: < Runtime > :: try_dispatch (
65
+ handle,
66
+ RawOrigin :: Signed ( account_id_src) . into ( ) ,
67
+ call,
68
+ )
69
+ . map ( |_| PrecompileOutput {
69
70
exit_status : ExitSucceed :: Returned ,
70
71
output : vec ! [ ] ,
71
72
} )
73
+ . map_err ( |_| PrecompileFailure :: Error {
74
+ exit_status : ExitError :: OutOfFund ,
75
+ } )
72
76
}
73
77
}
0 commit comments