1(module2 (import "seal0" "seal_input" (func $seal_input (param i32 i32)))3 (import "seal0" "seal_balance" (func $seal_balance (param i32 i32)))4 (import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))5 (import "seal0" "seal_instantiate" (func $seal_instantiate6 (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)7 ))8 (import "seal0" "seal_println" (func $seal_println (param i32 i32)))9 (import "env" "memory" (memory 1 1))1011 (func $assert (param i32)12 (block $ok13 (br_if $ok14 (get_local 0)15 )16 (unreachable)17 )18 )1920 (func $current_balance (param $sp i32) (result i64)21 (i32.store22 (i32.sub (get_local $sp) (i32.const 16))23 (i32.const 8)24 )25 (call $seal_balance26 (i32.sub (get_local $sp) (i32.const 8))27 (i32.sub (get_local $sp) (i32.const 16))28 )29 (call $assert30 (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 16))) (i32.const 8))31 )32 (i64.load (i32.sub (get_local $sp) (i32.const 8)))33 )3435 (func (export "deploy"))3637 (func (export "call")38 (local $sp i32)39 (local $exit_code i32)40 (local $balance i64)4142 ;; Length of the buffer43 (i32.store (i32.const 20) (i32.const 32))4445 ;; Copy input to this contracts memory46 (call $seal_input (i32.const 24) (i32.const 20))4748 ;; Input data is the code hash of the contract to be deployed.49 (call $assert50 (i32.eq51 (i32.load (i32.const 20))52 (i32.const 32)53 )54 )5556 ;; Read current balance into local variable.57 (set_local $sp (i32.const 1024))58 (set_local $balance59 (call $current_balance (get_local $sp))60 )6162 ;; Fail to deploy the contract since it returns a non-zero exit status.63 (set_local $exit_code64 (call $seal_instantiate65 (i32.const 24) ;; Pointer to the code hash.66 (i32.const 32) ;; Length of the code hash.67 (i64.const 0) ;; How much gas to devote for the execution. 0 = all.68 (i32.const 0) ;; Pointer to the buffer with value to transfer69 (i32.const 8) ;; Length of the buffer with value to transfer.70 (i32.const 9) ;; Pointer to input data buffer address71 (i32.const 7) ;; Length of input data buffer72 (i32.const 4294967295) ;; u32 max sentinel value: do not copy address73 (i32.const 0) ;; Length is ignored in this case74 (i32.const 4294967295) ;; u32 max sentinel value: do not copy output75 (i32.const 0) ;; Length is ignored in this case76 (i32.const 0) ;; salt_ptr77 (i32.const 0) ;; salt_le78 )79 )8081 ;; Check non-zero exit status.82 (call $assert83 (i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted84 )8586 ;; Check that balance has not changed.87 (call $assert88 (i64.eq (get_local $balance) (call $current_balance (get_local $sp)))89 )9091 ;; Fail to deploy the contract due to insufficient gas.92 (set_local $exit_code93 (call $seal_instantiate94 (i32.const 24) ;; Pointer to the code hash.95 (i32.const 32) ;; Length of the code hash.96 (i64.const 1) ;; Supply too little gas97 (i32.const 0) ;; Pointer to the buffer with value to transfer98 (i32.const 8) ;; Length of the buffer with value to transfer.99 (i32.const 8) ;; Pointer to input data buffer address100 (i32.const 8) ;; Length of input data buffer101 (i32.const 4294967295) ;; u32 max sentinel value: do not copy address102 (i32.const 0) ;; Length is ignored in this case103 (i32.const 4294967295) ;; u32 max sentinel value: do not copy output104 (i32.const 0) ;; Length is ignored in this case105 (i32.const 0) ;; salt_ptr106 (i32.const 0) ;; salt_le107108 )109 )110111 ;; Check for special trap exit status.112 (call $assert113 (i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped114 )115116 ;; Check that balance has not changed.117 (call $assert118 (i64.eq (get_local $balance) (call $current_balance (get_local $sp)))119 )120121 ;; Length of the output buffer122 (i32.store123 (i32.sub (get_local $sp) (i32.const 4))124 (i32.const 256)125 )126127 ;; Deploy the contract successfully.128 (set_local $exit_code129 (call $seal_instantiate130 (i32.const 24) ;; Pointer to the code hash.131 (i32.const 32) ;; Length of the code hash.132 (i64.const 0) ;; How much gas to devote for the execution. 0 = all.133 (i32.const 0) ;; Pointer to the buffer with value to transfer134 (i32.const 8) ;; Length of the buffer with value to transfer.135 (i32.const 8) ;; Pointer to input data buffer address136 (i32.const 8) ;; Length of input data buffer137 (i32.const 16) ;; Pointer to the address output buffer138 (i32.sub (get_local $sp) (i32.const 4)) ;; Pointer to the address buffer length139 (i32.const 4294967295) ;; u32 max sentinel value: do not copy output140 (i32.const 0) ;; Length is ignored in this case141 (i32.const 0) ;; salt_ptr142 (i32.const 0) ;; salt_le143144 )145 )146147 ;; Check for success exit status.148 (call $assert149 (i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success150 )151152 ;; Check that address has the expected length153 (call $assert154 (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 4))) (i32.const 32))155 )156157 ;; Check that balance has been deducted.158 (set_local $balance159 (i64.sub (get_local $balance) (i64.load (i32.const 0)))160 )161 (call $assert162 (i64.eq (get_local $balance) (call $current_balance (get_local $sp)))163 )164165 ;; Zero out destination buffer of output166 (i32.store167 (i32.sub (get_local $sp) (i32.const 4))168 (i32.const 0)169 )170171 ;; Length of the output buffer172 (i32.store173 (i32.sub (get_local $sp) (i32.const 8))174 (i32.const 4)175 )176177 ;; Call the new contract and expect it to return failing exit code.178 (set_local $exit_code179 (call $seal_call180 (i32.const 16) ;; Pointer to "callee" address.181 (i32.const 32) ;; Length of "callee" address.182 (i64.const 0) ;; How much gas to devote for the execution. 0 = all.183 (i32.const 0) ;; Pointer to the buffer with value to transfer184 (i32.const 8) ;; Length of the buffer with value to transfer.185 (i32.const 9) ;; Pointer to input data buffer address186 (i32.const 7) ;; Length of input data buffer187 (i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer188 (i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len189 )190 )191192 ;; Check non-zero exit status.193 (call $assert194 (i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted195 )196197 ;; Check that output buffer contains the expected return data.198 (call $assert199 (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 3))200 )201 (call $assert202 (i32.eq203 (i32.load (i32.sub (get_local $sp) (i32.const 4)))204 (i32.const 0x00776655)205 )206 )207208 ;; Check that balance has not changed.209 (call $assert210 (i64.eq (get_local $balance) (call $current_balance (get_local $sp)))211 )212213 ;; Fail to call the contract due to insufficient gas.214 (set_local $exit_code215 (call $seal_call216 (i32.const 16) ;; Pointer to "callee" address.217 (i32.const 32) ;; Length of "callee" address.218 (i64.const 1) ;; Supply too little gas219 (i32.const 0) ;; Pointer to the buffer with value to transfer220 (i32.const 8) ;; Length of the buffer with value to transfer.221 (i32.const 8) ;; Pointer to input data buffer address222 (i32.const 8) ;; Length of input data buffer223 (i32.const 4294967295) ;; u32 max sentinel value: do not copy output224 (i32.const 0) ;; Length is ignored in this cas225 )226 )227228 ;; Check for special trap exit status.229 (call $assert230 (i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped231 )232233 ;; Check that balance has not changed.234 (call $assert235 (i64.eq (get_local $balance) (call $current_balance (get_local $sp)))236 )237238 ;; Zero out destination buffer of output239 (i32.store240 (i32.sub (get_local $sp) (i32.const 4))241 (i32.const 0)242 )243244 ;; Length of the output buffer245 (i32.store246 (i32.sub (get_local $sp) (i32.const 8))247 (i32.const 4)248 )249250 ;; Call the contract successfully.251 (set_local $exit_code252 (call $seal_call253 (i32.const 16) ;; Pointer to "callee" address.254 (i32.const 32) ;; Length of "callee" address.255 (i64.const 0) ;; How much gas to devote for the execution. 0 = all.256 (i32.const 0) ;; Pointer to the buffer with value to transfer257 (i32.const 8) ;; Length of the buffer with value to transfer.258 (i32.const 8) ;; Pointer to input data buffer address259 (i32.const 8) ;; Length of input data buffer260 (i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer261 (i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len262 )263 )264265 ;; Check for success exit status.266 (call $assert267 (i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success268 )269270 ;; Check that the output buffer contains the expected return data.271 (call $assert272 (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 4))273 )274 (call $assert275 (i32.eq276 (i32.load (i32.sub (get_local $sp) (i32.const 4)))277 (i32.const 0x77665544)278 )279 )280281 ;; Check that balance has been deducted.282 (set_local $balance283 (i64.sub (get_local $balance) (i64.load (i32.const 0)))284 )285 (call $assert286 (i64.eq (get_local $balance) (call $current_balance (get_local $sp)))287 )288 )289290 (data (i32.const 0) "\00\80") ;; The value to transfer on instantiation and calls.291 ;; Chosen to be greater than existential deposit.292 (data (i32.const 8) "\00\01\22\33\44\55\66\77") ;; The input data to instantiations and calls.293)