@@ -91,6 +91,7 @@ pub struct CallCall<'a, T: Contracts> {
91
91
/// Address of the contract.
92
92
pub dest : & ' a <T as System >:: Address ,
93
93
/// Value to transfer to the contract.
94
+ #[ codec( compact) ]
94
95
pub value : <T as Balances >:: Balance ,
95
96
/// Gas limit.
96
97
#[ codec( compact) ]
@@ -115,45 +116,162 @@ pub struct InstantiatedEvent<T: Contracts> {
115
116
pub contract : <T as System >:: AccountId ,
116
117
}
117
118
119
+ /// Contract execution event.
120
+ ///
121
+ /// Emitted upon successful execution of a contract, if any contract events were produced.
122
+ #[ derive( Clone , Debug , Eq , PartialEq , Event , Decode ) ]
123
+ pub struct ContractExecutionEvent < T : Contracts > {
124
+ /// Caller of the contract.
125
+ pub caller : <T as System >:: AccountId ,
126
+ /// SCALE encoded contract event data.
127
+ pub data : Vec < u8 > ,
128
+ }
129
+
118
130
#[ cfg( test) ]
119
131
#[ cfg( feature = "integration-tests" ) ]
120
132
mod tests {
121
133
use sp_keyring:: AccountKeyring ;
122
134
123
135
use super :: * ;
124
136
use crate :: {
137
+ balances:: * ,
138
+ system:: * ,
139
+ Client ,
125
140
ClientBuilder ,
126
141
ContractsTemplateRuntime ,
142
+ Error ,
143
+ ExtrinsicSuccess ,
127
144
PairSigner ,
145
+ Signer ,
146
+ } ;
147
+ use sp_core:: {
148
+ crypto:: AccountId32 ,
149
+ sr25519:: Pair ,
150
+ } ;
151
+ use std:: sync:: atomic:: {
152
+ AtomicU32 ,
153
+ Ordering ,
128
154
} ;
129
155
130
- fn contract_wasm ( ) -> Vec < u8 > {
131
- const CONTRACT : & str = r#"
132
- (module
133
- (func (export "call"))
134
- (func (export "deploy"))
135
- )
136
- "# ;
137
- wabt:: wat2wasm ( CONTRACT ) . expect ( "invalid wabt" )
156
+ static STASH_NONCE : std:: sync:: atomic:: AtomicU32 = AtomicU32 :: new ( 0 ) ;
157
+
158
+ struct TestContext {
159
+ client : Client < ContractsTemplateRuntime > ,
160
+ signer : PairSigner < ContractsTemplateRuntime , Pair > ,
138
161
}
139
162
140
- #[ async_std:: test]
141
- #[ cfg( feature = "integration-tests" ) ]
142
- async fn tx_put_code ( ) {
143
- env_logger:: try_init ( ) . ok ( ) ;
163
+ impl TestContext {
164
+ async fn init ( ) -> Self {
165
+ env_logger:: try_init ( ) . ok ( ) ;
166
+
167
+ let client = ClientBuilder :: < ContractsTemplateRuntime > :: new ( )
168
+ . build ( )
169
+ . await
170
+ . expect ( "Error creating client" ) ;
171
+ let mut stash = PairSigner :: new ( AccountKeyring :: Alice . pair ( ) ) ;
172
+ let nonce = client
173
+ . account ( & stash. account_id ( ) , None )
174
+ . await
175
+ . unwrap ( )
176
+ . nonce ;
177
+ let local_nonce = STASH_NONCE . fetch_add ( 1 , Ordering :: SeqCst ) ;
178
+
179
+ stash. set_nonce ( nonce + local_nonce) ;
180
+
181
+ let signer = Self :: generate_account ( & client, & mut stash) . await ;
182
+
183
+ TestContext { client, signer }
184
+ }
185
+
186
+ /// generate a new keypair for an account, and fund it so it can perform smart contract operations
187
+ async fn generate_account (
188
+ client : & Client < ContractsTemplateRuntime > ,
189
+ stash : & mut PairSigner < ContractsTemplateRuntime , Pair > ,
190
+ ) -> PairSigner < ContractsTemplateRuntime , Pair > {
191
+ use sp_core:: Pair as _;
192
+ let new_account = Pair :: generate ( ) . 0 ;
193
+ let new_account_id: AccountId32 = new_account. public ( ) . into ( ) ;
194
+ // fund the account
195
+ let endowment = 200_000_000_000_000 ;
196
+ let _ = client
197
+ . transfer_and_watch ( stash, & new_account_id, endowment)
198
+ . await
199
+ . expect ( "New account balance transfer failed" ) ;
200
+ stash. increment_nonce ( ) ;
201
+ PairSigner :: new ( new_account)
202
+ }
144
203
145
- let signer = PairSigner :: new ( AccountKeyring :: Alice . pair ( ) ) ;
146
- let client = ClientBuilder :: < ContractsTemplateRuntime > :: new ( )
147
- . build ( )
148
- . await
149
- . unwrap ( ) ;
204
+ async fn put_code (
205
+ & self ,
206
+ ) -> Result < CodeStoredEvent < ContractsTemplateRuntime > , Error > {
207
+ const CONTRACT : & str = r#"
208
+ (module
209
+ (func (export "call"))
210
+ (func (export "deploy"))
211
+ )
212
+ "# ;
213
+ let code = wabt:: wat2wasm ( CONTRACT ) . expect ( "invalid wabt" ) ;
150
214
151
- let code = contract_wasm ( ) ;
152
- let result = client. put_code_and_watch ( & signer, & code) . await . unwrap ( ) ;
153
- let code_stored = result. code_stored ( ) . unwrap ( ) ;
215
+ let result = self . client . put_code_and_watch ( & self . signer , & code) . await ?;
216
+ let code_stored = result. code_stored ( ) ?. ok_or_else ( || {
217
+ Error :: Other ( "Failed to find a CodeStored event" . into ( ) )
218
+ } ) ?;
219
+ log:: info!( "Code hash: {:?}" , code_stored. code_hash) ;
220
+ Ok ( code_stored)
221
+ }
222
+
223
+ async fn instantiate (
224
+ & self ,
225
+ code_hash : & <ContractsTemplateRuntime as System >:: Hash ,
226
+ data : & [ u8 ] ,
227
+ ) -> Result < InstantiatedEvent < ContractsTemplateRuntime > , Error > {
228
+ // call instantiate extrinsic
229
+ let result = self
230
+ . client
231
+ . instantiate_and_watch (
232
+ & self . signer ,
233
+ 100_000_000_000_000 , // endowment
234
+ 500_000_000 , // gas_limit
235
+ code_hash,
236
+ data,
237
+ )
238
+ . await ?;
239
+
240
+ log:: info!( "Instantiate result: {:?}" , result) ;
241
+ let instantiated = result. instantiated ( ) ?. ok_or_else ( || {
242
+ Error :: Other ( "Failed to find a Instantiated event" . into ( ) )
243
+ } ) ?;
244
+
245
+ Ok ( instantiated)
246
+ }
247
+
248
+ async fn call (
249
+ & self ,
250
+ contract : & <ContractsTemplateRuntime as System >:: Address ,
251
+ input_data : & [ u8 ] ,
252
+ ) -> Result < ExtrinsicSuccess < ContractsTemplateRuntime > , Error > {
253
+ let result = self
254
+ . client
255
+ . call_and_watch (
256
+ & self . signer ,
257
+ contract,
258
+ 0 , // value
259
+ 500_000_000 , // gas_limit
260
+ input_data,
261
+ )
262
+ . await ?;
263
+ log:: info!( "Call result: {:?}" , result) ;
264
+ Ok ( result)
265
+ }
266
+ }
267
+
268
+ #[ async_std:: test]
269
+ async fn tx_put_code ( ) {
270
+ let ctx = TestContext :: init ( ) . await ;
271
+ let code_stored = ctx. put_code ( ) . await ;
154
272
155
273
assert ! (
156
- code_stored. is_some ( ) ,
274
+ code_stored. is_ok ( ) ,
157
275
format!(
158
276
"Error calling put_code and receiving CodeStored Event: {:?}" ,
159
277
code_stored
@@ -162,41 +280,29 @@ mod tests {
162
280
}
163
281
164
282
#[ async_std:: test]
165
- #[ cfg( feature = "integration-tests" ) ]
166
283
async fn tx_instantiate ( ) {
167
- env_logger:: try_init ( ) . ok ( ) ;
168
- let signer = PairSigner :: new ( AccountKeyring :: Bob . pair ( ) ) ;
169
- let client = ClientBuilder :: < ContractsTemplateRuntime > :: new ( )
170
- . build ( )
171
- . await
172
- . unwrap ( ) ;
173
-
174
- // call put_code extrinsic
175
- let code = contract_wasm ( ) ;
176
- let result = client. put_code_and_watch ( & signer, & code) . await . unwrap ( ) ;
177
- let code_stored = result. code_stored ( ) . unwrap ( ) ;
178
- let code_hash = code_stored. unwrap ( ) . code_hash ;
179
-
180
- log:: info!( "Code hash: {:?}" , code_hash) ;
181
-
182
- // call instantiate extrinsic
183
- let result = client
184
- . instantiate_and_watch (
185
- & signer,
186
- 100_000_000_000_000 , // endowment
187
- 500_000_000 , // gas_limit
188
- & code_hash,
189
- & [ ] , // data
190
- )
191
- . await
192
- . unwrap ( ) ;
284
+ let ctx = TestContext :: init ( ) . await ;
285
+ let code_stored = ctx. put_code ( ) . await . unwrap ( ) ;
286
+
287
+ let instantiated = ctx. instantiate ( & code_stored. code_hash , & [ ] ) . await ;
288
+
289
+ assert ! (
290
+ instantiated. is_ok( ) ,
291
+ format!( "Error instantiating contract: {:?}" , instantiated)
292
+ ) ;
293
+ }
294
+
295
+ #[ async_std:: test]
296
+ async fn tx_call ( ) {
297
+ let ctx = TestContext :: init ( ) . await ;
298
+ let code_stored = ctx. put_code ( ) . await . unwrap ( ) ;
193
299
194
- log :: info! ( "Instantiate result: {:?}" , result ) ;
195
- let event = result . instantiated ( ) . unwrap ( ) ;
300
+ let instantiated = ctx . instantiate ( & code_stored . code_hash , & [ ] ) . await . unwrap ( ) ;
301
+ let executed = ctx . call ( & instantiated . contract , & [ ] ) . await ;
196
302
197
303
assert ! (
198
- event . is_some ( ) ,
199
- format!( "Error instantiating contract: {:?}" , result )
304
+ executed . is_ok ( ) ,
305
+ format!( "Error calling contract: {:?}" , executed )
200
306
) ;
201
307
}
202
308
}
0 commit comments