3
3
// Copyright © 2017 Trust Wallet.
4
4
5
5
use crate :: abi:: contract:: Contract ;
6
+ use crate :: abi:: param_token:: NamedToken ;
6
7
use crate :: abi:: param_type:: ParamType ;
7
8
use crate :: abi:: token:: Token ;
8
- use crate :: abi:: AbiResult ;
9
+ use crate :: abi:: { AbiError , AbiErrorKind , AbiResult } ;
9
10
use crate :: address:: Address ;
10
11
use lazy_static:: lazy_static;
12
+ use tw_coin_entry:: error:: prelude:: { OrTWError , ResultContext } ;
11
13
use tw_memory:: Data ;
12
14
use tw_number:: U256 ;
13
15
14
16
/// Generated via https://remix.ethereum.org
15
17
/// https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccount.sol
16
18
const ERC4337_SIMPLE_ACCOUNT_ABI : & str = include_str ! ( "resource/erc4337.simple_account.abi.json" ) ;
19
+ const ERC4337_BIZ_ACCOUNT_ABI : & str = include_str ! ( "resource/erc4337.biz_account.abi.json" ) ;
17
20
18
21
lazy_static ! {
19
22
static ref ERC4337_SIMPLE_ACCOUNT : Contract =
20
23
serde_json:: from_str( ERC4337_SIMPLE_ACCOUNT_ABI ) . unwrap( ) ;
24
+ static ref ERC4337_BIZ_ACCOUNT : Contract =
25
+ serde_json:: from_str( ERC4337_BIZ_ACCOUNT_ABI ) . unwrap( ) ;
21
26
}
22
27
23
28
pub struct ExecuteArgs {
@@ -38,6 +43,15 @@ impl Erc4337SimpleAccount {
38
43
] )
39
44
}
40
45
46
+ pub fn encode_execute_4337_op ( args : ExecuteArgs ) -> AbiResult < Data > {
47
+ let func = ERC4337_BIZ_ACCOUNT . function ( "execute4337Op" ) ?;
48
+ func. encode_input ( & [
49
+ Token :: Address ( args. to ) ,
50
+ Token :: u256 ( args. value ) ,
51
+ Token :: Bytes ( args. data ) ,
52
+ ] )
53
+ }
54
+
41
55
pub fn encode_execute_batch < I > ( args : I ) -> AbiResult < Data >
42
56
where
43
57
I : IntoIterator < Item = ExecuteArgs > ,
@@ -66,4 +80,62 @@ impl Erc4337SimpleAccount {
66
80
Token :: array ( ParamType :: Bytes , datas) ,
67
81
] )
68
82
}
83
+
84
+ pub fn encode_execute_4337_ops < I > ( args : I ) -> AbiResult < Data >
85
+ where
86
+ I : IntoIterator < Item = ExecuteArgs > ,
87
+ {
88
+ let func = ERC4337_BIZ_ACCOUNT . function ( "execute4337Ops" ) ?;
89
+
90
+ // `tuple[]`, where each item is a tuple of (address, uint256, bytes).
91
+ let array_param = func
92
+ . inputs
93
+ . first ( )
94
+ . or_tw_err ( AbiErrorKind :: Error_internal )
95
+ . context ( "'Biz.execute4337Ops()' should contain only one argument" ) ?;
96
+
97
+ let ParamType :: Array {
98
+ kind : array_elem_type,
99
+ } = array_param. kind . clone ( )
100
+ else {
101
+ return AbiError :: err ( AbiErrorKind :: Error_internal ) . with_context ( || {
102
+ format ! (
103
+ "'Biz.execute4337Ops()' input argument should be an array, found: {:?}" ,
104
+ array_param. kind
105
+ )
106
+ } ) ;
107
+ } ;
108
+
109
+ let ParamType :: Tuple {
110
+ params : tuple_params,
111
+ } = array_elem_type. as_ref ( )
112
+ else {
113
+ return AbiError :: err ( AbiErrorKind :: Error_internal ) . with_context ( || {
114
+ format ! (
115
+ "'Biz.execute4337Ops()' input argument should be an array of tuples, found: {array_elem_type:?}" ,
116
+ )
117
+ } ) ;
118
+ } ;
119
+
120
+ if tuple_params. len ( ) != 3 {
121
+ return AbiError :: err ( AbiErrorKind :: Error_internal ) . with_context ( || {
122
+ format ! (
123
+ "'Biz.execute4337Ops()' input argument should be an array of tuples with 3 elements, found: {}" , tuple_params. len( )
124
+ )
125
+ } ) ;
126
+ }
127
+
128
+ let array_tokens = args
129
+ . into_iter ( )
130
+ . map ( |call| Token :: Tuple {
131
+ params : vec ! [
132
+ NamedToken :: with_param_and_token( & tuple_params[ 0 ] , Token :: Address ( call. to) ) ,
133
+ NamedToken :: with_param_and_token( & tuple_params[ 1 ] , Token :: u256( call. value) ) ,
134
+ NamedToken :: with_param_and_token( & tuple_params[ 2 ] , Token :: Bytes ( call. data) ) ,
135
+ ] ,
136
+ } )
137
+ . collect ( ) ;
138
+
139
+ func. encode_input ( & [ Token :: array ( * array_elem_type, array_tokens) ] )
140
+ }
69
141
}
0 commit comments