github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/evm/evm_test.go (about) 1 // Copyright Monax Industries Limited 2 // SPDX-License-Identifier: Apache-2.0 3 4 package evm 5 6 import ( 7 "bytes" 8 "encoding/binary" 9 "math/big" 10 "reflect" 11 "testing" 12 "time" 13 14 "github.com/hyperledger/burrow/acm" 15 "github.com/hyperledger/burrow/acm/acmstate" 16 . "github.com/hyperledger/burrow/binary" 17 "github.com/hyperledger/burrow/crypto" 18 "github.com/hyperledger/burrow/execution/engine" 19 "github.com/hyperledger/burrow/execution/errors" 20 "github.com/hyperledger/burrow/execution/evm/abi" 21 . "github.com/hyperledger/burrow/execution/evm/asm" 22 . "github.com/hyperledger/burrow/execution/evm/asm/bc" 23 "github.com/hyperledger/burrow/execution/exec" 24 "github.com/hyperledger/burrow/execution/native" 25 "github.com/hyperledger/burrow/execution/solidity" 26 "github.com/hyperledger/burrow/txs" 27 "github.com/stretchr/testify/assert" 28 "github.com/stretchr/testify/require" 29 "github.com/tmthrgd/go-hex" 30 ) 31 32 // Test output is a bit clearer if we /dev/null the logging, but can be re-enabled by uncommenting the below 33 //var logger, _, _ = lifecycle.NewStdErrLogger() 34 35 // Runs a basic loop 36 func TestEVM(t *testing.T) { 37 vm := New(engine.Options{ 38 Natives: native.MustDefaultNatives(), 39 }) 40 41 t.Run("BasicLoop", func(t *testing.T) { 42 st := acmstate.NewMemoryState() 43 blockchain := new(engine.TestBlockchain) 44 eventSink := exec.NewNoopEventSink() 45 46 // Create accounts 47 account1 := newAccount(t, st, "1") 48 account2 := newAccount(t, st, "101") 49 50 bytecode := MustSplice(PUSH1, 0x00, PUSH1, 0x20, MSTORE, JUMPDEST, PUSH2, 0x0F, 0x0F, PUSH1, 0x20, MLOAD, 51 SLT, ISZERO, PUSH1, 0x1D, JUMPI, PUSH1, 0x01, PUSH1, 0x20, MLOAD, ADD, PUSH1, 0x20, 52 MSTORE, PUSH1, 0x05, JUMP, JUMPDEST) 53 54 start := time.Now() 55 output, err := vm.Execute(st, blockchain, eventSink, engine.CallParams{ 56 Caller: account1, 57 Callee: account2, 58 Gas: big.NewInt(100000), 59 }, bytecode) 60 t.Logf("Output: %v Error: %v\n", output, err) 61 t.Logf("Call took: %v", time.Since(start)) 62 require.NoError(t, err) 63 }) 64 65 t.Run("SHL", func(t *testing.T) { 66 st := acmstate.NewMemoryState() 67 account1 := newAccount(t, st, "1") 68 account2 := newAccount(t, st, "101") 69 70 gas := big.NewInt(100000) 71 72 //Shift left 0 73 bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHL, return1()) 74 output, err := call(vm, st, account1, account2, bytecode, nil, gas) 75 value := []byte{0x1} 76 expected := LeftPadBytes(value, 32) 77 assert.Equal(t, expected, output) 78 79 t.Logf("Result: %v == %v\n", output, expected) 80 81 if err != nil { 82 t.Fatal(err) 83 } 84 85 //Alternative shift left 0 86 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 87 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHL, return1()) 88 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 89 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 90 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} 91 92 assert.Equal(t, expected, output) 93 94 t.Logf("Result: %v == %v\n", output, expected) 95 96 if err != nil { 97 t.Fatal(err) 98 } 99 100 //Shift left 1 101 bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHL, return1()) 102 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 103 value = []byte{0x2} 104 expected = LeftPadBytes(value, 32) 105 assert.Equal(t, expected, output) 106 107 t.Logf("Result: %v == %v\n", output, expected) 108 109 if err != nil { 110 t.Fatal(err) 111 } 112 113 //Alternative shift left 1 114 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 115 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1()) 116 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 117 value = []byte{0x2} 118 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 119 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE} 120 121 assert.Equal(t, expected, output) 122 123 t.Logf("Result: %v == %v\n", output, expected) 124 125 if err != nil { 126 t.Fatal(err) 127 } 128 129 //Alternative shift left 1 130 bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 131 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1()) 132 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 133 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 134 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE} 135 136 assert.Equal(t, expected, output) 137 138 t.Logf("Result: %v == %v\n", output, expected) 139 140 if err != nil { 141 t.Fatal(err) 142 } 143 144 //Shift left 255 145 bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0xFF, SHL, return1()) 146 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 147 value = []byte{0x80} 148 expected = RightPadBytes(value, 32) 149 assert.Equal(t, expected, output) 150 151 t.Logf("Result: %v == %v\n", output, expected) 152 153 if err != nil { 154 t.Fatal(err) 155 } 156 157 //Alternative shift left 255 158 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 159 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHL, return1()) 160 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 161 value = []byte{0x80} 162 expected = RightPadBytes(value, 32) 163 assert.Equal(t, expected, output) 164 165 t.Logf("Result: %v == %v\n", output, expected) 166 167 if err != nil { 168 t.Fatal(err) 169 } 170 171 //Shift left 256 (overflow) 172 bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x00, SHL, return1()) 173 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 174 value = []byte{0x00} 175 expected = LeftPadBytes(value, 32) 176 assert.Equal(t, expected, output) 177 178 t.Logf("Result: %v == %v\n", output, expected) 179 180 if err != nil { 181 t.Fatal(err) 182 } 183 184 //Alternative shift left 256 (overflow) 185 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 186 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHL, 187 return1()) 188 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 189 value = []byte{0x00} 190 expected = LeftPadBytes(value, 32) 191 assert.Equal(t, expected, output) 192 193 t.Logf("Result: %v == %v\n", output, expected) 194 195 if err != nil { 196 t.Fatal(err) 197 } 198 199 //Shift left 257 (overflow) 200 bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x01, SHL, return1()) 201 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 202 value = []byte{0x00} 203 expected = LeftPadBytes(value, 32) 204 assert.Equal(t, expected, output) 205 206 t.Logf("Result: %v == %v\n", output, expected) 207 208 if err != nil { 209 t.Fatal(err) 210 } 211 }) 212 213 t.Run("SHR", func(t *testing.T) { 214 st := acmstate.NewMemoryState() 215 account1 := newAccount(t, st, "1") 216 account2 := newAccount(t, st, "101") 217 218 gas := big.NewInt(100000) 219 220 //Shift right 0 221 bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHR, return1()) 222 output, err := call(vm, st, account1, account2, bytecode, nil, gas) 223 value := []byte{0x1} 224 expected := LeftPadBytes(value, 32) 225 assert.Equal(t, expected, output) 226 227 t.Logf("Result: %v == %v\n", output, expected) 228 229 if err != nil { 230 t.Fatal(err) 231 } 232 233 //Alternative shift right 0 234 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 235 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHR, return1()) 236 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 237 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 238 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} 239 240 assert.Equal(t, expected, output) 241 242 t.Logf("Result: %v == %v\n", output, expected) 243 244 if err != nil { 245 t.Fatal(err) 246 } 247 248 //Shift right 1 249 bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHR, return1()) 250 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 251 value = []byte{0x00} 252 expected = LeftPadBytes(value, 32) 253 assert.Equal(t, expected, output) 254 255 t.Logf("Result: %v == %v\n", output, expected) 256 257 if err != nil { 258 t.Fatal(err) 259 } 260 261 //Alternative shift right 1 262 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SHR, return1()) 264 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 265 value = []byte{0x40} 266 expected = RightPadBytes(value, 32) 267 assert.Equal(t, expected, output) 268 269 t.Logf("Result: %v == %v\n", output, expected) 270 271 if err != nil { 272 t.Fatal(err) 273 } 274 275 //Alternative shift right 1 276 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 277 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHR, return1()) 278 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 279 expected = []byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 280 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} 281 282 assert.Equal(t, expected, output) 283 284 t.Logf("Result: %v == %v\n", output, expected) 285 286 if err != nil { 287 t.Fatal(err) 288 } 289 290 //Shift right 255 291 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SHR, return1()) 293 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 294 value = []byte{0x1} 295 expected = LeftPadBytes(value, 32) 296 assert.Equal(t, expected, output) 297 298 t.Logf("Result: %v == %v\n", output, expected) 299 300 if err != nil { 301 t.Fatal(err) 302 } 303 304 //Alternative shift right 255 305 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 306 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHR, return1()) 307 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 308 value = []byte{0x1} 309 expected = LeftPadBytes(value, 32) 310 assert.Equal(t, expected, output) 311 312 t.Logf("Result: %v == %v\n", output, expected) 313 314 if err != nil { 315 t.Fatal(err) 316 } 317 318 //Shift right 256 (underflow) 319 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SHR, 321 return1()) 322 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 323 value = []byte{0x00} 324 expected = LeftPadBytes(value, 32) 325 assert.Equal(t, expected, output) 326 327 t.Logf("Result: %v == %v\n", output, expected) 328 329 if err != nil { 330 t.Fatal(err) 331 } 332 333 //Alternative shift right 256 (underflow) 334 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 335 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHR, 336 return1()) 337 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 338 value = []byte{0x00} 339 expected = LeftPadBytes(value, 32) 340 assert.Equal(t, expected, output) 341 342 t.Logf("Result: %v == %v\n", output, expected) 343 344 if err != nil { 345 t.Fatal(err) 346 } 347 348 //Shift right 257 (underflow) 349 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SHR, 351 return1()) 352 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 353 value = []byte{0x00} 354 expected = LeftPadBytes(value, 32) 355 assert.Equal(t, expected, output) 356 357 t.Logf("Result: %v == %v\n", output, expected) 358 359 if err != nil { 360 t.Fatal(err) 361 } 362 }) 363 364 t.Run("SAR", func(t *testing.T) { 365 st := acmstate.NewMemoryState() 366 account1 := newAccount(t, st, "1") 367 account2 := newAccount(t, st, "101") 368 369 gas := big.NewInt(100000) 370 371 //Shift arith right 0 372 bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SAR, return1()) 373 output, err := call(vm, st, account1, account2, bytecode, nil, gas) 374 value := []byte{0x1} 375 expected := LeftPadBytes(value, 32) 376 assert.Equal(t, expected, output) 377 378 t.Logf("Result: %v == %v\n", output, expected) 379 380 if err != nil { 381 t.Fatal(err) 382 } 383 384 //Alternative arith shift right 0 385 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 386 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SAR, return1()) 387 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 388 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 389 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} 390 391 assert.Equal(t, expected, output) 392 393 t.Logf("Result: %v == %v\n", output, expected) 394 395 if err != nil { 396 t.Fatal(err) 397 } 398 399 //Shift arith right 1 400 bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SAR, return1()) 401 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 402 value = []byte{0x00} 403 expected = LeftPadBytes(value, 32) 404 assert.Equal(t, expected, output) 405 406 t.Logf("Result: %v == %v\n", output, expected) 407 408 if err != nil { 409 t.Fatal(err) 410 } 411 412 //Alternative shift arith right 1 413 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SAR, return1()) 415 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 416 value = []byte{0xc0} 417 expected = RightPadBytes(value, 32) 418 assert.Equal(t, expected, output) 419 420 t.Logf("Result: %v == %v\n", output, expected) 421 422 if err != nil { 423 t.Fatal(err) 424 } 425 426 //Alternative shift arith right 1 427 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 428 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SAR, return1()) 429 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 430 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 431 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} 432 433 assert.Equal(t, expected, output) 434 435 t.Logf("Result: %v == %v\n", output, expected) 436 437 if err != nil { 438 t.Fatal(err) 439 } 440 441 //Shift arith right 255 442 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SAR, return1()) 444 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 445 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 446 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} 447 448 assert.Equal(t, expected, output) 449 450 t.Logf("Result: %v == %v\n", output, expected) 451 452 if err != nil { 453 t.Fatal(err) 454 } 455 456 //Alternative shift arith right 255 457 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 458 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1()) 459 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 460 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 461 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} 462 463 assert.Equal(t, expected, output) 464 465 t.Logf("Result: %v == %v\n", output, expected) 466 467 if err != nil { 468 t.Fatal(err) 469 } 470 471 //Alternative shift arith right 255 472 bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 473 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1()) 474 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 475 value = []uint8([]byte{0x00}) 476 expected = RightPadBytes(value, 32) 477 assert.Equal(t, expected, output) 478 479 t.Logf("Result: %v == %v\n", output, expected) 480 481 if err != nil { 482 t.Fatal(err) 483 } 484 485 //Shift arith right 256 (reset) 486 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SAR, 488 return1()) 489 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 490 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 491 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 492 493 assert.Equal(t, expected, output) 494 495 t.Logf("Result: %v == %v\n", output, expected) 496 497 if err != nil { 498 t.Fatal(err) 499 } 500 501 //Alternative shift arith right 256 (reset) 502 bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 503 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SAR, 504 return1()) 505 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 506 value = []byte{0x00} 507 expected = LeftPadBytes(value, 32) 508 assert.Equal(t, expected, output) 509 510 t.Logf("Result: %v == %v\n", output, expected) 511 512 if err != nil { 513 t.Fatal(err) 514 } 515 516 //Shift arith right 257 (reset) 517 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SAR, 519 return1()) 520 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 521 expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 522 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} 523 524 assert.Equal(t, expected, output) 525 526 t.Logf("Result: %v == %v\n", output, expected) 527 528 if err != nil { 529 t.Fatal(err) 530 } 531 }) 532 533 //Test attempt to jump to bad destination (position 16) 534 t.Run("JumpErr", func(t *testing.T) { 535 st := acmstate.NewMemoryState() 536 537 // Create accounts 538 account1 := newAccount(t, st, "1") 539 account2 := newAccount(t, st, "2") 540 541 gas := big.NewInt(100000) 542 543 bytecode := MustSplice(PUSH1, 0x10, JUMP) 544 545 var err error 546 ch := make(chan struct{}) 547 go func() { 548 _, err = call(vm, st, account1, account2, bytecode, nil, gas) 549 ch <- struct{}{} 550 }() 551 tick := time.NewTicker(time.Second * 2) 552 select { 553 case <-tick.C: 554 t.Fatal("VM ended up in an infinite loop from bad jump dest (it took too long!)") 555 case <-ch: 556 if err == nil { 557 t.Fatal("Expected invalid jump dest err") 558 } 559 } 560 }) 561 562 // Tests the code for a subcurrency contract compiled by serpent 563 t.Run("Subcurrency", func(t *testing.T) { 564 st := acmstate.NewMemoryState() 565 // Create accounts 566 account1 := newAccount(t, st, "1, 2, 3") 567 account2 := newAccount(t, st, "3, 2, 1") 568 569 gas := big.NewInt(1000) 570 571 bytecode := MustSplice(PUSH3, 0x0F, 0x42, 0x40, CALLER, SSTORE, PUSH29, 0x01, 0x00, 0x00, 0x00, 572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 574 0x00, CALLDATALOAD, DIV, PUSH4, 0x15, 0xCF, 0x26, 0x84, DUP2, EQ, ISZERO, PUSH2, 575 0x00, 0x46, JUMPI, PUSH1, 0x04, CALLDATALOAD, PUSH1, 0x40, MSTORE, PUSH1, 0x40, 576 MLOAD, SLOAD, PUSH1, 0x60, MSTORE, PUSH1, 0x20, PUSH1, 0x60, RETURN, JUMPDEST, 577 PUSH4, 0x69, 0x32, 0x00, 0xCE, DUP2, EQ, ISZERO, PUSH2, 0x00, 0x87, JUMPI, PUSH1, 578 0x04, CALLDATALOAD, PUSH1, 0x80, MSTORE, PUSH1, 0x24, CALLDATALOAD, PUSH1, 0xA0, 579 MSTORE, CALLER, SLOAD, PUSH1, 0xC0, MSTORE, CALLER, PUSH1, 0xE0, MSTORE, PUSH1, 580 0xA0, MLOAD, PUSH1, 0xC0, MLOAD, SLT, ISZERO, ISZERO, PUSH2, 0x00, 0x86, JUMPI, 581 PUSH1, 0xA0, MLOAD, PUSH1, 0xC0, MLOAD, SUB, PUSH1, 0xE0, MLOAD, SSTORE, PUSH1, 582 0xA0, MLOAD, PUSH1, 0x80, MLOAD, SLOAD, ADD, PUSH1, 0x80, MLOAD, SSTORE, JUMPDEST, 583 JUMPDEST, POP, JUMPDEST, PUSH1, 0x00, PUSH1, 0x00, RETURN) 584 585 data := hex.MustDecodeString("693200CE0000000000000000000000004B4363CDE27C2EB05E66357DB05BC5C88F850C1A0000000000000000000000000000000000000000000000000000000000000005") 586 output, err := call(vm, st, account1, account2, bytecode, data, gas) 587 t.Logf("Output: %v Error: %v\n", output, err) 588 if err != nil { 589 t.Fatal(err) 590 } 591 require.NoError(t, err) 592 }) 593 594 //This test case is taken from EIP-140 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md); 595 //it is meant to test the implementation of the REVERT opcode 596 t.Run("Revert", func(t *testing.T) { 597 st := acmstate.NewMemoryState() 598 599 // Create accounts 600 account1 := newAccount(t, st, "1") 601 account2 := newAccount(t, st, "1, 0, 1") 602 603 key, value := []byte{0x00}, []byte{0x00} 604 err := st.SetStorage(account1, LeftPadWord256(key), value) 605 require.NoError(t, err) 606 607 gas := big.NewInt(100000) 608 609 bytecode := MustSplice(PUSH13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 610 PUSH1, 0x00, SSTORE, PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 612 PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, REVERT) 613 614 /*bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 615 0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 616 0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, REVERT)*/ 617 618 output, err := call(vm, st, account1, account2, bytecode, nil, gas) 619 assert.Error(t, err, "Expected execution reverted error") 620 621 storageVal, err := st.GetStorage(account1, LeftPadWord256(key)) 622 require.NoError(t, err) 623 assert.Equal(t, value, storageVal) 624 625 t.Logf("Output: %v\n", output) 626 }) 627 628 // Test sending tokens from a contract to another account 629 t.Run("SendCall", func(t *testing.T) { 630 st := acmstate.NewMemoryState() 631 632 // Create accounts 633 account1 := newAccount(t, st, "1") 634 account2 := newAccount(t, st, "2") 635 account3 := newAccount(t, st, "3") 636 637 // account1 will call account2 which will trigger CALL opcode to account3 638 addr := account3 639 contractCode := callContractCode(addr) 640 641 //---------------------------------------------- 642 // account2 has insufficient balance, should fail 643 //txe := runVM(st, account1, account2, contractCode, 100000) 644 //exCalls := txe.ExceptionalCalls() 645 //require.Len(t, exCalls, 1) 646 //require.Equal(t, errors.Codes.InsufficientBalance, errors.GetCode(exCalls[0].Header.Exception)) 647 648 //---------------------------------------------- 649 // give account2 sufficient balance, should pass 650 addToBalance(t, st, account2, 100000) 651 //txe = runVM(st, account1, account2, contractCode, 1000) 652 //assert.Nil(t, txe.Exception, "Should have sufficient balance") 653 654 //---------------------------------------------- 655 // insufficient gas, should fail 656 txe := runVM(st, account1, account2, contractCode, 19) 657 assert.NotNil(t, txe.Exception, "Expected insufficient gas error") 658 }) 659 660 // Test to ensure that contracts called with STATICCALL cannot modify state 661 // as per https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md 662 t.Run("StaticCallReadOnly", func(t *testing.T) { 663 gas1, gas2 := byte(0x1), byte(0x1) 664 value := byte(0x69) 665 var inOff, inSize, retOff, retSize byte 666 667 logDefault := MustSplice(PUSH1, inSize, PUSH1, inOff) 668 testRecipient := engine.AddressFromName("1") 669 // check all illegal state modifications in child staticcall frame 670 for _, illegalContractCode := range []acm.Bytecode{ 671 MustSplice(PUSH9, "arbitrary", PUSH1, 0x00, SSTORE), 672 MustSplice(logDefault, LOG0), 673 MustSplice(logDefault, PUSH1, 0x1, LOG1), 674 MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, LOG2), 675 MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, LOG3), 676 MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, LOG4), 677 MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x69, CREATE), 678 MustSplice(PUSH20, testRecipient, SELFDESTRUCT), 679 } { 680 // TODO: CREATE2 681 682 t.Logf("Testing state-modifying bytecode: %v", illegalContractCode.MustTokens()) 683 st := acmstate.NewMemoryState() 684 callee := makeAccountWithCode(t, st, "callee", MustSplice(illegalContractCode, PUSH1, 0x1, return1())) 685 686 // equivalent to CALL, but enforce state immutability for children 687 code := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff, 688 PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize, 689 PUSH1, retOff, RETURN) 690 caller := makeAccountWithCode(t, st, "caller", code) 691 692 txe := runVM(st, caller, callee, code, 1000) 693 // the topmost caller can never *illegally* modify state 694 require.Error(t, txe.Exception) 695 require.Equal(t, errors.Codes.IllegalWrite, txe.Exception.ErrorCode(), 696 "should get an error from child accounts that st is read only") 697 } 698 }) 699 700 t.Run("StaticCallWithValue", func(t *testing.T) { 701 gas1, gas2 := byte(0x1), byte(0x1) 702 value := byte(0x69) 703 var inOff, inSize, retOff, retSize byte 704 705 st := acmstate.NewMemoryState() 706 707 finalAddress := makeAccountWithCode(t, st, "final", MustSplice(PUSH1, int64(20), return1())) 708 709 // intermediate account CALLs another contract *with* a value 710 callee := makeAccountWithCode(t, st, "callee", MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 711 inOff, PUSH1, value, PUSH20, finalAddress, PUSH2, gas1, gas2, CALL, returnWord())) 712 713 callerCode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 714 inOff, PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize, 715 PUSH1, retOff, RETURN) 716 caller := makeAccountWithCode(t, st, "caller", callerCode) 717 718 addToBalance(t, st, callee, 100000) 719 txe := runVM(st, caller, callee, callerCode, 1000) 720 require.NotNil(t, txe.Exception) 721 require.Equal(t, errors.Codes.IllegalWrite, txe.Exception.ErrorCode(), 722 "expected static call violation because of call with value") 723 }) 724 725 t.Run("StaticCallNoValue", func(t *testing.T) { 726 gas1, gas2 := byte(0x1), byte(0x1) 727 value := byte(0x69) 728 var inOff, inSize, retOff, retSize byte 729 730 // this final test just checks that STATICCALL actually works 731 st := acmstate.NewMemoryState() 732 733 finalAddress := makeAccountWithCode(t, st, "final", MustSplice(PUSH1, int64(20), return1())) 734 // intermediate account CALLs another contract *without* a value 735 callee := makeAccountWithCode(t, st, "callee", MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 736 inOff, PUSH1, 0x00, PUSH20, finalAddress, PUSH2, gas1, gas2, CALL, returnWord())) 737 738 callerCode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 739 inOff, PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize, 740 PUSH1, retOff, RETURN) 741 caller := makeAccountWithCode(t, st, "caller", callerCode) 742 743 addToBalance(t, st, callee, 100000) 744 txe := runVM(st, caller, callee, callerCode, 1000) 745 // no exceptions expected because value never set in children 746 require.NoError(t, txe.Exception.AsError()) 747 exCalls := txe.ExceptionalCalls() 748 require.Len(t, exCalls, 0) 749 }) 750 751 // Test evm account creation 752 t.Run("Create", func(t *testing.T) { 753 st := acmstate.NewMemoryState() 754 755 code := MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x0, CREATE, PUSH1, 0, MSTORE, PUSH1, 20, PUSH1, 12, RETURN) 756 callee := makeAccountWithCode(t, st, "callee", code) 757 // ensure pre-generated address has same sequence number 758 nonce := make([]byte, txs.HashLength+uint64Length) 759 binary.BigEndian.PutUint64(nonce[txs.HashLength:], 1) 760 addr := crypto.NewContractAddress(callee, nonce) 761 762 gas := big.NewInt(100000) 763 caller := newAccount(t, st, "1, 2, 3") 764 output, err := call(vm, st, caller, callee, code, nil, gas) 765 assert.NoError(t, err, "Should return new address without error") 766 assert.Equal(t, addr.Bytes(), output, "Addresses should be equal") 767 }) 768 769 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md 770 t.Run("Create2", func(t *testing.T) { 771 st := acmstate.NewMemoryState() 772 773 // salt of 0s 774 var salt [32]byte 775 code := MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x0, PUSH32, salt[:], CREATE2, PUSH1, 0, MSTORE, PUSH1, 20, PUSH1, 12, RETURN) 776 callee := makeAccountWithCode(t, st, "callee", code) 777 addr := crypto.NewContractAddress2(callee, salt, code) 778 779 gas := big.NewInt(100000) 780 caller := newAccount(t, st, "1, 2, 3") 781 output, err := call(vm, st, caller, callee, code, nil, gas) 782 assert.NoError(t, err, "Should return new address without error") 783 assert.Equal(t, addr.Bytes(), output, "Returned value not equal to create2 address") 784 }) 785 786 // This test was introduced to cover an issues exposed in our handling of the 787 // gas limit passed from caller to callee on various forms of CALL. 788 // The idea of this test is to implement a simple DelegateCall in EVM code 789 // We first run the DELEGATECALL with _just_ enough gas expecting a simple return, 790 // and then run it with 1 gas unit less, expecting a failure 791 t.Run("DelegateCallGas", func(t *testing.T) { 792 st := acmstate.NewMemoryState() 793 794 inOff := 0 795 inSize := 0 // no call data 796 retOff := 0 797 retSize := 32 798 calleeReturnValue := int64(20) 799 800 callee := makeAccountWithCode(t, st, "callee", MustSplice(PUSH1, calleeReturnValue, PUSH1, 0, MSTORE, PUSH1, 32, PUSH1, 0, RETURN)) 801 802 // 6 op codes total 803 baseOpsCost := engine.GasBaseOp * 6 804 // 4 pushes 805 pushCost := engine.GasStackOp * 4 806 // 2 pushes 2 pops 807 returnCost := engine.GasStackOp * 4 808 809 delegateCallCost := baseOpsCost + pushCost + returnCost 810 811 // Here we split up the caller code so we can make a DELEGATE call with 812 // different amounts of gas. The value we sandwich in the middle is the amount 813 // we subtract from the available gas (that the caller has available), so: 814 // code := MustSplice(callerCodePrefix, <amount to subtract from GAS> , callerCodeSuffix) 815 // gives us the code to make the call 816 callerCodePrefix := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, 817 PUSH1, inOff, PUSH20, callee, PUSH1) 818 callerCodeSuffix := MustSplice(DELEGATECALL, returnWord()) 819 820 // Perform a delegate call 821 //Give just enough gas to make the DELEGATECALL 822 callerCode := MustSplice(callerCodePrefix, 823 delegateCallCost, callerCodeSuffix) 824 caller := makeAccountWithCode(t, st, "caller", callerCode) 825 // Should pass 826 txe := runVM(st, caller, callee, callerCode, 100) 827 assert.Nil(t, txe.Exception, "Should have sufficient funds for call") 828 assert.Equal(t, Int64ToWord256(calleeReturnValue).Bytes(), txe.Result.Return) 829 830 callerCode2 := MustSplice(callerCodePrefix, 831 // Shouldn't be enough gas to make call 832 delegateCallCost-1, callerCodeSuffix) 833 caller2 := makeAccountWithCode(t, st, "caller2", callerCode2) 834 835 // Should fail 836 txe = runVM(st, caller2, callee, callerCode2, 100) 837 assert.NotNil(t, txe.Exception, "Should have insufficient gas for call") 838 }) 839 840 t.Run("MemoryBounds", func(t *testing.T) { 841 st := acmstate.NewMemoryState() 842 blockchain := new(engine.TestBlockchain) 843 eventSink := exec.NewNoopEventSink() 844 vm := New(engine.Options{ 845 MemoryProvider: func(err errors.Sink) engine.Memory { 846 return engine.NewDynamicMemory(1024, 2048, err) 847 }, 848 }) 849 caller := makeAccountWithCode(t, st, "caller", nil) 850 callee := makeAccountWithCode(t, st, "callee", nil) 851 word := One256 852 // This attempts to store a value at the memory boundary and return it 853 params := engine.CallParams{ 854 Gas: big.NewInt(100000), 855 Caller: caller, 856 Callee: callee, 857 } 858 code := MustSplice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()) 859 860 output, err := vm.Execute(st, blockchain, eventSink, params, code) 861 assert.NoError(t, err) 862 assert.Equal(t, word.Bytes(), output) 863 864 // Same with number 865 word = Int64ToWord256(232234234432) 866 code = MustSplice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()) 867 output, err = vm.Execute(st, blockchain, eventSink, params, code) 868 assert.NoError(t, err) 869 assert.Equal(t, word.Bytes(), output) 870 871 // Now test a series of boundary stores 872 code = pushWord(word) 873 for i := 0; i < 10; i++ { 874 code = MustSplice(code, storeAtEnd(), MLOAD) 875 } 876 code = MustSplice(code, storeAtEnd(), returnAfterStore()) 877 output, err = vm.Execute(st, blockchain, eventSink, params, code) 878 assert.NoError(t, err) 879 assert.Equal(t, word.Bytes(), output) 880 881 // Same as above but we should breach the upper memory limit set in memoryProvider 882 code = pushWord(word) 883 for i := 0; i < 100; i++ { 884 code = MustSplice(code, storeAtEnd(), MLOAD) 885 } 886 code = MustSplice(code, storeAtEnd(), returnAfterStore()) 887 _, err = vm.Execute(st, blockchain, eventSink, params, code) 888 assert.Error(t, err, "Should hit memory out of bounds") 889 }) 890 891 t.Run("MsgSender", func(t *testing.T) { 892 st := acmstate.NewMemoryState() 893 account1 := newAccount(t, st, "1, 2, 3") 894 account2 := newAccount(t, st, "3, 2, 1") 895 gas := big.NewInt(100000) 896 897 /* 898 pragma solidity ^0.5.4; 899 900 contract SimpleStorage { 901 function get() public constant returns (address) { 902 return msg.sender; 903 } 904 } 905 */ 906 907 // This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler 908 code := hex.MustDecodeString("6060604052341561000f57600080fd5b60ca8061001d6000396000f30060606040526004361060" + 909 "3f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14604457" + 910 "5b600080fd5b3415604e57600080fd5b60546096565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ff" + 911 "ffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000339050905600a165627a" + 912 "7a72305820b9ebf49535372094ae88f56d9ad18f2a79c146c8f56e7ef33b9402924045071e0029") 913 914 var err error 915 // Run the contract initialisation code to obtain the contract code that would be mounted at account2 916 contractCode, err := call(vm, st, account1, account2, code, code, gas) 917 require.NoError(t, err) 918 919 // Not needed for this test (since contract code is passed as argument to vm), but this is what an execution 920 // framework must do 921 err = engine.InitEVMCode(st, account2, contractCode) 922 require.NoError(t, err) 923 924 // Input is the function hash of `get()` 925 input := hex.MustDecodeString("6d4ce63c") 926 927 output, err := call(vm, st, account1, account2, contractCode, input, gas) 928 require.NoError(t, err) 929 930 assert.Equal(t, account1.Word256().Bytes(), output) 931 }) 932 933 t.Run("Invalid", func(t *testing.T) { 934 st := acmstate.NewMemoryState() 935 936 // Create accounts 937 account1 := newAccount(t, st, "1") 938 account2 := newAccount(t, st, "1, 0, 1") 939 940 gas := big.NewInt(100000) 941 942 bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 943 0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 944 0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, INVALID) 945 946 output, err := call(vm, st, account1, account2, bytecode, nil, gas) 947 assert.Equal(t, errors.Codes.ExecutionAborted, errors.GetCode(err)) 948 t.Logf("Output: %v Error: %v\n", output, err) 949 }) 950 951 t.Run("ReturnDataSize", func(t *testing.T) { 952 st := acmstate.NewMemoryState() 953 954 accountName := "account2addresstests" 955 956 ret := "My return message" 957 callcode := MustSplice(PUSH32, RightPadWord256([]byte(ret)), PUSH1, 0x00, MSTORE, PUSH1, len(ret), PUSH1, 0x00, RETURN) 958 959 // Create accounts 960 account1 := newAccount(t, st, "1") 961 account2 := makeAccountWithCode(t, st, accountName, callcode) 962 963 gas := big.NewInt(100000) 964 965 gas1, gas2 := byte(0x1), byte(0x1) 966 value := byte(0x69) 967 inOff, inSize := byte(0x0), byte(0x0) // no call data 968 retOff, retSize := byte(0x0), byte(len(ret)) 969 970 bytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff, PUSH1, value, 971 PUSH20, account2, PUSH2, gas1, gas2, CALL, 972 RETURNDATASIZE, PUSH1, 0x00, MSTORE, PUSH1, 0x20, PUSH1, 0x00, RETURN) 973 974 expected := Uint64ToWord256(uint64(len(ret))).Bytes() 975 976 output, err := call(vm, st, account1, account2, bytecode, nil, gas) 977 require.NoError(t, err) 978 assert.Equal(t, expected, output) 979 980 t.Logf("Output: %v Error: %v\n", output, err) 981 982 if err != nil { 983 t.Fatal(err) 984 } 985 }) 986 987 t.Run("ReturnDataCopy", func(t *testing.T) { 988 st := acmstate.NewMemoryState() 989 990 accountName := "account2addresstests" 991 992 ret := "My return message" 993 callcode := MustSplice(PUSH32, RightPadWord256([]byte(ret)), PUSH1, 0x00, MSTORE, PUSH1, len(ret), PUSH1, 0x00, RETURN) 994 995 // Create accounts 996 account1 := newAccount(t, st, "1") 997 account2 := makeAccountWithCode(t, st, accountName, callcode) 998 999 gas := big.NewInt(100000) 1000 1001 gas1, gas2 := byte(0x1), byte(0x1) 1002 value := byte(0x69) 1003 inOff, inSize := byte(0x0), byte(0x0) // no call data 1004 retOff, retSize := byte(0x0), byte(len(ret)) 1005 1006 bytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff, PUSH1, value, 1007 PUSH20, account2, PUSH2, gas1, gas2, CALL, RETURNDATASIZE, PUSH1, 0x00, PUSH1, 0x00, RETURNDATACOPY, 1008 RETURNDATASIZE, PUSH1, 0x00, RETURN) 1009 1010 expected := []byte(ret) 1011 1012 output, err := call(vm, st, account1, account2, bytecode, nil, gas) 1013 require.NoError(t, err) 1014 assert.Equal(t, expected, output) 1015 1016 t.Logf("Output: %v Error: %v\n", output, err) 1017 }) 1018 1019 t.Run("CallNonExistent", func(t *testing.T) { 1020 st := acmstate.NewMemoryState() 1021 blockchain := new(engine.TestBlockchain) 1022 eventSink := exec.NewNoopEventSink() 1023 account1 := newAccount(t, st, "1") 1024 addToBalance(t, st, account1, 100000) 1025 unknownAddress := engine.AddressFromName("nonexistent") 1026 1027 params := engine.CallParams{ 1028 Caller: account1, 1029 Callee: unknownAddress, 1030 Value: *big.NewInt(100), 1031 Gas: big.NewInt(100000), 1032 } 1033 _, ex := vm.Execute(st, blockchain, eventSink, params, nil) 1034 require.Equal(t, errors.Codes.NonExistentAccount, errors.GetCode(ex), 1035 "Should not be able to call account before creating it (even before initialising)") 1036 acc, err := st.GetAccount(unknownAddress) 1037 require.NoError(t, err) 1038 require.Nil(t, acc) 1039 }) 1040 1041 t.Run("GetBlockHash", func(t *testing.T) { 1042 st := acmstate.NewMemoryState() 1043 blockchain := new(engine.TestBlockchain) 1044 eventSink := exec.NewNoopEventSink() 1045 1046 // Create accounts 1047 account1 := newAccount(t, st, "1") 1048 account2 := newAccount(t, st, "101") 1049 1050 var gas = big.NewInt(100000) 1051 1052 bytecode := MustSplice(PUSH1, 2, BLOCKHASH) 1053 1054 params := engine.CallParams{ 1055 Caller: account1, 1056 Callee: account2, 1057 Gas: gas, 1058 } 1059 // Non existing block 1060 blockchain.BlockHeight = 1 1061 _, err := vm.Execute(st, blockchain, eventSink, params, bytecode) 1062 require.Equal(t, errors.Codes.InvalidBlockNumber, errors.GetCode(err), 1063 "attempt to get block hash of a non-existent block") 1064 1065 // Excessive old block 1066 blockchain.BlockHeight = 258 1067 bytecode = MustSplice(PUSH1, 1, BLOCKHASH) 1068 1069 _, err = vm.Execute(st, blockchain, eventSink, params, bytecode) 1070 require.Equal(t, errors.Codes.BlockNumberOutOfRange, errors.GetCode(err), 1071 "attempt to get block hash of a block outside of allowed range") 1072 1073 // Get block hash 1074 blockchain.BlockHeight = 257 1075 bytecode = MustSplice(PUSH1, 2, BLOCKHASH, return1()) 1076 1077 output, err := vm.Execute(st, blockchain, eventSink, params, bytecode) 1078 assert.NoError(t, err) 1079 assert.Equal(t, LeftPadWord256([]byte{2}), LeftPadWord256(output)) 1080 1081 // Get block hash fail 1082 blockchain.BlockHeight = 3 1083 bytecode = MustSplice(PUSH1, 4, BLOCKHASH, return1()) 1084 1085 _, err = vm.Execute(st, blockchain, eventSink, params, bytecode) 1086 require.Equal(t, errors.Codes.InvalidBlockNumber, errors.GetCode(err), 1087 "attempt to get block hash failed") 1088 }) 1089 1090 t.Run("PushWord", func(t *testing.T) { 1091 word := Int64ToWord256(int64(2133213213)) 1092 assert.Equal(t, MustSplice(PUSH4, 0x7F, 0x26, 0x40, 0x1D), pushWord(word)) 1093 word[0] = 1 1094 assert.Equal(t, MustSplice(PUSH32, 1095 1, 0, 0, 0, 0, 0, 0, 0, 1096 0, 0, 0, 0, 0, 0, 0, 0, 1097 0, 0, 0, 0, 0, 0, 0, 0, 1098 0, 0, 0, 0, 0x7F, 0x26, 0x40, 0x1D), pushWord(word)) 1099 assert.Equal(t, MustSplice(PUSH1, 0), pushWord(Word256{})) 1100 assert.Equal(t, MustSplice(PUSH1, 1), pushWord(Int64ToWord256(1))) 1101 }) 1102 1103 // Kind of indirect test of Splice, but here to avoid import cycles 1104 t.Run("Bytecode", func(t *testing.T) { 1105 assert.Equal(t, 1106 MustSplice(1, 2, 3, 4, 5, 6), 1107 MustSplice(1, 2, 3, MustSplice(4, 5, 6))) 1108 assert.Equal(t, 1109 MustSplice(1, 2, 3, 4, 5, 6, 7, 8), 1110 MustSplice(1, 2, 3, MustSplice(4, MustSplice(5), 6), 7, 8)) 1111 assert.Equal(t, 1112 MustSplice(PUSH1, 2), 1113 MustSplice(byte(PUSH1), 0x02)) 1114 assert.Equal(t, 1115 []byte{}, 1116 MustSplice(MustSplice(MustSplice()))) 1117 1118 contractAccount := &acm.Account{Address: crypto.AddressFromWord256(Int64ToWord256(102))} 1119 addr := contractAccount.Address 1120 gas1, gas2 := byte(0x1), byte(0x1) 1121 value := byte(0x69) 1122 inOff, inSize := byte(0x0), byte(0x0) // no call data 1123 retOff, retSize := byte(0x0), byte(0x20) 1124 contractCodeBytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 1125 inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize, 1126 PUSH1, retOff, RETURN) 1127 contractCode := []byte{0x60, retSize, 0x60, retOff, 0x60, inSize, 0x60, inOff, 0x60, value, 0x73} 1128 contractCode = append(contractCode, addr[:]...) 1129 contractCode = append(contractCode, []byte{0x61, gas1, gas2, 0xf1, 0x60, 0x20, 0x60, 0x0, 0xf3}...) 1130 assert.Equal(t, contractCode, contractCodeBytecode) 1131 }) 1132 1133 t.Run("Concat", func(t *testing.T) { 1134 assert.Equal(t, 1135 []byte{0x01, 0x02, 0x03, 0x04}, 1136 Concat([]byte{0x01, 0x02}, []byte{0x03, 0x04})) 1137 }) 1138 1139 t.Run("Subslice", func(t *testing.T) { 1140 const size = 10 1141 data := make([]byte, size) 1142 for i := 0; i < size; i++ { 1143 data[i] = byte(i) 1144 } 1145 for n := uint64(0); n < size; n++ { 1146 data = data[:n] 1147 for offset := uint64(0); offset < size; offset++ { 1148 for length := uint64(0); length < size; length++ { 1149 _, err := subslice(data, offset, length) 1150 if offset < 0 || length < 0 || n < offset { 1151 assert.Error(t, err) 1152 } else { 1153 assert.NoError(t, err) 1154 } 1155 } 1156 } 1157 } 1158 1159 bs, err := subslice([]byte{1, 2, 3, 4, 5, 6, 7, 8}, 4, 32) 1160 require.NoError(t, err) 1161 assert.Equal(t, []byte{ 1162 5, 6, 7, 8, 0, 0, 0, 0, 1163 0, 0, 0, 0, 0, 0, 0, 0, 1164 0, 0, 0, 0, 0, 0, 0, 0, 1165 0, 0, 0, 0, 0, 0, 0, 0, 1166 }, bs) 1167 }) 1168 1169 t.Run("DataStackOverflow", func(t *testing.T) { 1170 st := acmstate.NewMemoryState() 1171 blockchain := new(engine.TestBlockchain) 1172 eventSink := exec.NewNoopEventSink() 1173 account1 := newAccount(t, st, "1, 2, 3") 1174 account2 := newAccount(t, st, "3, 2, 1") 1175 1176 /* 1177 pragma solidity ^0.5.4; 1178 1179 contract SimpleStorage { 1180 function get() public constant returns (address) { 1181 return get(); 1182 } 1183 } 1184 */ 1185 1186 // This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler 1187 code, err := hex.DecodeString("608060405234801561001057600080fd5b5060d18061001f6000396000f300608060405260043610" + 1188 "603f576000357c0100000000000000000000000000000000000000000000000000000000900463ff" + 1189 "ffffff1680636d4ce63c146044575b600080fd5b348015604f57600080fd5b5060566098565b6040" + 1190 "51808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffff" + 1191 "ffffffffffff16815260200191505060405180910390f35b600060a06098565b9050905600a16562" + 1192 "7a7a72305820daacfba0c21afacb5b67f26bc8021de63eaa560db82f98357d4e513f3249cf350029") 1193 require.NoError(t, err) 1194 1195 // Run the contract initialisation code to obtain the contract code that would be mounted at account2 1196 params := engine.CallParams{ 1197 Caller: account1, 1198 Callee: account2, 1199 Input: code, 1200 Gas: big.NewInt(1000000), 1201 } 1202 vm := New(engine.Options{ 1203 DataStackMaxDepth: 4, 1204 }) 1205 1206 code, err = vm.Execute(st, blockchain, eventSink, params, code) 1207 require.NoError(t, err) 1208 1209 // Input is the function hash of `get()` 1210 params.Input, err = hex.DecodeString("6d4ce63c") 1211 require.NoError(t, err) 1212 1213 _, ex := vm.Execute(st, blockchain, eventSink, params, code) 1214 require.Equal(t, errors.Codes.DataStackOverflow, errors.GetCode(ex), "Should be stack overflow") 1215 }) 1216 1217 t.Run("CallStackOverflow", func(t *testing.T) { 1218 st := acmstate.NewMemoryState() 1219 blockchain := new(engine.TestBlockchain) 1220 eventSink := exec.NewNoopEventSink() 1221 txe := new(exec.TxExecution) 1222 1223 account1 := newAccount(t, st, "1, 2, 3") 1224 account2 := newAccount(t, st, "3, 2, 1") 1225 1226 // Sender accepts lot of gaz but we run on a caped call stack node 1227 /* 1228 pragma solidity ^0.5.4; 1229 1230 contract A { 1231 function callMeBack() public { 1232 return require(msg.sender.call(bytes4(keccak256("callMeBack()")),this)); 1233 } 1234 } 1235 */ 1236 1237 // This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler 1238 code, err := hex.DecodeString("608060405234801561001057600080fd5b5061017a806100206000396000f3006080604052600436" + 1239 "10610041576000357c01000000000000000000000000000000000000000000000000000000009004" + 1240 "63ffffffff168063692c3b7c14610046575b600080fd5b34801561005257600080fd5b5061005b61" + 1241 "005d565b005b3373ffffffffffffffffffffffffffffffffffffffff1660405180807f63616c6c4d" + 1242 "654261636b28290000000000000000000000000000000000000000815250600c0190506040518091" + 1243 "0390207c010000000000000000000000000000000000000000000000000000000090043060405182" + 1244 "63ffffffff167c010000000000000000000000000000000000000000000000000000000002815260" + 1245 "0401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffff" + 1246 "ffffffffffffff1681526020019150506000604051808303816000875af192505050151561014c57" + 1247 "600080fd5b5600a165627a7a723058209315a40abb8b23b7c2a340e938b01367b419a23818475a2e" + 1248 "ee80d09da3f7ba780029") 1249 require.NoError(t, err) 1250 1251 params := engine.CallParams{ 1252 Caller: account1, 1253 Callee: account2, 1254 Input: code, 1255 Gas: big.NewInt(1000000), 1256 } 1257 options := engine.Options{ 1258 CallStackMaxDepth: 2, 1259 } 1260 vm := New(options) 1261 // Run the contract initialisation code to obtain the contract code that would be mounted at account2 1262 contractCode, err := vm.Execute(st, blockchain, eventSink, params, code) 1263 require.NoError(t, err) 1264 1265 err = engine.InitEVMCode(st, account1, contractCode) 1266 require.NoError(t, err) 1267 err = engine.InitEVMCode(st, account2, contractCode) 1268 require.NoError(t, err) 1269 1270 // keccak256 hash of 'callMeBack()' 1271 params.Input, err = hex.DecodeString("692c3b7c") 1272 require.NoError(t, err) 1273 1274 _, err = vm.Execute(st, blockchain, txe, params, contractCode) 1275 // The TxExecution must be an exception to get the callerror 1276 txe.PushError(err) 1277 require.Error(t, err) 1278 callError := txe.CallError() 1279 require.Error(t, callError) 1280 require.Equal(t, errors.Codes.CallStackOverflow, errors.GetCode(callError)) 1281 // Errors are post-order so first is deepest 1282 require.True(t, len(callError.NestedErrors) > 0) 1283 deepestErr := callError.NestedErrors[0] 1284 require.Equal(t, errors.Codes.CallStackOverflow, errors.GetCode(deepestErr)) 1285 assert.Equal(t, options.CallStackMaxDepth, deepestErr.StackDepth) 1286 assert.Equal(t, account2, deepestErr.Callee) 1287 assert.Equal(t, account1, deepestErr.Caller) 1288 }) 1289 1290 t.Run("ExtCodeHash", func(t *testing.T) { 1291 st := acmstate.NewMemoryState() 1292 account1 := newAccount(t, st, "1") 1293 account2 := newAccount(t, st, "101") 1294 1295 gas := big.NewInt(100000) 1296 1297 // The EXTCODEHASH of the account without code is c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 1298 // what is the keccack256 hash of empty data. 1299 bytecode := MustSplice(PUSH20, account1, EXTCODEHASH, return1()) 1300 output, err := call(vm, st, account1, account2, bytecode, nil, gas) 1301 assert.NoError(t, err) 1302 assert.Equal(t, hex.MustDecodeString("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), output) 1303 1304 // The EXTCODEHASH of a native account is hash of its name. 1305 bytecode = MustSplice(PUSH1, 0x03, EXTCODEHASH, return1()) 1306 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 1307 assert.NoError(t, err) 1308 assert.Equal(t, crypto.Keccak256([]byte("ripemd160Func")), output) 1309 1310 // EXTCODEHASH of non-existent account should be 0 1311 bytecode = MustSplice(PUSH1, 0xff, EXTCODEHASH, return1()) 1312 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 1313 assert.NoError(t, err) 1314 assert.Equal(t, Zero256[:], output) 1315 1316 // EXTCODEHASH is the hash of an account code 1317 acc := makeAccountWithCode(t, st, "trustedCode", MustSplice(BLOCKHASH, return1())) 1318 bytecode = MustSplice(PUSH20, acc, EXTCODEHASH, return1()) 1319 output, err = call(vm, st, account1, account2, bytecode, nil, gas) 1320 assert.NoError(t, err) 1321 assert.Equal(t, hex.MustDecodeString("010da270094b5199d3e54f89afe4c66cdd658dd8111a41998714227e14e171bd"), output) 1322 }) 1323 1324 // Tests logs and events. 1325 t.Run("TestLogEvents", func(t *testing.T) { 1326 expectedData := []byte{0x10} 1327 expectedHeight := uint64(0) 1328 expectedTopics := []Word256{ 1329 Int64ToWord256(1), 1330 Int64ToWord256(2), 1331 Int64ToWord256(3), 1332 Int64ToWord256(4)} 1333 1334 st := acmstate.NewMemoryState() 1335 blockchain := new(engine.TestBlockchain) 1336 // Create accounts 1337 address1 := crypto.Address{1, 3, 5, 7, 9} 1338 address2 := crypto.Address{2, 4, 6, 8, 10} 1339 1340 err := engine.CreateAccount(st, address1) 1341 require.NoError(t, err) 1342 err = engine.CreateAccount(st, address2) 1343 require.NoError(t, err) 1344 1345 mstore8 := byte(MSTORE8) 1346 push1 := byte(PUSH1) 1347 log4 := byte(LOG4) 1348 stop := byte(STOP) 1349 1350 code := []byte{ 1351 push1, 16, // data value 1352 push1, 0, // memory slot 1353 mstore8, 1354 push1, 4, // topic 4 1355 push1, 3, // topic 3 1356 push1, 2, // topic 2 1357 push1, 1, // topic 1 1358 push1, 1, // size of data 1359 push1, 0, // data starts at this offset 1360 log4, 1361 stop, 1362 } 1363 1364 txe := new(exec.TxExecution) 1365 1366 params := engine.CallParams{ 1367 Caller: address1, 1368 Callee: address2, 1369 Gas: big.NewInt(1000000), 1370 } 1371 _, err = vm.Execute(st, blockchain, txe, params, code) 1372 require.NoError(t, err) 1373 1374 for _, ev := range txe.Events { 1375 if ev.Log != nil { 1376 if !reflect.DeepEqual(ev.Log.Topics, expectedTopics) { 1377 t.Errorf("Event topics are wrong. Got: %v. Expected: %v", ev.Log.Topics, expectedTopics) 1378 } 1379 if !bytes.Equal(ev.Log.Data, expectedData) { 1380 t.Errorf("Event data is wrong. Got: %s. Expected: %s", ev.Log.Data, expectedData) 1381 } 1382 if ev.Header.Height != expectedHeight { 1383 t.Errorf("Event block height is wrong. Got: %d. Expected: %d", ev.Header.Height, expectedHeight) 1384 } 1385 return 1386 } 1387 } 1388 t.Fatalf("Did not see LogEvent") 1389 }) 1390 1391 t.Run("BigModExp", func(t *testing.T) { 1392 st := acmstate.NewMemoryState() 1393 account1 := newAccount(t, st, "1") 1394 account2 := newAccount(t, st, "101") 1395 1396 // The solidity compiled contract. It calls bigmodexp with b,e,m inputs and compares the result with proof, where m is the mod, b the base, e the exp, and proof the expected result. 1397 bytecode := solidity.DeployedBytecode_BigMod 1398 1399 // The function "expmod" is an assertion. It takes the base, exponent, modulus, and the expected value and 1400 // returns 1 if the values match. 1401 spec, err := abi.ReadSpec(solidity.Abi_BigMod) 1402 require.NoError(t, err) 1403 1404 expModFunctionID := spec.Functions["expmod"].FunctionID 1405 1406 n := int64(10) 1407 for base := -n; base < n; base++ { 1408 for exp := -n; exp < n; exp++ { 1409 for mod := int64(1); mod < n; mod++ { 1410 b := big.NewInt(base) 1411 e := big.NewInt(exp) 1412 m := big.NewInt(mod) 1413 v := new(big.Int).Exp(b, e, m) 1414 if v == nil { 1415 continue 1416 } 1417 1418 input := MustSplice(expModFunctionID, // expmod function 1419 BigIntToWord256(b), BigIntToWord256(e), BigIntToWord256(m), // base^exp % mod 1420 BigIntToWord256(v)) // == expected 1421 1422 gas := big.NewInt(10000000) 1423 out, err := call(vm, st, account1, account2, bytecode, input, gas) 1424 1425 require.NoError(t, err) 1426 1427 require.Equal(t, One256, LeftPadWord256(out), "expected %d^%d mod %d == %d", 1428 base, exp, mod, e) 1429 } 1430 } 1431 } 1432 }) 1433 1434 t.Run("SDIV", func(t *testing.T) { 1435 st := acmstate.NewMemoryState() 1436 blockchain := new(engine.TestBlockchain) 1437 eventSink := exec.NewNoopEventSink() 1438 1439 account1 := newAccount(t, st, "1") 1440 account2 := newAccount(t, st, "101") 1441 1442 tests := []struct { 1443 name string 1444 bytecode []byte 1445 expected []byte 1446 }{ 1447 { 1448 // (SDIV 7 3 ) 1449 name: "sdiv0", 1450 bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x07, SDIV, return1()), 1451 expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 1455 }, 1456 { 1457 // (SDIV 7 (- 0 3) ) 1458 name: "sdiv1", 1459 bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x00, SUB, PUSH1, 0x07, SDIV, return1()), 1460 expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1461 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1462 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1463 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, 1464 }, 1465 { 1466 // (SDIV (- 0 7) 3 ) 1467 name: "sdiv2", 1468 bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x07, PUSH1, 0x00, SUB, SDIV, return1()), 1469 expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1470 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1471 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1472 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, 1473 }, 1474 { 1475 // (SDIV (- 0 7) (- 0 3) ) 1476 name: "sdiv3", 1477 bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x00, SUB, PUSH1, 0x07, PUSH1, 0x00, SUB, SDIV, return1()), 1478 expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 1482 }, 1483 } 1484 for _, tt := range tests { 1485 params := engine.CallParams{ 1486 Caller: account1, 1487 Callee: account2, 1488 Gas: big.NewInt(1000000), 1489 } 1490 if output, err := vm.Execute(st, blockchain, eventSink, params, tt.bytecode); err != nil || !bytes.Equal(output, tt.expected) { 1491 t.Errorf("Reported error in %v.", tt.name) 1492 assert.NoError(t, err) 1493 assert.Equal(t, tt.expected, output) 1494 } 1495 } 1496 }) 1497 1498 t.Run("SMOD", func(t *testing.T) { 1499 st := acmstate.NewMemoryState() 1500 blockchain := new(engine.TestBlockchain) 1501 eventSink := exec.NewNoopEventSink() 1502 1503 account1 := newAccount(t, st, "1") 1504 account2 := newAccount(t, st, "101") 1505 1506 tests := []struct { 1507 name string 1508 bytecode []byte 1509 expected []byte 1510 }{ 1511 { 1512 // (SMOD 7 3) 1513 name: "smod0", 1514 bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x07, SMOD, return1()), 1515 expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1519 }, 1520 { 1521 // (SMOD 7 (- 0 3)) 1522 name: "smod1", 1523 bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x00, SUB, PUSH1, 0x07, SMOD, return1()), 1524 expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1528 }, 1529 { 1530 // (SMOD (- 0 7) 3) 1531 name: "smod2", 1532 bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x07, PUSH1, 0x00, SUB, SMOD, return1()), 1533 expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1534 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1535 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1536 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1537 }, 1538 { 1539 // (SMOD (- 0 7) (- 0 3)) 1540 name: "smod3", 1541 bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x00, SUB, PUSH1, 0x07, PUSH1, 0x00, SUB, SMOD, return1()), 1542 expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1543 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1544 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1545 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1546 }, 1547 } 1548 for _, tt := range tests { 1549 params := engine.CallParams{ 1550 Caller: account1, 1551 Callee: account2, 1552 Gas: big.NewInt(1000000), 1553 } 1554 if output, err := vm.Execute(st, blockchain, eventSink, params, tt.bytecode); err != nil || !bytes.Equal(output, tt.expected) { 1555 t.Errorf("Reported error in %v.", tt.name) 1556 assert.NoError(t, err) 1557 assert.Equal(t, tt.expected, output) 1558 } 1559 } 1560 }) 1561 1562 t.Run("SIGNEXTEND and MSTORE8", func(t *testing.T) { 1563 st := acmstate.NewMemoryState() 1564 blockchain := new(engine.TestBlockchain) 1565 eventSink := exec.NewNoopEventSink() 1566 1567 account1 := newAccount(t, st, "1") 1568 account2 := newAccount(t, st, "101") 1569 1570 tests := []struct { 1571 name string 1572 bytecode []byte 1573 expected []byte 1574 }{ 1575 { 1576 // 0x6A == 0b01101010 1577 name: "signextend0", 1578 bytecode: MustSplice(PUSH3, 0x12, 0x2F, 0x6A, PUSH1, 0x00, SIGNEXTEND, return1()), 1579 expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A}, 1583 }, 1584 { 1585 name: "signextend1", 1586 bytecode: MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1587 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1588 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1589 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1590 PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1591 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1592 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1593 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, SIGNEXTEND, return1()), 1594 expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1595 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1596 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1597 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1598 }, 1599 { 1600 name: "mstore8", 1601 bytecode: MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1602 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1603 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1604 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1605 PUSH1, 0x01, MSTORE8, PUSH1, 0x01, MLOAD, return1()), 1606 expected: []byte{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 1610 }, 1611 } 1612 for _, tt := range tests { 1613 params := engine.CallParams{ 1614 Caller: account1, 1615 Callee: account2, 1616 Gas: big.NewInt(1000000), 1617 } 1618 if output, err := vm.Execute(st, blockchain, eventSink, params, tt.bytecode); err != nil || !bytes.Equal(output, tt.expected) { 1619 t.Errorf("Reported error in %v.", tt.name) 1620 assert.NoError(t, err) 1621 assert.Equal(t, tt.expected, output) 1622 } 1623 } 1624 }) 1625 1626 t.Run("JUMPDEST", func(t *testing.T) { 1627 st := acmstate.NewMemoryState() 1628 blockchain := new(engine.TestBlockchain) 1629 eventSink := exec.NewNoopEventSink() 1630 1631 account1 := newAccount(t, st, "1") 1632 account2 := newAccount(t, st, "101") 1633 1634 tests := []struct { 1635 name string 1636 bytecode []byte 1637 expected_out []byte 1638 expected_err *errors.Code 1639 }{ 1640 { 1641 name: "Jump_InsidePushWithJumpDest", 1642 bytecode: MustSplice(PUSH1, 0x04, PUSH1, 0x03, ADD, JUMP, 1643 PUSH6, JUMPDEST, 0x60, 0x01, 0x60, 0x01, 0x55, return1()), 1644 expected_err: errors.Codes.InvalidJumpDest, 1645 }, 1646 { 1647 name: "Jumpi_InsidePushWithJumpDest", 1648 bytecode: MustSplice(PUSH1, 0x01, PUSH1, 0x06, PUSH1, 0x03, ADD, JUMPI, 1649 PUSH6, JUMPDEST, 0x60, 0x01, 0x60, 0x01, 0x55, return1()), 1650 expected_err: errors.Codes.InvalidJumpDest, 1651 }, 1652 } 1653 for _, tt := range tests { 1654 params := engine.CallParams{ 1655 Caller: account1, 1656 Callee: account2, 1657 Gas: big.NewInt(1000000), 1658 } 1659 if output, err := vm.Execute(st, blockchain, eventSink, params, tt.bytecode); errors.GetCode(err) != tt.expected_err { 1660 t.Errorf("FAIL: %v.", tt.name) 1661 assert.Equal(t, tt.expected_err, errors.GetCode(err)) 1662 } else if tt.expected_err == errors.Codes.None && !bytes.Equal(output, tt.expected_out) { 1663 t.Errorf("FAIL: %v.", tt.name) 1664 assert.Equal(t, tt.expected_out, output) 1665 } 1666 } 1667 }) 1668 } 1669 1670 // helpers 1671 1672 func newAccount(t testing.TB, st acmstate.ReaderWriter, name string) crypto.Address { 1673 address := engine.AddressFromName(name) 1674 err := engine.CreateAccount(st, address) 1675 require.NoError(t, err) 1676 return address 1677 } 1678 1679 func makeAccountWithCode(t testing.TB, st acmstate.ReaderWriter, name string, code []byte) crypto.Address { 1680 address := engine.AddressFromName(name) 1681 err := engine.CreateAccount(st, address) 1682 require.NoError(t, err) 1683 err = engine.InitEVMCode(st, address, code) 1684 require.NoError(t, err) 1685 addToBalance(t, st, address, 9999999) 1686 return address 1687 } 1688 1689 func addToBalance(t testing.TB, st acmstate.ReaderWriter, address crypto.Address, amount uint64) { 1690 err := engine.UpdateAccount(st, address, func(account *acm.Account) error { 1691 return account.AddToBalance(amount) 1692 }) 1693 require.NoError(t, err) 1694 } 1695 1696 func call(vm *EVM, st acmstate.ReaderWriter, origin, callee crypto.Address, code []byte, input []byte, 1697 gas *big.Int) ([]byte, error) { 1698 1699 evs := new(exec.Events) 1700 out, err := vm.Execute(st, new(engine.TestBlockchain), evs, engine.CallParams{ 1701 Caller: origin, 1702 Callee: callee, 1703 Input: input, 1704 Gas: gas, 1705 }, code) 1706 1707 if err != nil { 1708 return nil, &errors.CallError{ 1709 CodedError: errors.AsException(err), 1710 NestedErrors: evs.NestedCallErrors(), 1711 } 1712 } 1713 return out, nil 1714 } 1715 1716 // These code segment helpers exercise the MSTORE MLOAD MSTORE cycle to test 1717 // both of the memory operations. Each MSTORE is done on the memory boundary 1718 // (at MSIZE) which Solidity uses to find guaranteed unallocated memory. 1719 1720 // storeAtEnd expects the value to be stored to be on top of the stack, it then 1721 // stores that value at the current memory boundary 1722 func storeAtEnd() []byte { 1723 // Pull in MSIZE (to carry forward to MLOAD), swap in value to store, store it at MSIZE 1724 return MustSplice(MSIZE, SWAP1, DUP2, MSTORE) 1725 } 1726 1727 func returnAfterStore() []byte { 1728 return MustSplice(PUSH1, 32, DUP2, RETURN) 1729 } 1730 1731 // Store the top element of the stack (which is a 32-byte word) in memory 1732 // and return it. Useful for a simple return value. 1733 func return1() []byte { 1734 return MustSplice(PUSH1, 0, MSTORE, returnWord()) 1735 } 1736 1737 func returnWord() []byte { 1738 // PUSH1 => return size, PUSH1 => return offset, RETURN 1739 return MustSplice(PUSH1, 32, PUSH1, 0, RETURN) 1740 } 1741 1742 // Subscribes to an AccCall, runs the vm, returns the output any direct exception 1743 // and then waits for any exceptions transmitted by Data in the AccCall 1744 // event (in the case of no direct error from call we will block waiting for 1745 // at least 1 AccCall event) 1746 func runVM(st acmstate.ReaderWriter, caller, callee crypto.Address, code []byte, gas uint64) *exec.TxExecution { 1747 gasBefore := new(big.Int).SetUint64(gas) 1748 txe := new(exec.TxExecution) 1749 vm := New(engine.Options{ 1750 DebugOpcodes: true, 1751 }) 1752 bigGas := new(big.Int).SetUint64(gas) 1753 params := engine.CallParams{ 1754 Caller: caller, 1755 Callee: callee, 1756 Gas: bigGas, 1757 } 1758 output, err := vm.Execute(st, new(engine.TestBlockchain), txe, params, code) 1759 txe.PushError(err) 1760 for _, ev := range txe.ExceptionalCalls() { 1761 txe.PushError(ev.Header.Exception) 1762 } 1763 txe.Return(output, gasBefore.Sub(gasBefore, bigGas).Uint64()) 1764 return txe 1765 } 1766 1767 // this is code to call another contract (hardcoded as addr) 1768 func callContractCode(addr crypto.Address) []byte { 1769 gas1, gas2 := byte(0x1), byte(0x1) 1770 value := byte(0x69) 1771 inOff, inSize := byte(0x0), byte(0x0) // no call data 1772 retOff, retSize := byte(0x0), byte(0x20) 1773 // this is the code we want to run (send funds to an account and return) 1774 return MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 1775 inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize, 1776 PUSH1, retOff, RETURN) 1777 } 1778 1779 // Produce bytecode for a PUSH<N>, b_1, ..., b_N where the N is number of bytes 1780 // contained in the unpadded word 1781 func pushWord(word Word256) []byte { 1782 leadingZeros := byte(0) 1783 for leadingZeros < 32 { 1784 if word[leadingZeros] == 0 { 1785 leadingZeros++ 1786 } else { 1787 return MustSplice(byte(PUSH32)-leadingZeros, word[leadingZeros:]) 1788 } 1789 } 1790 return MustSplice(PUSH1, 0) 1791 }