Contracts move fixtures to new crate (#2246)

Small PR that introduce a new crate that will host RISC-V & wasm
fixtures for testing pallet-contracts
This commit is contained in:
PG Herveou
2023-11-10 12:22:47 +01:00
committed by GitHub
parent 03ee44d9e1
commit 64effd0e6f
57 changed files with 74 additions and 23 deletions
@@ -0,0 +1,37 @@
;; This fixture tests if account_reentrance_count works as expected
;; testing it with 2 different addresses
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_caller" (func $seal_caller (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "seal0" "account_reentrance_count" (func $account_reentrance_count (param i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) buffer where input is copied
;; [32, 36) size of the input buffer
(data (i32.const 32) "\20")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
;; Reading "callee" input address
(call $seal_input (i32.const 0) (i32.const 32))
(i32.store
(i32.const 36)
(call $account_reentrance_count (i32.const 0))
)
(call $seal_return (i32.const 0) (i32.const 36) (i32.const 4))
)
(func (export "deploy"))
)
@@ -0,0 +1,111 @@
;; This contract tests the behavior of adding / removing delegate_dependencies when delegate calling into a contract.
(module
(import "seal0" "add_delegate_dependency" (func $add_delegate_dependency (param i32)))
(import "seal0" "remove_delegate_dependency" (func $remove_delegate_dependency (param i32)))
(import "seal0" "input" (func $input (param i32 i32)))
(import "seal1" "terminate" (func $terminate (param i32)))
(import "seal0" "delegate_call" (func $delegate_call (param i32 i32 i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; [100, 132) Address of Alice
(data (i32.const 100)
"\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"
)
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
;; This function loads input data and performs the action specified.
;; The first 4 bytes of the input specify the action to perform.
;; The next 32 bytes specify the code hash to use when calling add_delegate_dependency or remove_delegate_dependency.
;; Actions are:
;; 1: call add_delegate_dependency
;; 2: call remove_delegate_dependency.
;; 3: call terminate.
;; Any other value is a no-op.
(func $load_input
(local $action i32)
(local $code_hash_ptr i32)
;; Store available input size at offset 0.
(i32.store (i32.const 0) (i32.const 512))
;; Read input data.
(call $input (i32.const 4) (i32.const 0))
;; Input data layout.
;; [0..4) - size of the call
;; [4..8) - action to perform
;; [8..42) - code hash of the callee
(set_local $action (i32.load (i32.const 4)))
(set_local $code_hash_ptr (i32.const 8))
;; Assert input size == 36 (4 for action + 32 for code_hash).
(call $assert
(i32.eq
(i32.load (i32.const 0))
(i32.const 36)
)
)
;; Call add_delegate_dependency when action == 1.
(if (i32.eq (get_local $action) (i32.const 1))
(then
(call $add_delegate_dependency (get_local $code_hash_ptr))
)
(else)
)
;; Call remove_delegate_dependency when action == 2.
(if (i32.eq (get_local $action) (i32.const 2))
(then
(call $remove_delegate_dependency
(get_local $code_hash_ptr)
)
)
(else)
)
;; Call terminate when action == 3.
(if (i32.eq (get_local $action) (i32.const 3))
(then
(call $terminate
(i32.const 100) ;; Pointer to beneficiary address
)
(unreachable) ;; terminate never returns
)
(else)
)
)
(func (export "deploy")
(call $load_input)
)
(func (export "call")
(call $load_input)
;; Delegate call into passed code hash.
(call $assert
(i32.eq
(call $delegate_call
(i32.const 0) ;; Set no call flags.
(i32.const 8) ;; Pointer to "callee" code_hash.
(i32.const 0) ;; Input is ignored.
(i32.const 0) ;; Length of the input.
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output.
(i32.const 0) ;; Length is ignored in this case.
)
(i32.const 0)
)
)
)
)
@@ -0,0 +1,42 @@
(module
(import "seal0" "seal_balance" (func $seal_balance (param i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 8) reserved for $seal_balance output
;; [8, 16) length of the buffer for $seal_balance
(data (i32.const 8) "\08")
;; [16, inf) zero initialized
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy"))
(func (export "call")
(call $seal_balance (i32.const 0) (i32.const 8))
;; Balance should be encoded as a u64.
(call $assert
(i32.eq
(i32.load (i32.const 8))
(i32.const 8)
)
)
;; Assert the free balance to be zero.
(call $assert
(i64.eq
(i64.load (i32.const 0))
(i64.const 0)
)
)
)
)
@@ -0,0 +1,39 @@
;; This calls another contract as passed as its account id.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy"))
(func (export "call")
;; Store length of input buffer.
(i32.store (i32.const 0) (i32.const 512))
;; Copy input at address 4.
(call $seal_input (i32.const 4) (i32.const 0))
;; Call passed contract.
(call $assert (i32.eqz
(call $seal_call
(i32.const 0) ;; No flags
(i32.const 8) ;; Pointer to "callee" address.
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 512) ;; Pointer to the buffer with value to transfer
(i32.const 4) ;; Pointer to input data buffer address
(i32.const 4) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
))
)
)
@@ -0,0 +1,42 @@
;; This calls the supplied dest and transfers 100 balance during this call and copies
;; the return code of this call to the output buffer.
;; It also forwards its input to the callee.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 8) 100 balance
(data (i32.const 0) "\64\00\00\00\00\00\00\00")
;; [8, 12) here we store the return code of the transfer
;; [12, 16) size of the input data
(data (i32.const 12) "\24")
;; [16, inf) here we store the input data
;; 32 byte dest + 4 byte forward
(func (export "deploy"))
(func (export "call")
(call $seal_input (i32.const 16) (i32.const 12))
(i32.store
(i32.const 8)
(call $seal_call
(i32.const 16) ;; Pointer to "callee" address.
(i32.const 32) ;; Length of "callee" address.
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Length of the buffer with value to transfer.
(i32.const 48) ;; Pointer to input data buffer address
(i32.const 4) ;; Length of input data buffer
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Ptr to output buffer len
)
)
;; exit with success and take transfer return code to the output buffer
(call $seal_return (i32.const 0) (i32.const 8) (i32.const 4))
)
)
@@ -0,0 +1,33 @@
;; This passes its input to `seal_call_runtime` and returns the return value to its caller.
(module
(import "seal0" "call_runtime" (func $call_runtime (param i32 i32) (result i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; 0x1000 = 4k in little endian
;; size of input buffer
(data (i32.const 0) "\00\10")
(func (export "call")
;; Receive the encoded call
(call $seal_input
(i32.const 4) ;; Pointer to the input buffer
(i32.const 0) ;; Size of the length buffer
)
;; Just use the call passed as input and store result to memory
(i32.store (i32.const 0)
(call $call_runtime
(i32.const 4) ;; Pointer where the call is stored
(i32.load (i32.const 0)) ;; Size of the call
)
)
(call $seal_return
(i32.const 0) ;; flags
(i32.const 0) ;; returned value
(i32.const 4) ;; length of returned value
)
)
(func (export "deploy"))
)
@@ -0,0 +1,56 @@
(module
(import "seal0" "call_runtime" (func $call_runtime (param i32 i32) (result i32)))
(import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
(func $assert (param i32)
(block $ok
(br_if $ok (get_local 0))
(unreachable)
)
)
(func (export "call")
;; Store available input size at offset 0.
(i32.store (i32.const 0) (i32.const 512))
;; read input data
(call $seal_input (i32.const 4) (i32.const 0))
;; Input data layout.
;; [0..4) - size of the call
;; [4..8) - how many bytes to add to storage
;; [8..40) - address of the callee
;; [40..n) - encoded runtime call
;; Invoke call_runtime with the encoded call passed to this contract.
(call $assert (i32.eqz
(call $call_runtime
(i32.const 40) ;; Pointer where the call is stored
(i32.sub
(i32.load (i32.const 0)) ;; Size of the call
(i32.const 36) ;; Subtract size of the subcall-related part: 4 bytes for storage length to add + 32 bytes of the callee address
)
)
))
;; call passed contract
(call $assert (i32.eqz
(call $seal_call
(i32.const 0) ;; No flags
(i32.const 8) ;; Pointer to "callee" address.
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 512) ;; Pointer to the buffer with value to transfer
(i32.const 4) ;; Pointer to input data buffer address
(i32.const 4) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
))
)
(func (export "deploy"))
)
@@ -0,0 +1,38 @@
;; This expects [account_id, ref_time, proof_size] as input and calls the account_id with the supplied 2D Weight limit.
;; It returns the result of the call as output data.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal2" "call" (func $seal_call (param i32 i32 i64 i64 i32 i32 i32 i32 i32 i32) (result i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; 0x1000 = 4k in little endian
;; size of input buffer
(data (i32.const 0) "\00\10")
(func (export "deploy"))
(func (export "call")
;; Receive the encoded account_id, ref_time, proof_size
(call $seal_input
(i32.const 4) ;; Pointer to the input buffer
(i32.const 0) ;; Pointer to the length of the input buffer
)
(i32.store
(i32.const 0)
(call $seal_call
(i32.const 0) ;; Set no flag.
(i32.const 4) ;; Pointer to "callee" address.
(i64.load (i32.const 36)) ;; How much ref_time to devote for the execution.
(i64.load (i32.const 44)) ;; How much proof_size to devote for the execution.
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 0) ;; Pointer to input data buffer address
(i32.const 0) ;; Length of input data buffer
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
)
(call $seal_return (i32.const 0) (i32.const 0) (i32.const 4))
)
)
@@ -0,0 +1,286 @@
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_balance" (func $seal_balance (param i32 i32)))
(import "seal2" "call" (func $seal_call (param i32 i32 i64 i64 i32 i32 i32 i32 i32 i32) (result i32)))
(import "seal2" "instantiate" (func $seal_instantiate
(param i32 i64 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
))
(import "env" "memory" (memory 1 1))
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy"))
(func (export "call")
(local $sp i32)
(local $exit_code i32)
;; Length of the buffer
(i32.store (i32.const 20) (i32.const 32))
;; Copy input to this contracts memory
(call $seal_input (i32.const 24) (i32.const 20))
;; Input data is the code hash of the contract to be deployed.
(call $assert
(i32.eq
(i32.load (i32.const 20))
(i32.const 32)
)
)
;; Read current balance into local variable.
(set_local $sp (i32.const 1024))
;; Fail to deploy the contract since it returns a non-zero exit status.
(set_local $exit_code
(call $seal_instantiate
(i32.const 24) ;; Pointer to the code hash.
(i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all.
(i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all.
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 9) ;; Pointer to input data buffer address
(i32.const 7) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
(i32.const 0) ;; Length is ignored in this case
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
(i32.const 0) ;; salt_ptr
(i32.const 0) ;; salt_le
)
)
;; Check non-zero exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted
)
;; Fail to deploy the contract due to insufficient ref_time weight.
(set_local $exit_code
(call $seal_instantiate
(i32.const 24) ;; Pointer to the code hash.
(i64.const 1) ;; Supply too little ref_time weight
(i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all.
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
(i32.const 0) ;; Length is ignored in this case
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
(i32.const 0) ;; salt_ptr
(i32.const 0) ;; salt_le
)
)
;; Check for special trap exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
)
;; Fail to deploy the contract due to insufficient ref_time weight.
(set_local $exit_code
(call $seal_instantiate
(i32.const 24) ;; Pointer to the code hash.
(i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all.
(i64.const 1) ;; Supply too little proof_size weight
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
(i32.const 0) ;; Length is ignored in this case
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
(i32.const 0) ;; salt_ptr
(i32.const 0) ;; salt_le
)
)
;; Check for special trap exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
)
;; Length of the output buffer
(i32.store
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 256)
)
;; Deploy the contract successfully.
(set_local $exit_code
(call $seal_instantiate
(i32.const 24) ;; Pointer to the code hash.
(i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all.
(i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all.
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.const 16) ;; Pointer to the address output buffer
(i32.sub (get_local $sp) (i32.const 4)) ;; Pointer to the address buffer length
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
(i32.const 0) ;; salt_ptr
(i32.const 0) ;; salt_le
)
)
;; Check for success exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
)
;; Check that address has the expected length
(call $assert
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 4))) (i32.const 32))
)
;; Zero out destination buffer of output
(i32.store
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 0)
)
;; Length of the output buffer
(i32.store
(i32.sub (get_local $sp) (i32.const 8))
(i32.const 4)
)
;; Call the new contract and expect it to return failing exit code.
(set_local $exit_code
(call $seal_call
(i32.const 0) ;; Set no flag
(i32.const 16) ;; Pointer to "callee" address.
(i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all.
(i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all.
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 9) ;; Pointer to input data buffer address
(i32.const 7) ;; Length of input data buffer
(i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer
(i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len
)
)
;; Check non-zero exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted
)
;; Check that output buffer contains the expected return data.
(call $assert
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 3))
)
(call $assert
(i32.eq
(i32.load (i32.sub (get_local $sp) (i32.const 4)))
(i32.const 0x00776655)
)
)
;; Fail to call the contract due to insufficient ref_time weight.
(set_local $exit_code
(call $seal_call
(i32.const 0) ;; Set no flag
(i32.const 16) ;; Pointer to "callee" address.
(i64.const 1) ;; Supply too little ref_time weight
(i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all.
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this cas
)
)
;; Check for special trap exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
)
;; Fail to call the contract due to insufficient proof_size weight.
(set_local $exit_code
(call $seal_call
(i32.const 0) ;; Set no flag
(i32.const 16) ;; Pointer to "callee" address.
(i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all.
(i64.const 1) ;; Supply too little proof_size weight
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this cas
)
)
;; Check for special trap exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
)
;; Zero out destination buffer of output
(i32.store
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 0)
)
;; Length of the output buffer
(i32.store
(i32.sub (get_local $sp) (i32.const 8))
(i32.const 4)
)
;; Call the contract successfully.
(set_local $exit_code
(call $seal_call
(i32.const 0) ;; Set no flag
(i32.const 16) ;; Pointer to "callee" address.
(i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all.
(i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all.
(i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer
(i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len
)
)
;; Check for success exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
)
;; Check that the output buffer contains the expected return data.
(call $assert
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 4))
)
(call $assert
(i32.eq
(i32.load (i32.sub (get_local $sp) (i32.const 4)))
(i32.const 0x77665544)
)
)
)
(data (i32.const 0) "\00\80") ;; The value to transfer on instantiation and calls.
;; Chosen to be greater than existential deposit.
(data (i32.const 8) "\00\01\22\33\44\55\66\77") ;; The input data to instantiations and calls.
)
@@ -0,0 +1,46 @@
;; Call chain extension by passing through input and output of this contract
(module
(import "seal0" "call_chain_extension"
(func $call_chain_extension (param i32 i32 i32 i32 i32) (result i32))
)
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 16 16))
(func $assert (param i32)
(block $ok
(br_if $ok (get_local 0))
(unreachable)
)
)
;; [0, 4) len of input output
(data (i32.const 0) "\08")
;; [4, 12) buffer for input
;; [12, 48) len of output buffer
(data (i32.const 12) "\20")
;; [16, inf) buffer for output
(func (export "deploy"))
(func (export "call")
(call $seal_input (i32.const 4) (i32.const 0))
;; the chain extension passes through the input and returns it as output
(call $call_chain_extension
(i32.load (i32.const 4)) ;; id
(i32.const 4) ;; input_ptr
(i32.load (i32.const 0)) ;; input_len
(i32.const 16) ;; output_ptr
(i32.const 12) ;; output_len_ptr
)
;; the chain extension passes through the id
(call $assert (i32.eq (i32.load (i32.const 4))))
(call $seal_return (i32.const 0) (i32.const 16) (i32.load (i32.const 12)))
)
)
@@ -0,0 +1,85 @@
;; Call chain extension two times with the specified func_ids
;; It then calls itself once
(module
(import "seal0" "seal_call_chain_extension"
(func $seal_call_chain_extension (param i32 i32 i32 i32 i32) (result i32))
)
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_address" (func $seal_address (param i32 i32)))
(import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 16 16))
(func $assert (param i32)
(block $ok
(br_if $ok (get_local 0))
(unreachable)
)
)
;; [0, 4) len of input buffer: 8 byte (func_ids) + 1byte (stop_recurse)
(data (i32.const 0) "\09")
;; [4, 16) buffer for input
;; [16, 48] buffer for self address
;; [48, 52] len of self address buffer
(data (i32.const 48) "\20")
(func (export "deploy"))
(func (export "call")
;; input: (func_id1: i32, func_id2: i32, stop_recurse: i8)
(call $seal_input (i32.const 4) (i32.const 0))
(call $seal_call_chain_extension
(i32.load (i32.const 4)) ;; id
(i32.const 0) ;; input_ptr
(i32.const 0) ;; input_len
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; output_len_ptr
)
drop
(call $seal_call_chain_extension
(i32.load (i32.const 8)) ;; _id
(i32.const 0) ;; input_ptr
(i32.const 0) ;; input_len
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; output_len_ptr
)
drop
(if (i32.eqz (i32.load8_u (i32.const 12)))
(then
;; stop recursion
(i32.store8 (i32.const 12) (i32.const 1))
;; load own address into buffer
(call $seal_address (i32.const 16) (i32.const 48))
;; call function 2 + 3 of chainext 3 next time
;; (3 << 16) | 2
;; (3 << 16) | 3
(i32.store (i32.const 4) (i32.const 196610))
(i32.store (i32.const 8) (i32.const 196611))
;; call self
(call $seal_call
(i32.const 8) ;; Set ALLOW_REENTRY
(i32.const 16) ;; Pointer to "callee" address.
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 512) ;; Pointer to the buffer with value to transfer
(i32.const 4) ;; Pointer to input data buffer address
(i32.load (i32.const 0)) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
;; check that call succeeded of call
(call $assert (i32.eqz))
)
(else)
)
)
)
@@ -0,0 +1,60 @@
;; This calls another contract as passed as its account id. It also creates some storage.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal2" "call" (func $seal_call (param i32 i32 i64 i64 i32 i32 i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy"))
(func (export "call")
;; store length of input buffer
(i32.store (i32.const 0) (i32.const 512))
;; copy input at address 4:
;; first 4 bytes for the size of the storage to be created in callee
;; next 32 bytes are for the callee address
;; next bytes for the encoded deposit limit
(call $seal_input (i32.const 4) (i32.const 0))
;; create 4 byte of storage before calling
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.const 4) ;; Size of value
)
;; call passed contract
(call $assert (i32.eqz
(call $seal_call
(i32.const 0) ;; No flags
(i32.const 8) ;; Pointer to "callee" address
(i64.const 0) ;; How much ref_time to devote for the execution. 0 = all
(i64.const 0) ;; How much proof_limit to devote for the execution. 0 = all
(i32.const 40) ;; Pointer to the storage deposit limit
(i32.const 512) ;; Pointer to the buffer with value to transfer
(i32.const 4) ;; Pointer to input data buffer address
(i32.const 4) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
))
;; create 8 byte of storage after calling
;; item of 12 bytes because we override 4 bytes
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.const 12) ;; Size of value
)
)
)
@@ -0,0 +1,66 @@
;; This instantiates another contract and passes some input to its constructor.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal2" "instantiate" (func $seal_instantiate
(param i32 i64 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 8) send 10_000 balance
(data (i32.const 48) "\10\27\00\00\00\00\00\00")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy"))
(func (export "call")
;; store length of input buffer
(i32.store (i32.const 0) (i32.const 512))
;; store length of contract address
(i32.store (i32.const 84) (i32.const 32))
;; copy input at address 4
(call $seal_input (i32.const 4) (i32.const 0))
;; memory layout is:
;; [0,4): size of input buffer
;; [4,8): size of the storage to be created in callee
;; [8,40): the code hash of the contract to instantiate
;; [40,48): for the encoded deposit limit
;; [48,52): value to transfer
;; [52,84): address of the deployed contract
;; [84,88): len of the address
;; instantiate a contract
(call $assert (i32.eqz
;; (i32.store
;; (i32.const 64)
(call $seal_instantiate
(i32.const 8) ;; Pointer to the code hash.
(i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all.
(i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all.
(i32.const 40) ;; Pointer to the storage deposit limit
(i32.const 48) ;; Pointer to the buffer with value to transfer
(i32.const 4) ;; Pointer to input data buffer address
(i32.const 4) ;; Length of input data buffer
(i32.const 52) ;; Pointer to where to copy address
(i32.const 84) ;; Pointer to address len ptr
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
(i32.const 0) ;; salt_ptr
(i32.const 0) ;; salt_len
)
))
;; return the deployed contract address
(call $seal_return (i32.const 0) (i32.const 52) (i32.const 32))
)
)
@@ -0,0 +1,81 @@
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "seal0" "seal_hash_sha2_256" (func $seal_hash_sha2_256 (param i32 i32 i32)))
(import "seal0" "seal_hash_keccak_256" (func $seal_hash_keccak_256 (param i32 i32 i32)))
(import "seal0" "seal_hash_blake2_256" (func $seal_hash_blake2_256 (param i32 i32 i32)))
(import "seal0" "seal_hash_blake2_128" (func $seal_hash_blake2_128 (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
(type $hash_fn_sig (func (param i32 i32 i32)))
(table 8 funcref)
(elem (i32.const 1)
$seal_hash_sha2_256
$seal_hash_keccak_256
$seal_hash_blake2_256
$seal_hash_blake2_128
)
(data (i32.const 1) "20202010201008") ;; Output sizes of the hashes in order in hex.
;; Not in use by the tests besides instantiating the contract.
(func (export "deploy"))
;; Called by the tests.
;;
;; The `call` function expects data in a certain format in the input buffer.
;;
;; 1. The first byte encodes an identifier for the crypto hash function
;; under test. (*)
;; 2. The rest encodes the input data that is directly fed into the
;; crypto hash function chosen in 1.
;;
;; The `deploy` function then computes the chosen crypto hash function
;; given the input and puts the result into the output buffer.
;; After contract execution the test driver then asserts that the returned
;; values are equal to the expected bytes for the input and chosen hash
;; function.
;;
;; (*) The possible value for the crypto hash identifiers can be found below:
;;
;; | value | Algorithm | Bit Width |
;; |-------|-----------|-----------|
;; | 0 | SHA2 | 256 |
;; | 1 | KECCAK | 256 |
;; | 2 | BLAKE2 | 256 |
;; | 3 | BLAKE2 | 128 |
;; ---------------------------------
(func (export "call")
(local $chosen_hash_fn i32)
(local $input_len_ptr i32)
(local $input_ptr i32)
(local $input_len i32)
(local $output_ptr i32)
(local $output_len i32)
(local.set $input_len_ptr (i32.const 256))
(local.set $input_ptr (i32.const 10))
(i32.store (local.get $input_len_ptr) (i32.const 246))
(call $seal_input (local.get $input_ptr) (local.get $input_len_ptr))
(local.set $chosen_hash_fn (i32.load8_u (local.get $input_ptr)))
(if (i32.gt_u (local.get $chosen_hash_fn) (i32.const 7))
;; We check that the chosen hash fn identifier is within bounds: [0,7]
(unreachable)
)
(local.set $input_ptr (i32.add (local.get $input_ptr) (i32.const 1)))
(local.set $input_len (i32.sub (i32.load (local.get $input_len_ptr)) (i32.const 1)))
(local.set $output_len (i32.load8_u (local.get $chosen_hash_fn)))
(call_indirect (type $hash_fn_sig)
(local.get $input_ptr)
(local.get $input_len)
(local.get $input_ptr)
(local.get $chosen_hash_fn) ;; Which crypto hash function to execute.
)
(call $seal_return
(i32.const 0)
(local.get $input_ptr) ;; Linear memory location of the output buffer.
(local.get $output_len) ;; Number of output buffer bytes.
)
(unreachable)
)
)
@@ -0,0 +1,28 @@
;; Emit a debug message with an invalid utf-8 code
(module
(import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
(data (i32.const 0) "\fc")
(func $assert_eq (param i32 i32)
(block $ok
(br_if $ok
(i32.eq (get_local 0) (get_local 1))
)
(unreachable)
)
)
(func (export "call")
(call $assert_eq
(call $seal_debug_message
(i32.const 0) ;; Pointer to the text buffer
(i32.const 12) ;; The size of the buffer
)
(i32.const 0) ;; Success return code
)
)
(func (export "deploy"))
)
@@ -0,0 +1,28 @@
;; Emit a "Hello World!" debug message but assume that logging is disabled.
(module
(import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
(data (i32.const 0) "Hello World!")
(func $assert_eq (param i32 i32)
(block $ok
(br_if $ok
(i32.eq (get_local 0) (get_local 1))
)
(unreachable)
)
)
(func (export "call")
(call $assert_eq
(call $seal_debug_message
(i32.const 0) ;; Pointer to the text buffer
(i32.const 12) ;; The size of the buffer
)
(i32.const 0) ;; Success return code
)
)
(func (export "deploy"))
)
@@ -0,0 +1,28 @@
;; Emit a "Hello World!" debug message
(module
(import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
(data (i32.const 0) "Hello World!")
(func $assert_eq (param i32 i32)
(block $ok
(br_if $ok
(i32.eq (get_local 0) (get_local 1))
)
(unreachable)
)
)
(func (export "call")
(call $assert_eq
(call $seal_debug_message
(i32.const 0) ;; Pointer to the text buffer
(i32.const 12) ;; The size of the buffer
)
(i32.const 0) ;; success return code
)
)
(func (export "deploy"))
)
@@ -0,0 +1,111 @@
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32)))
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 3 3))
;; [0, 32) storage key
(data (i32.const 0) "\01")
;; [32, 64) storage key
(data (i32.const 32) "\02")
;; [64, 96) buffer where input is copied
;; [96, 100) size of the input buffer
(data (i32.const 96) "\20")
;; [100, 104) size of buffer for seal_get_storage
(data (i32.const 100) "\20")
;; [104, 136) seal_get_storage buffer
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(local $exit_code i32)
;; Reading "callee" code_hash
(call $seal_input (i32.const 64) (i32.const 96))
;; assert input size == 32
(call $assert
(i32.eq
(i32.load (i32.const 96))
(i32.const 32)
)
)
;; place a value in storage, the size of which is specified by the call input.
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 32) ;; Pointer to initial value
(i32.load (i32.const 100)) ;; Size of value
)
(call $assert
(i32.eq
(call $seal_get_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 104) ;; buffer where to copy result
(i32.const 100) ;; pointer to size of buffer
)
(i32.const 0) ;; ReturnCode::Success
)
)
(call $assert
(i32.eq
(i32.load (i32.const 104)) ;; value received from storage
(i32.load (i32.const 32)) ;; initial value
)
)
;; Call deployed library contract code.
(set_local $exit_code
(call $seal_delegate_call
(i32.const 0) ;; Set no call flags
(i32.const 64) ;; Pointer to "callee" code_hash.
(i32.const 0) ;; Input is ignored
(i32.const 0) ;; Length of the input
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
)
;; Check for success exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
)
(call $assert
(i32.eq
(call $seal_get_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 104) ;; buffer where to copy result
(i32.const 100) ;; pointer to size of buffer
)
(i32.const 0) ;; ReturnCode::Success
)
)
;; Make sure that 'callee' code changed the value
(call $assert
(i32.eq
(i32.load (i32.const 104))
(i32.const 1)
)
)
)
(func (export "deploy"))
)
@@ -0,0 +1,79 @@
(module
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_caller" (func $seal_caller (param i32 i32)))
(import "seal0" "seal_value_transferred" (func $seal_value_transferred (param i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) storage key
(data (i32.const 0) "\01")
;; [32, 64) buffer for transferred value
;; [64, 96) size of the buffer for transferred value
(data (i32.const 64) "\20")
;; [96, 128) buffer for the caller
;; [128, 160) size of the buffer for caller
(data (i32.const 128) "\20")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
;; place a value in storage
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.const 32) ;; Size of value
)
;; This stores the value transferred in the buffer
(call $seal_value_transferred (i32.const 32) (i32.const 64))
;; assert len == 8
(call $assert
(i32.eq
(i32.load (i32.const 64))
(i32.const 8)
)
)
;; assert that contents of the buffer is equal to the value
;; passed to the `caller` contract: 1337
(call $assert
(i64.eq
(i64.load (i32.const 32))
(i64.const 1337)
)
)
;; fill the buffer with the caller.
(call $seal_caller (i32.const 96) (i32.const 128))
;; assert len == 32
(call $assert
(i32.eq
(i32.load (i32.const 128))
(i32.const 32)
)
)
;; assert that the first 64 byte are the beginning of "ALICE",
;; who is the caller of the `caller` contract
(call $assert
(i64.eq
(i64.load (i32.const 96))
(i64.const 0x0101010101010101)
)
)
)
(func (export "deploy"))
)
@@ -0,0 +1,50 @@
;; Just delegate call into the passed code hash and assert success.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 3 3))
;; [0, 32) buffer where input is copied
;; [32, 36) size of the input buffer
(data (i32.const 32) "\20")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
;; Reading "callee" code_hash
(call $seal_input (i32.const 0) (i32.const 32))
;; assert input size == 32
(call $assert
(i32.eq
(i32.load (i32.const 32))
(i32.const 32)
)
)
;; Delegate call into passed code hash
(call $assert
(i32.eq
(call $seal_delegate_call
(i32.const 0) ;; Set no call flags
(i32.const 0) ;; Pointer to "callee" code_hash.
(i32.const 0) ;; Input is ignored
(i32.const 0) ;; Length of the input
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
(i32.const 0)
)
)
)
(func (export "deploy"))
)
@@ -0,0 +1,161 @@
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32)))
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
(import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32)))
(import "seal0" "seal_instantiate" (func $seal_instantiate
(param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
))
(import "env" "memory" (memory 1 1))
;; [0, 8) value to send when creating contract.
(data (i32.const 0) "\00\00\01")
;; [8, 16) Value to send when calling contract.
;; [16, 48) The key to store the contract address under.
;; [48, 80) Buffer where to store the input to the contract
;; [88, 96) Size of the buffer
(data (i32.const 88) "\FF")
;; [96, 100) Size of the input buffer
(data (i32.const 96) "\20")
;; [100, 132) Buffer where to store the address of the instantiated contract
;; [132, 134) Salt
(data (i32.const 132) "\47\11")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy")
;; Input data is the code hash of the contract to be deployed.
(call $seal_input (i32.const 48) (i32.const 96))
(call $assert
(i32.eq
(i32.load (i32.const 96))
(i32.const 32)
)
)
;; Deploy the contract with the provided code hash.
(call $assert
(i32.eq
(call $seal_instantiate
(i32.const 48) ;; Pointer to the code hash.
(i32.const 32) ;; Length of the code hash.
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Length of the buffer with value to transfer.
(i32.const 0) ;; Pointer to input data buffer address
(i32.const 0) ;; Length of input data buffer
(i32.const 100) ;; Buffer where to store address of new contract
(i32.const 88) ;; Pointer to the length of the buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
(i32.const 132) ;; salt_ptr
(i32.const 2) ;; salt_len
)
(i32.const 0)
)
)
;; Check that address has expected length
(call $assert
(i32.eq
(i32.load (i32.const 88))
(i32.const 32)
)
)
;; Store the return address.
(call $seal_set_storage
(i32.const 16) ;; Pointer to the key
(i32.const 100) ;; Pointer to the value
(i32.const 32) ;; Length of the value
)
)
(func (export "call")
;; Read address of destination contract from storage.
(call $assert
(i32.eq
(call $seal_get_storage
(i32.const 16) ;; Pointer to the key
(i32.const 100) ;; Pointer to the value
(i32.const 88) ;; Pointer to the len of the value
)
(i32.const 0)
)
)
(call $assert
(i32.eq
(i32.load (i32.const 88))
(i32.const 32)
)
)
;; Calling the destination contract with non-empty input data should fail.
(call $assert
(i32.eq
(call $seal_call
(i32.const 100) ;; Pointer to destination address
(i32.const 32) ;; Length of destination address
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Length of the buffer with value to transfer
(i32.const 0) ;; Pointer to input data buffer address
(i32.const 1) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
(i32.const 0x1)
)
)
;; Call the destination contract regularly, forcing it to self-destruct.
(call $assert
(i32.eq
(call $seal_call
(i32.const 100) ;; Pointer to destination address
(i32.const 32) ;; Length of destination address
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 8) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Length of the buffer with value to transfer
(i32.const 0) ;; Pointer to input data buffer address
(i32.const 0) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
(i32.const 0)
)
)
;; Calling the destination address with non-empty input data should now work since the
;; contract has been removed. Also transfer a balance to the address so we can ensure this
;; does not hinder the contract from being removed.
(call $assert
(i32.eq
(call $seal_transfer
(i32.const 100) ;; Pointer to destination address
(i32.const 32) ;; Length of destination address
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Length of the buffer with value to transfer
)
(i32.const 0)
)
)
)
)
@@ -0,0 +1,75 @@
(module
(import "seal0" "seal_balance" (func $seal_balance (param i32 i32)))
(import "seal0" "seal_minimum_balance" (func $seal_minimum_balance (param i32 i32)))
(import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; [0, 8) reserved for $seal_balance output
;; [8, 16) length of the buffer for $seal_balance
(data (i32.const 8) "\08")
;; [16, 24) reserved for $seal_minimum_balance
;; [24, 32) length of the buffer for $seal_minimum_balance
(data (i32.const 24) "\08")
;; [32, inf) zero initialized
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy"))
(func (export "call")
;; Send entire remaining balance to the 0 address.
(call $seal_balance (i32.const 0) (i32.const 8))
;; Balance should be encoded as a u64.
(call $assert
(i32.eq
(i32.load (i32.const 8))
(i32.const 8)
)
)
;; Get the minimum balance.
(call $seal_minimum_balance (i32.const 16) (i32.const 24))
;; Minimum balance should be encoded as a u64.
(call $assert
(i32.eq
(i32.load (i32.const 24))
(i32.const 8)
)
)
;; Make the transferred value exceed the balance by adding the minimum balance.
(i64.store (i32.const 0)
(i64.add
(i64.load (i32.const 0))
(i64.load (i32.const 16))
)
)
;; Try to self-destruct by sending more balance to the 0 address.
;; The call will fail because a contract transfer has a keep alive requirement
(call $assert
(i32.eq
(call $seal_transfer
(i32.const 32) ;; Pointer to destination address
(i32.const 48) ;; Length of destination address
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Length of the buffer with value to transfer
)
(i32.const 5) ;; ReturnCode::TransferFailed
)
)
)
)
@@ -0,0 +1,6 @@
;; A valid contract which does nothing at all
(module
(import "env" "memory" (memory 1 1))
(func (export "deploy"))
(func (export "call"))
)
@@ -0,0 +1,55 @@
;; This contract:
;; 1) Reads signature and message hash from the input
;; 2) Calls ecdsa_recover
;; 3) Validates that result is Success
;; 4) Returns recovered compressed public key
(module
(import "seal0" "seal_ecdsa_recover" (func $seal_ecdsa_recover (param i32 i32 i32) (result i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 1 1))
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy"))
;; [4, 8) len of signature + message hash - 65 bytes + 32 byte = 97 bytes
(data (i32.const 4) "\61")
;; Memory layout during `call`
;; [10, 75) signature
;; [75, 107) message hash
(func (export "call")
(local $signature_ptr i32)
(local $message_hash_ptr i32)
(local $result i32)
(local.set $signature_ptr (i32.const 10))
(local.set $message_hash_ptr (i32.const 75))
;; Read signature and message hash - 97 bytes
(call $seal_input (local.get $signature_ptr) (i32.const 4))
(local.set
$result
(call $seal_ecdsa_recover
(local.get $signature_ptr)
(local.get $message_hash_ptr)
(local.get $signature_ptr) ;; Store output into message signature ptr, because we don't need it anymore
)
)
(call $assert
(i32.eq
(local.get $result) ;; The result of recovery execution
(i32.const 0x0) ;; 0x0 - Success result
)
)
;; exit with success and return recovered public key
(call $seal_return (i32.const 0) (local.get $signature_ptr) (i32.const 33))
)
)
@@ -0,0 +1,26 @@
(module
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
(import "env" "memory" (memory 1 1))
(func (export "deploy")
(call $seal_deposit_event
(i32.const 0) ;; The topics buffer
(i32.const 0) ;; The topics buffer's length
(i32.const 8) ;; The data buffer
(i32.const 4) ;; The data buffer's length
)
(call $seal_return
(i32.const 0)
(i32.const 8)
(i32.const 4)
)
(unreachable)
)
(func (export "call")
(unreachable)
)
(data (i32.const 8) "\01\02\03\04")
)
@@ -0,0 +1,39 @@
(module
(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 16 16))
;; [0, 4) size of the input buffer
(data (i32.const 0) "\04")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(call $seal_input (i32.const 4) (i32.const 0))
;; assert input size == 4
(call $assert
(i32.eq
(i32.load (i32.const 0))
(i32.const 4)
)
)
;; place a garbage value in storage, the size of which is specified by the call input.
(call $seal_deposit_event
(i32.const 0) ;; topics_ptr
(i32.const 0) ;; topics_len
(i32.const 0) ;; data_ptr
(i32.load (i32.const 4)) ;; data_len
)
)
(func (export "deploy"))
)
@@ -0,0 +1,12 @@
;; Module that contains a float instruction which is illegal in deterministic mode
(module
(import "env" "memory" (memory 1 1))
(func (export "call")
f32.const 1
drop
)
(func (export "deploy")
f32.const 2
drop
)
)
@@ -0,0 +1,47 @@
;; This instantiats a contract and transfers 100 balance during this call and copies the return code
;; of this call to the output buffer.
;; The first 32 byte of input is the code hash to instantiate
;; The rest of the input is forwarded to the constructor of the callee
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal1" "seal_instantiate" (func $seal_instantiate
(param i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 8) 10_000 balance
(data (i32.const 0) "\10\27\00\00\00\00\00\00")
;; [8, 12) here we store the return code of the transfer
;; [12, 16) size of the input buffer
(data (i32.const 12) "\24")
;; [16, inf) input buffer
;; 32 bye code hash + 4 byte forward
(func (export "deploy"))
(func (export "call")
(call $seal_input (i32.const 16) (i32.const 12))
(i32.store
(i32.const 8)
(call $seal_instantiate
(i32.const 16) ;; Pointer to the code hash.
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 48) ;; Pointer to input data buffer address
(i32.const 4) ;; Length of input data buffer
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy address
(i32.const 0) ;; Length is ignored in this case
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
(i32.const 0) ;; salt_ptr
(i32.const 0) ;; salt_len
)
)
;; exit with success and take transfer return code to the output buffer
(call $seal_return (i32.const 0) (i32.const 8) (i32.const 4))
)
)
@@ -0,0 +1,5 @@
;; Valid module but missing the call function
(module
(import "env" "memory" (memory 1 1))
(func (export "deploy"))
)
@@ -0,0 +1,5 @@
;; A valid contract which does nothing at all
(module
(func (export "deploy"))
(func (export "call"))
)
@@ -0,0 +1,8 @@
;; An invalid module
(module
(func (export "deploy"))
(func (export "call")
;; imbalanced stack
(i32.const 7)
)
)
@@ -0,0 +1,54 @@
;; Does two stores to two seperate storage items
;; Expects (len0, len1) as input.
(module
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 16 16))
;; [0, 32) storage key 0
(data (i32.const 0) "\01")
;; [32, 64) storage key 1
(data (i32.const 32) "\02")
;; [64, 72) buffer where input is copied (expected sizes of storage items)
;; [72, 76) size of the input buffer
(data (i32.const 72) "\08")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(call $seal_input (i32.const 64) (i32.const 72))
;; assert input size == 8
(call $assert
(i32.eq
(i32.load (i32.const 72))
(i32.const 8)
)
)
;; place a values in storage sizes are specified in the input buffer
;; we don't care about the contents of the storage item
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.load (i32.const 64)) ;; Size of value
)
(call $seal_set_storage
(i32.const 32) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.load (i32.const 68)) ;; Size of value
)
)
(func (export "deploy"))
)
@@ -0,0 +1,13 @@
(module
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) return value
(data (i32.const 0) "\02")
(func (export "deploy"))
(func (export "call")
(call $seal_return (i32.const 0) (i32.const 0) (i32.const 4))
)
)
@@ -0,0 +1,35 @@
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
(func (export "deploy")
(call $ok_trap_revert)
)
(func (export "call")
(call $ok_trap_revert)
)
(func $ok_trap_revert
(i32.store (i32.const 4) (i32.const 4))
(call $seal_input (i32.const 0) (i32.const 4))
(block $IF_2
(block $IF_1
(block $IF_0
(br_table $IF_0 $IF_1 $IF_2
(i32.load8_u (i32.const 0))
)
(unreachable)
)
;; 0 = return with success
return
)
;; 1 = revert
(call $seal_return (i32.const 1) (i32.const 0) (i32.const 0))
(unreachable)
)
;; 2 = trap
(unreachable)
)
)
@@ -0,0 +1,76 @@
;; This fixture recursively tests if reentrance_count returns correct reentrant count value when
;; using seal_call to make caller contract call to itself
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_address" (func $seal_address (param i32 i32)))
(import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32)))
(import "seal0" "reentrance_count" (func $reentrance_count (result i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) reserved for $seal_address output
;; [32, 36) buffer for the call stack height
;; [36, 40) size of the input buffer
(data (i32.const 36) "\04")
;; [40, 44) length of the buffer for $seal_address
(data (i32.const 40) "\20")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(local $expected_reentrance_count i32)
(local $seal_call_exit_code i32)
;; reading current contract address
(call $seal_address (i32.const 0) (i32.const 40))
;; reading passed input
(call $seal_input (i32.const 32) (i32.const 36))
;; reading manually passed reentrant count
(set_local $expected_reentrance_count (i32.load (i32.const 32)))
;; reentrance count is calculated correctly
(call $assert
(i32.eq (call $reentrance_count) (get_local $expected_reentrance_count))
)
;; re-enter 5 times in a row and assert that the reentrant counter works as expected
(i32.eq (call $reentrance_count) (i32.const 5))
(if
(then) ;; recursion exit case
(else
;; incrementing $expected_reentrance_count passed to the contract
(i32.store (i32.const 32) (i32.add (i32.load (i32.const 32)) (i32.const 1)))
;; Call to itself
(set_local $seal_call_exit_code
(call $seal_call
(i32.const 8) ;; Allow reentrancy flag set
(i32.const 0) ;; Pointer to "callee" address
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 0) ;; Pointer to the buffer with value to transfer
(i32.const 32) ;; Pointer to input data buffer address
(i32.const 4) ;; Length of input data buffer
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Ptr to output buffer len
)
)
(call $assert
(i32.eq (get_local $seal_call_exit_code) (i32.const 0))
)
)
)
)
(func (export "deploy"))
)
@@ -0,0 +1,71 @@
;; This fixture recursively tests if reentrance_count returns correct reentrant count value when
;; using seal_delegate_call to make caller contract delegate call to itself
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32)))
(import "seal0" "reentrance_count" (func $reentrance_count (result i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) buffer where code hash is copied
;; [32, 36) buffer for the call stack height
;; [36, 40) size of the input buffer
(data (i32.const 36) "\24")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(local $callstack_height i32)
(local $delegate_call_exit_code i32)
;; Reading input
(call $seal_input (i32.const 0) (i32.const 36))
;; reading passed callstack height
(set_local $callstack_height (i32.load (i32.const 32)))
;; incrementing callstack height
(i32.store (i32.const 32) (i32.add (i32.load (i32.const 32)) (i32.const 1)))
;; reentrance count stays 0
(call $assert
(i32.eq (call $reentrance_count) (i32.const 0))
)
(i32.eq (get_local $callstack_height) (i32.const 5))
(if
(then) ;; exit recursion case
(else
;; Call to itself
(set_local $delegate_call_exit_code
(call $seal_delegate_call
(i32.const 0) ;; Set no call flags
(i32.const 0) ;; Pointer to "callee" code_hash.
(i32.const 0) ;; Pointer to the input data
(i32.const 36) ;; Length of the input
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
)
(call $assert
(i32.eq (get_local $delegate_call_exit_code) (i32.const 0))
)
)
)
(call $assert
(i32.le_s (get_local $callstack_height) (i32.const 5))
)
)
(func (export "deploy"))
)
@@ -0,0 +1,33 @@
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 128) buffer where input is copied
;; [128, 132) length of the input buffer
(data (i32.const 128) "\80")
;; Deploy routine is the same as call.
(func (export "deploy")
(call $call)
)
;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data.
(func $call (export "call")
;; Copy input into this contracts memory.
(call $seal_input (i32.const 0) (i32.const 128))
;; Copy all but the first 4 bytes of the input data as the output data.
;; Use the first byte as exit status
(call $seal_return
(i32.load8_u (i32.const 0)) ;; Exit status
(i32.const 4) ;; Pointer to the data to return.
(i32.sub ;; Count of bytes to copy.
(i32.load (i32.const 128))
(i32.const 4)
)
)
(unreachable)
)
)
@@ -0,0 +1,8 @@
(module
(import "env" "memory" (memory 1 1))
(func (export "call")
(loop $inf (br $inf)) ;; just run out of gas
(unreachable)
)
(func (export "deploy"))
)
@@ -0,0 +1,10 @@
(module
(import "env" "memory" (memory 1 1))
(start $start)
(func $start
(loop $inf (br $inf)) ;; just run out of gas
(unreachable)
)
(func (export "call"))
(func (export "deploy"))
)
@@ -0,0 +1,14 @@
;; Everything prepared for the host function call, but no call is performed.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 8) buffer to write input
;; [8, 12) size of the input buffer
(data (i32.const 8) "\04")
(func (export "call"))
(func (export "deploy"))
)
@@ -0,0 +1,22 @@
;; Stores a value of the passed size. The host function is called once.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 8) buffer to write input
;; [8, 12) size of the input buffer
(data (i32.const 8) "\04")
(func (export "call")
;; instructions to consume engine fuel
(drop
(i32.const 42)
)
(call $seal_input (i32.const 0) (i32.const 8))
)
(func (export "deploy"))
)
@@ -0,0 +1,28 @@
;; Stores a value of the passed size. The host function is called twice.
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 8) buffer to write input
;; [8, 12) size of the input buffer
(data (i32.const 8) "\04")
(func (export "call")
;; instructions to consume engine fuel
(drop
(i32.const 42)
)
(call $seal_input (i32.const 0) (i32.const 8))
;; instructions to consume engine fuel
(drop
(i32.const 42)
)
(call $seal_input (i32.const 0) (i32.const 8))
)
(func (export "deploy"))
)
@@ -0,0 +1,83 @@
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_address" (func $seal_address (param i32 i32)))
(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
(import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) reserved for $seal_address output
;; [32, 36) length of the buffer
(data (i32.const 32) "\20")
;; [36, 68) Address of django
(data (i32.const 36)
"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04"
"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04"
)
;; [68, 72) reserved for output of $seal_input
;; [72, 76) length of the buffer
(data (i32.const 72) "\04")
;; [76, inf) zero initialized
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy"))
(func (export "call")
;; If the input data is not empty, then recursively call self with empty input data.
;; This should trap instead of self-destructing since a contract cannot be removed live in
;; the execution stack cannot be removed. If the recursive call traps, then trap here as
;; well.
(call $seal_input (i32.const 68) (i32.const 72))
(if (i32.load (i32.const 72))
(then
(call $seal_address (i32.const 0) (i32.const 32))
;; Expect address to be 8 bytes.
(call $assert
(i32.eq
(i32.load (i32.const 32))
(i32.const 32)
)
)
;; Recursively call self with empty input data.
(call $assert
(i32.eq
(call $seal_call
(i32.const 0) ;; Pointer to own address
(i32.const 32) ;; Length of own address
(i64.const 0) ;; How much gas to devote for the execution. 0 = all.
(i32.const 76) ;; Pointer to the buffer with value to transfer
(i32.const 8) ;; Length of the buffer with value to transfer
(i32.const 0) ;; Pointer to input data buffer address
(i32.const 0) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
(i32.const 0)
)
)
)
(else
;; Try to terminate and give balance to django.
(call $seal_terminate
(i32.const 36) ;; Pointer to beneficiary address
(i32.const 32) ;; Length of beneficiary address
)
(unreachable) ;; seal_terminate never returns
)
)
)
)
@@ -0,0 +1,23 @@
(module
(import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32)))
(import "env" "memory" (memory 1 1))
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy")
;; Self-destruct by sending full balance to the 0 address.
(call $seal_terminate
(i32.const 0) ;; Pointer to destination address
(i32.const 32) ;; Length of destination address
)
)
(func (export "call"))
)
@@ -0,0 +1,43 @@
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "seal0" "seal_set_code_hash" (func $seal_set_code_hash (param i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) here we store input
;; [32, 36) input size
(data (i32.const 32) "\20")
;; [36, 40) return value
(data (i32.const 36) "\01")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(local $exit_code i32)
(call $seal_input (i32.const 0) (i32.const 32))
(set_local $exit_code
(call $seal_set_code_hash (i32.const 0)) ;; Pointer to the input data.
)
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
)
;; we return 1 after setting new code_hash
;; next `call` will NOT return this value, because contract code has been changed
(call $seal_return (i32.const 0) (i32.const 36) (i32.const 4))
)
(func (export "deploy"))
)
@@ -0,0 +1,15 @@
;; This module stores a KV pair into the storage
(module
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "env" "memory" (memory 16 16))
(func (export "call")
)
(func (export "deploy")
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.load (i32.const 0)) ;; Size of value
)
)
)
@@ -0,0 +1,55 @@
;; This contract:
;; 1) Reads signature, message and public key from the input
;; 2) Calls and return the result of sr25519_verify
(module
;; import the host functions from the seal0 module
(import "seal0" "sr25519_verify" (func $sr25519_verify (param i32 i32 i32 i32) (result i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
;; give the program 1 page of memory
(import "env" "memory" (memory 1 1))
;; [0, 4) length of signature + message + public key - 64 + 11 + 32 = 107 bytes
;; write the length of the input (6b = 107) bytes at offset 0
(data (i32.const 0) "\6b")
(func (export "deploy"))
(func (export "call")
;; define local variables
(local $signature_ptr i32)
(local $pub_key_ptr i32)
(local $message_len i32)
(local $message_ptr i32)
;; set the pointers to the memory locations
;; Memory layout during `call`
;; [10, 74) signature
;; [74, 106) public key
;; [106, 117) message (11 bytes)
(local.set $signature_ptr (i32.const 10))
(local.set $pub_key_ptr (i32.const 74))
(local.set $message_ptr (i32.const 106))
;; store the input into the memory, starting at the signature and
;; up to 107 bytes stored at offset 0
(call $seal_input (local.get $signature_ptr) (i32.const 0))
;; call sr25519_verify and store the return code
(i32.store
(i32.const 0)
(call $sr25519_verify
(local.get $signature_ptr)
(local.get $pub_key_ptr)
(i32.const 11)
(local.get $message_ptr)
)
)
;; exit with success and take transfer return code to the output buffer
(call $seal_return (i32.const 0) (i32.const 0) (i32.const 4))
)
)
@@ -0,0 +1,68 @@
(module
(import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32)))
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 16 16))
;; [0, 32) storage key
(data (i32.const 0) "\01")
;; [32, 36) buffer where input is copied (expected size of storage item)
;; [36, 40) size of the input buffer
(data (i32.const 36) "\04")
;; [40, 44) size of buffer for seal_get_storage set to max
(data (i32.const 40) "\FF\FF\FF\FF")
;; [44, inf) seal_get_storage buffer
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(call $seal_input (i32.const 32) (i32.const 36))
;; assert input size == 4
(call $assert
(i32.eq
(i32.load (i32.const 36))
(i32.const 4)
)
)
;; place a garbage value in storage, the size of which is specified by the call input.
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.load (i32.const 32)) ;; Size of value
)
(call $assert
(i32.eq
(call $seal_get_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 44) ;; buffer where to copy result
(i32.const 40) ;; pointer to size of buffer
)
(i32.const 0)
)
)
(call $assert
(i32.eq
(i32.load (i32.const 40))
(i32.load (i32.const 32))
)
)
)
(func (export "deploy"))
)
@@ -0,0 +1,45 @@
;; Stores a value of the passed size.
(module
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 16 16))
;; [0, 32) storage key
(data (i32.const 0) "\01")
;; [32, 36) buffer where input is copied (expected size of storage item)
;; [36, 40) size of the input buffer
(data (i32.const 36) "\04")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(call $seal_input (i32.const 32) (i32.const 36))
;; assert input size == 4
(call $assert
(i32.eq
(i32.load (i32.const 36))
(i32.const 4)
)
)
;; place a value in storage, the size of which is specified by the call input.
;; we don't care about the contents of the storage item
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.load (i32.const 32)) ;; Size of value
)
)
(func (export "deploy"))
)
@@ -0,0 +1,45 @@
;; Stores a value of the passed size in constructor.
(module
(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "env" "memory" (memory 16 16))
;; [0, 32) storage key
(data (i32.const 0) "\01")
;; [32, 36) buffer where input is copied (expected size of storage item)
;; [36, 40) size of the input buffer
(data (i32.const 36) "\04")
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "deploy")
(call $seal_input (i32.const 32) (i32.const 36))
;; assert input size == 4
(call $assert
(i32.eq
(i32.load (i32.const 36))
(i32.const 4)
)
)
;; place a value in storage, the size of which is specified by the call input.
;; we don't care about the contents of the storage item
(call $seal_set_storage
(i32.const 0) ;; Pointer to storage key
(i32.const 0) ;; Pointer to value
(i32.load (i32.const 32)) ;; Size of value
)
)
(func (export "call"))
)
@@ -0,0 +1,34 @@
;; This transfers 100 balance to the zero account and copies the return code
;; of this transfer to the output buffer.
(module
(import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) zero-adress
(data (i32.const 0)
"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
)
;; [32, 40) 100 balance
(data (i32.const 32) "\64\00\00\00\00\00\00\00")
;; [40, 44) here we store the return code of the transfer
(func (export "deploy"))
(func (export "call")
(i32.store
(i32.const 40)
(call $seal_transfer
(i32.const 0) ;; ptr to destination address
(i32.const 32) ;; length of destination address
(i32.const 32) ;; ptr to value to transfer
(i32.const 8) ;; length of value to transfer
)
)
;; exit with success and take transfer return code to the output buffer
(call $seal_return (i32.const 0) (i32.const 40) (i32.const 4))
)
)