1919// TODO: Extract to it's own crate?
2020
2121use codec:: Slicable ;
22- use primitives:: traits:: As ;
2322use rstd:: prelude:: * ;
2423use sandbox;
2524use { AccountDb , Module , OverlayAccountDb , Trait } ;
@@ -190,15 +189,19 @@ pub(crate) fn execute<'a, 'b: 'a, T: Trait>(
190189 fn ext_transfer < T : Trait > ( e : & mut ExecutionExt < T > , args : & [ sandbox:: TypedValue ] ) -> Result < sandbox:: ReturnValue , sandbox:: HostError > {
191190 let transfer_to_ptr = args[ 0 ] . as_i32 ( ) . unwrap ( ) as u32 ;
192191 let transfer_to_len = args[ 1 ] . as_i32 ( ) . unwrap ( ) as u32 ;
193- let value = args[ 2 ] . as_i32 ( ) . unwrap ( ) as u64 ;
192+ let value_ptr = args[ 2 ] . as_i32 ( ) . unwrap ( ) as u32 ;
193+ let value_len = args[ 3 ] . as_i32 ( ) . unwrap ( ) as u32 ;
194194
195- // TODO: slicable
196195 let mut transfer_to = Vec :: new ( ) ;
197196 transfer_to. resize ( transfer_to_len as usize , 0 ) ;
198197 e. memory ( ) . get ( transfer_to_ptr, & mut transfer_to) ?;
199- let value = T :: Balance :: sa ( value as usize ) ;
200198 let transfer_to = T :: AccountId :: decode ( & mut & transfer_to[ ..] ) . unwrap ( ) ;
201199
200+ let mut value_buf = Vec :: new ( ) ;
201+ value_buf. resize ( value_len as usize , 0 ) ;
202+ e. memory ( ) . get ( value_ptr, & mut value_buf) ?;
203+ let value = T :: Balance :: decode ( & mut & value_buf[ ..] ) . unwrap ( ) ;
204+
202205 let account = e. account ( ) . clone ( ) ;
203206 if let Some ( commit_state) =
204207 Module :: < T > :: effect_transfer ( & account, & transfer_to, value, e. account_db ( ) )
@@ -213,10 +216,13 @@ pub(crate) fn execute<'a, 'b: 'a, T: Trait>(
213216 fn ext_create < T : Trait > ( e : & mut ExecutionExt < T > , args : & [ sandbox:: TypedValue ] ) -> Result < sandbox:: ReturnValue , sandbox:: HostError > {
214217 let code_ptr = args[ 0 ] . as_i32 ( ) . unwrap ( ) as u32 ;
215218 let code_len = args[ 1 ] . as_i32 ( ) . unwrap ( ) as u32 ;
216- let value = args[ 2 ] . as_i32 ( ) . unwrap ( ) as u32 ;
219+ let value_ptr = args[ 2 ] . as_i32 ( ) . unwrap ( ) as u32 ;
220+ let value_len = args[ 3 ] . as_i32 ( ) . unwrap ( ) as u32 ;
217221
218- // TODO: slicable
219- let value = T :: Balance :: sa ( value as usize ) ;
222+ let mut value_buf = Vec :: new ( ) ;
223+ value_buf. resize ( value_len as usize , 0 ) ;
224+ e. memory ( ) . get ( value_ptr, & mut value_buf) ?;
225+ let value = T :: Balance :: decode ( & mut & value_buf[ ..] ) . unwrap ( ) ;
220226
221227 let mut code = Vec :: new ( ) ;
222228 code. resize ( code_len as usize , 0u8 ) ;
@@ -506,30 +512,35 @@ mod tests {
506512 assert_matches ! ( r, Err ( Error :: Memory ) ) ;
507513 }
508514
509- #[ test]
510- fn contract_transfer ( ) {
511- let code_transfer = wabt:: wat2wasm (
512- r#"
515+ const CODE_TRANSFER : & str = r#"
513516(module
514- ;; ext_transfer(transfer_to: u32, transfer_to_len: u32, value : u32)
515- (import "env" "ext_transfer" (func $ext_transfer (param i32 i32 i32)))
517+ ;; ext_transfer(transfer_to: u32, transfer_to_len: u32, value_ptr: u32, value_len : u32)
518+ (import "env" "ext_transfer" (func $ext_transfer (param i32 i32 i32 i32 )))
516519
517520 (import "env" "memory" (memory 1 1))
518521
519522 (func (export "call")
520523 (call $ext_transfer
521524 (i32.const 4) ;; Pointer to "Transfer to" address.
522525 (i32.const 8) ;; Length of "Transfer to" address.
523- (i32.const 6) ;; value to transfer
526+ (i32.const 12) ;; Pointer to the buffer with value to transfer
527+ (i32.const 8) ;; Length of the buffer with value to transfer.
524528 )
525529 )
526530
527531 ;; Destination AccountId to transfer the funds.
528532 ;; Represented by u64 (8 bytes long) in little endian.
529533 (data (i32.const 4) "\02\00\00\00\00\00\00\00")
534+
535+ ;; Amount of value to transfer.
536+ ;; Represented by u64 (8 bytes long) in little endian.
537+ (data (i32.const 12) "\06\00\00\00\00\00\00\00")
530538)
531- "# ,
532- ) . unwrap ( ) ;
539+ "# ;
540+
541+ #[ test]
542+ fn contract_transfer ( ) {
543+ let code_transfer = wabt:: wat2wasm ( CODE_TRANSFER ) . unwrap ( ) ;
533544
534545 with_externalities ( & mut new_test_ext ( 1 , 3 , 1 , false ) , || {
535546 <FreeBalance < Test > >:: insert ( 0 , 111 ) ;
@@ -546,61 +557,55 @@ mod tests {
546557 } ) ;
547558 }
548559
549- fn escaped_bytestring ( bytes : & [ u8 ] ) -> String {
550- use std:: fmt:: Write ;
551- let mut result = String :: new ( ) ;
552- for b in bytes {
553- write ! ( result, "\\ {:02x}" , b) . unwrap ( ) ;
560+ /// Returns code that uses `ext_create` runtime call.
561+ ///
562+ /// Takes bytecode of the contract that needs to be deployed.
563+ fn code_create ( child_bytecode : & [ u8 ] ) -> String {
564+ /// Convert a byte slice to a string with hex values.
565+ ///
566+ /// Each value is preceeded with a `\` character.
567+ fn escaped_bytestring ( bytes : & [ u8 ] ) -> String {
568+ use std:: fmt:: Write ;
569+ let mut result = String :: new ( ) ;
570+ for b in bytes {
571+ write ! ( result, "\\ {:02x}" , b) . unwrap ( ) ;
572+ }
573+ result
554574 }
555- result
556- }
557575
558- #[ test]
559- fn contract_create ( ) {
560- let code_transfer = wabt:: wat2wasm (
561- r#"
576+ format ! (
577+ r#"
562578(module
563- ;; ext_transfer(transfer_to : u32, transfer_to_len : u32, value : u32)
564- (import "env" "ext_transfer " (func $ext_transfer (param i32 i32 i32)))
579+ ;; ext_create(code_ptr : u32, code_len : u32, value_ptr: u32, value_len : u32)
580+ (import "env" "ext_create " (func $ext_create (param i32 i32 i32 i32)))
565581
566582 (import "env" "memory" (memory 1 1))
567583
568584 (func (export "call")
569- (call $ext_transfer
570- (i32.const 4) ;; Pointer to "Transfer to" address.
571- (i32.const 8) ;; Length of "Transfer to" address.
572- (i32.const 6) ;; value to transfer
585+ (call $ext_create
586+ (i32.const 12) ;; Pointer to `code`
587+ (i32.const {code_len}) ;; Length of `code`
588+ (i32.const 4) ;; Pointer to the buffer with value to transfer
589+ (i32.const 8) ;; Length of the buffer with value to transfer
573590 )
574591 )
592+ ;; Amount of value to transfer.
593+ ;; Represented by u64 (8 bytes long) in little endian.
594+ (data (i32.const 4) "\03\00\00\00\00\00\00\00")
575595
576- ;; Destination AccountId to transfer the funds.
577- ;; Represented by u64 (8 bytes long) in little endian.
578- (data (i32.const 4) "\02\00\00\00\00\00\00\00")
596+ ;; Embedded wasm code.
597+ (data (i32.const 12) "{escaped_bytecode}")
579598)
580- "# ,
581- ) . unwrap ( ) ;
582-
583- let code_create = wabt:: wat2wasm ( format ! (
584- r#"
585- (module
586- ;; ext_create(code_ptr: u32, code_len: u32, value: u32)
587- (import "env" "ext_create" (func $ext_create (param i32 i32 i32)))
588-
589- (import "env" "memory" (memory 1 1))
599+ "# ,
600+ escaped_bytecode = escaped_bytestring( & child_bytecode) ,
601+ code_len = child_bytecode. len( ) ,
602+ )
603+ }
590604
591- (func (export "call")
592- (call $ext_create
593- (i32.const 4) ;; Pointer to `code`
594- (i32.const {code_length}) ;; Length of `code`
595- (i32.const 3) ;; Value to transfer
596- )
597- )
598- (data (i32.const 4) "{escaped_code_transfer}")
599- )
600- "# ,
601- escaped_code_transfer = escaped_bytestring( & code_transfer) ,
602- code_length = code_transfer. len( ) ,
603- ) ) . unwrap ( ) ;
605+ #[ test]
606+ fn contract_create ( ) {
607+ let code_transfer = wabt:: wat2wasm ( CODE_TRANSFER ) . unwrap ( ) ;
608+ let code_create = wabt:: wat2wasm ( & code_create ( & code_transfer) ) . unwrap ( ) ;
604609
605610 with_externalities ( & mut new_test_ext ( 1 , 3 , 1 , false ) , || {
606611 <FreeBalance < Test > >:: insert ( 0 , 111 ) ;
@@ -620,9 +625,10 @@ mod tests {
620625 } ) ;
621626 }
622627
623- #[ test]
624- fn contract_adder ( ) {
625- let code_adder = wabt:: wat2wasm ( r#"
628+ /// This code a value from the storage, increment it's first byte
629+ /// and then stores it back in the storage.
630+ const CODE_ADDER : & str =
631+ r#"
626632(module
627633 ;; ext_set_storage(location_ptr: i32, value_non_null: bool, value_ptr: i32)
628634 (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32)))
@@ -652,10 +658,14 @@ mod tests {
652658 )
653659 )
654660
655- ;; Location of storage to put the data. 32 bytes.
661+ ;; Location of storage to load/store the data. 32 bytes.
656662 (data (i32.const 4) "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01")
657663)
658- "# ) . unwrap ( ) ;
664+ "# ;
665+
666+ #[ test]
667+ fn contract_adder ( ) {
668+ let code_adder = wabt:: wat2wasm ( CODE_ADDER ) . unwrap ( ) ;
659669
660670 with_externalities ( & mut new_test_ext ( 1 , 3 , 1 , false ) , || {
661671 <FreeBalance < Test > >:: insert ( 0 , 111 ) ;
@@ -681,12 +691,10 @@ mod tests {
681691 } ) ;
682692 }
683693
684- #[ test]
685- fn contract_out_of_gas ( ) {
686- // This code should make 100_000 iterations so it should
687- // consume more than 100_000 units of gas.
688- let code_loop = wabt:: wat2wasm (
689- r#"
694+ // This code should make 100_000 iterations so it should
695+ // consume more than 100_000 units of gas.
696+ const CODE_LOOP : & str =
697+ r#"
690698(module
691699 (func (export "call")
692700 (local $i i32)
@@ -710,8 +718,11 @@ mod tests {
710718 end
711719 )
712720)
713- "# ,
714- ) . unwrap ( ) ;
721+ "# ;
722+
723+ #[ test]
724+ fn contract_out_of_gas ( ) {
725+ let code_loop = wabt:: wat2wasm ( CODE_LOOP ) . unwrap ( ) ;
715726
716727 with_externalities ( & mut new_test_ext ( 1 , 3 , 1 , false ) , || {
717728 // Set initial balances.
@@ -730,10 +741,8 @@ mod tests {
730741 } ) ;
731742 }
732743
733- #[ test]
734- fn contract_internal_mem ( ) {
735- let code_mem = wabt:: wat2wasm (
736- r#"
744+ const CODE_MEM : & str =
745+ r#"
737746(module
738747 ;; Internal memory is not allowed.
739748 (memory 1 1)
@@ -742,8 +751,11 @@ mod tests {
742751 nop
743752 )
744753)
745- "# ,
746- ) . unwrap ( ) ;
754+ "# ;
755+
756+ #[ test]
757+ fn contract_internal_mem ( ) {
758+ let code_mem = wabt:: wat2wasm ( CODE_MEM ) . unwrap ( ) ;
747759
748760 with_externalities ( & mut new_test_ext ( 1 , 3 , 1 , false ) , || {
749761 // Set initial balances.
0 commit comments