github.com/datachainlab/burrow@v0.25.0/execution/evm/vm_test.go (about) 1 // Copyright 2017 Monax Industries Limited 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package evm 16 17 import ( 18 "strconv" 19 "testing" 20 "time" 21 22 "fmt" 23 24 "github.com/hyperledger/burrow/acm/acmstate" 25 26 "github.com/hyperledger/burrow/acm" 27 "github.com/hyperledger/burrow/binary" 28 . "github.com/hyperledger/burrow/binary" 29 "github.com/hyperledger/burrow/crypto" 30 "github.com/hyperledger/burrow/execution/errors" 31 . "github.com/hyperledger/burrow/execution/evm/asm" 32 . "github.com/hyperledger/burrow/execution/evm/asm/bc" 33 "github.com/hyperledger/burrow/execution/exec" 34 "github.com/hyperledger/burrow/logging" 35 "github.com/hyperledger/burrow/permission" 36 "github.com/hyperledger/burrow/txs" 37 "github.com/stretchr/testify/assert" 38 "github.com/stretchr/testify/require" 39 hex "github.com/tmthrgd/go-hex" 40 "golang.org/x/crypto/ripemd160" 41 ) 42 43 // Test output is a bit clearer if we /dev/null the logging, but can be re-enabled by uncommenting the below 44 //var logger, _, _ = lifecycle.NewStdErrLogger() 45 // 46 var logger = logging.NewNoopLogger() 47 48 type testState struct { 49 *State 50 BlockHashProvider func(blockNumber uint64) (Word256, error) 51 } 52 53 func NewTestState(st acmstate.ReaderWriter, blockHashGetter func(uint64) []byte) *testState { 54 evmState := NewState(st, blockHashGetter) 55 return &testState{ 56 State: evmState, 57 BlockHashProvider: evmState.GetBlockHash, 58 } 59 } 60 61 func newAppState() *FakeAppState { 62 fas := &FakeAppState{ 63 accounts: make(map[crypto.Address]*acm.Account), 64 storage: make(map[string]Word256), 65 } 66 // For default permissions 67 fas.accounts[acm.GlobalPermissionsAddress] = &acm.Account{ 68 Permissions: permission.DefaultAccountPermissions, 69 } 70 return fas 71 } 72 73 func newParams() Params { 74 return Params{ 75 BlockHeight: 0, 76 BlockTime: 0, 77 GasLimit: 0, 78 } 79 } 80 81 func newAddress(name string) crypto.Address { 82 hasher := ripemd160.New() 83 hasher.Write([]byte(name)) 84 return crypto.MustAddressFromBytes(hasher.Sum(nil)) 85 } 86 87 func newAccount(st Interface, name string) crypto.Address { 88 address := newAddress(name) 89 st.CreateAccount(address) 90 return address 91 } 92 93 func makeAccountWithCode(st Interface, name string, code []byte) crypto.Address { 94 address := newAddress(name) 95 st.CreateAccount(address) 96 st.InitCode(address, code) 97 st.AddToBalance(address, 9999999) 98 return address 99 } 100 101 // Runs a basic loop 102 func TestVM(t *testing.T) { 103 cache := NewState(newAppState(), blockHashGetter) 104 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 105 106 // Create accounts 107 account1 := newAccount(cache, "1") 108 account2 := newAccount(cache, "101") 109 110 var gas uint64 = 100000 111 112 bytecode := MustSplice(PUSH1, 0x00, PUSH1, 0x20, MSTORE, JUMPDEST, PUSH2, 0x0F, 0x0F, PUSH1, 0x20, MLOAD, 113 SLT, ISZERO, PUSH1, 0x1D, JUMPI, PUSH1, 0x01, PUSH1, 0x20, MLOAD, ADD, PUSH1, 0x20, 114 MSTORE, PUSH1, 0x05, JUMP, JUMPDEST) 115 116 start := time.Now() 117 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 118 t.Logf("Output: %v Error: %v\n", output, err) 119 t.Logf("Call took: %v", time.Since(start)) 120 require.NoError(t, err) 121 require.NoError(t, cache.Error()) 122 } 123 124 func TestSHL(t *testing.T) { 125 cache := NewState(newAppState(), blockHashGetter) 126 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 127 account1 := newAccount(cache, "1") 128 account2 := newAccount(cache, "101") 129 130 var gas uint64 = 100000 131 132 //Shift left 0 133 bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHL, return1()) 134 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 135 value := []uint8([]byte{0x1}) 136 expected := LeftPadBytes(value, 32) 137 assert.Equal(t, expected, output) 138 139 t.Logf("Result: %v == %v\n", output, expected) 140 141 if err != nil { 142 t.Fatal(err) 143 } 144 145 //Alternative shift left 0 146 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 147 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHL, return1()) 148 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 149 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 150 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 151 152 assert.Equal(t, expected, output) 153 154 t.Logf("Result: %v == %v\n", output, expected) 155 156 if err != nil { 157 t.Fatal(err) 158 } 159 160 //Shift left 1 161 bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHL, return1()) 162 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 163 value = []uint8([]byte{0x2}) 164 expected = LeftPadBytes(value, 32) 165 assert.Equal(t, expected, output) 166 167 t.Logf("Result: %v == %v\n", output, expected) 168 169 if err != nil { 170 t.Fatal(err) 171 } 172 173 //Alternative shift left 1 174 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 175 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1()) 176 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 177 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 178 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}) 179 180 assert.Equal(t, expected, output) 181 182 t.Logf("Result: %v == %v\n", output, expected) 183 184 if err != nil { 185 t.Fatal(err) 186 } 187 188 //Alternative shift left 1 189 bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 190 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1()) 191 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 192 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 193 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}) 194 195 assert.Equal(t, expected, output) 196 197 t.Logf("Result: %v == %v\n", output, expected) 198 199 if err != nil { 200 t.Fatal(err) 201 } 202 203 //Shift left 255 204 bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0xFF, SHL, return1()) 205 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 206 value = []uint8([]byte{0x80}) 207 expected = RightPadBytes(value, 32) 208 assert.Equal(t, expected, output) 209 210 t.Logf("Result: %v == %v\n", output, expected) 211 212 if err != nil { 213 t.Fatal(err) 214 } 215 216 //Alternative shift left 255 217 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 218 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHL, return1()) 219 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 220 value = []uint8([]byte{0x80}) 221 expected = RightPadBytes(value, 32) 222 assert.Equal(t, expected, output) 223 224 t.Logf("Result: %v == %v\n", output, expected) 225 226 if err != nil { 227 t.Fatal(err) 228 } 229 230 //Shift left 256 (overflow) 231 bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x00, SHL, return1()) 232 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 233 value = []uint8([]byte{0x00}) 234 expected = LeftPadBytes(value, 32) 235 assert.Equal(t, expected, output) 236 237 t.Logf("Result: %v == %v\n", output, expected) 238 239 if err != nil { 240 t.Fatal(err) 241 } 242 243 //Alternative shift left 256 (overflow) 244 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 245 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHL, 246 return1()) 247 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 248 value = []uint8([]byte{0x00}) 249 expected = LeftPadBytes(value, 32) 250 assert.Equal(t, expected, output) 251 252 t.Logf("Result: %v == %v\n", output, expected) 253 254 if err != nil { 255 t.Fatal(err) 256 } 257 258 //Shift left 257 (overflow) 259 bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x01, SHL, return1()) 260 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 261 value = []uint8([]byte{0x00}) 262 expected = LeftPadBytes(value, 32) 263 assert.Equal(t, expected, output) 264 265 t.Logf("Result: %v == %v\n", output, expected) 266 267 if err != nil { 268 t.Fatal(err) 269 } 270 271 require.NoError(t, cache.Error()) 272 } 273 274 func TestSHR(t *testing.T) { 275 cache := NewState(newAppState(), blockHashGetter) 276 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 277 account1 := newAccount(cache, "1") 278 account2 := newAccount(cache, "101") 279 280 var gas uint64 = 100000 281 282 //Shift right 0 283 bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHR, return1()) 284 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 285 value := []uint8([]byte{0x1}) 286 expected := LeftPadBytes(value, 32) 287 assert.Equal(t, expected, output) 288 289 t.Logf("Result: %v == %v\n", output, expected) 290 291 if err != nil { 292 t.Fatal(err) 293 } 294 295 //Alternative shift right 0 296 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 297 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHR, return1()) 298 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 299 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 300 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 301 302 assert.Equal(t, expected, output) 303 304 t.Logf("Result: %v == %v\n", output, expected) 305 306 if err != nil { 307 t.Fatal(err) 308 } 309 310 //Shift right 1 311 bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHR, return1()) 312 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 313 value = []uint8([]byte{0x00}) 314 expected = LeftPadBytes(value, 32) 315 assert.Equal(t, expected, output) 316 317 t.Logf("Result: %v == %v\n", output, expected) 318 319 if err != nil { 320 t.Fatal(err) 321 } 322 323 //Alternative shift right 1 324 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SHR, return1()) 326 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 327 value = []uint8([]byte{0x40}) 328 expected = RightPadBytes(value, 32) 329 assert.Equal(t, expected, output) 330 331 t.Logf("Result: %v == %v\n", output, expected) 332 333 if err != nil { 334 t.Fatal(err) 335 } 336 337 //Alternative shift right 1 338 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 339 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHR, return1()) 340 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 341 expected = []uint8([]byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 342 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 343 344 assert.Equal(t, expected, output) 345 346 t.Logf("Result: %v == %v\n", output, expected) 347 348 if err != nil { 349 t.Fatal(err) 350 } 351 352 //Shift right 255 353 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SHR, return1()) 355 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 356 value = []uint8([]byte{0x1}) 357 expected = LeftPadBytes(value, 32) 358 assert.Equal(t, expected, output) 359 360 t.Logf("Result: %v == %v\n", output, expected) 361 362 if err != nil { 363 t.Fatal(err) 364 } 365 366 //Alternative shift right 255 367 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 368 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHR, return1()) 369 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 370 value = []uint8([]byte{0x1}) 371 expected = LeftPadBytes(value, 32) 372 assert.Equal(t, expected, output) 373 374 t.Logf("Result: %v == %v\n", output, expected) 375 376 if err != nil { 377 t.Fatal(err) 378 } 379 380 //Shift right 256 (underflow) 381 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SHR, 383 return1()) 384 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 385 value = []uint8([]byte{0x00}) 386 expected = LeftPadBytes(value, 32) 387 assert.Equal(t, expected, output) 388 389 t.Logf("Result: %v == %v\n", output, expected) 390 391 if err != nil { 392 t.Fatal(err) 393 } 394 395 //Alternative shift right 256 (underflow) 396 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 397 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHR, 398 return1()) 399 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 400 value = []uint8([]byte{0x00}) 401 expected = LeftPadBytes(value, 32) 402 assert.Equal(t, expected, output) 403 404 t.Logf("Result: %v == %v\n", output, expected) 405 406 if err != nil { 407 t.Fatal(err) 408 } 409 410 //Shift right 257 (underflow) 411 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SHR, 413 return1()) 414 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 415 value = []uint8([]byte{0x00}) 416 expected = LeftPadBytes(value, 32) 417 assert.Equal(t, expected, output) 418 419 t.Logf("Result: %v == %v\n", output, expected) 420 421 if err != nil { 422 t.Fatal(err) 423 } 424 425 require.NoError(t, cache.Error()) 426 } 427 428 func TestSAR(t *testing.T) { 429 cache := NewState(newAppState(), blockHashGetter) 430 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 431 account1 := newAccount(cache, "1") 432 account2 := newAccount(cache, "101") 433 434 var gas uint64 = 100000 435 436 //Shift arith right 0 437 bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SAR, return1()) 438 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 439 value := []uint8([]byte{0x1}) 440 expected := LeftPadBytes(value, 32) 441 assert.Equal(t, expected, output) 442 443 t.Logf("Result: %v == %v\n", output, expected) 444 445 if err != nil { 446 t.Fatal(err) 447 } 448 449 //Alternative arith shift right 0 450 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 451 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SAR, return1()) 452 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 453 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 454 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 455 456 assert.Equal(t, expected, output) 457 458 t.Logf("Result: %v == %v\n", output, expected) 459 460 if err != nil { 461 t.Fatal(err) 462 } 463 464 //Shift arith right 1 465 bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SAR, return1()) 466 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 467 value = []uint8([]byte{0x00}) 468 expected = LeftPadBytes(value, 32) 469 assert.Equal(t, expected, output) 470 471 t.Logf("Result: %v == %v\n", output, expected) 472 473 if err != nil { 474 t.Fatal(err) 475 } 476 477 //Alternative shift arith right 1 478 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SAR, return1()) 480 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 481 value = []uint8([]byte{0xc0}) 482 expected = RightPadBytes(value, 32) 483 assert.Equal(t, expected, output) 484 485 t.Logf("Result: %v == %v\n", output, expected) 486 487 if err != nil { 488 t.Fatal(err) 489 } 490 491 //Alternative shift arith right 1 492 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 493 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SAR, return1()) 494 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 495 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 496 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 497 498 assert.Equal(t, expected, output) 499 500 t.Logf("Result: %v == %v\n", output, expected) 501 502 if err != nil { 503 t.Fatal(err) 504 } 505 506 //Shift arith right 255 507 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SAR, return1()) 509 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 510 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 511 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 512 513 assert.Equal(t, expected, output) 514 515 t.Logf("Result: %v == %v\n", output, expected) 516 517 if err != nil { 518 t.Fatal(err) 519 } 520 521 //Alternative shift arith right 255 522 bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 523 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1()) 524 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 525 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 526 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 527 528 assert.Equal(t, expected, output) 529 530 t.Logf("Result: %v == %v\n", output, expected) 531 532 if err != nil { 533 t.Fatal(err) 534 } 535 536 //Alternative shift arith right 255 537 bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 538 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1()) 539 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 540 value = []uint8([]byte{0x00}) 541 expected = RightPadBytes(value, 32) 542 assert.Equal(t, expected, output) 543 544 t.Logf("Result: %v == %v\n", output, expected) 545 546 if err != nil { 547 t.Fatal(err) 548 } 549 550 //Shift arith right 256 (reset) 551 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SAR, 553 return1()) 554 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 555 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 556 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 557 558 assert.Equal(t, expected, output) 559 560 t.Logf("Result: %v == %v\n", output, expected) 561 562 if err != nil { 563 t.Fatal(err) 564 } 565 566 //Alternative shift arith right 256 (reset) 567 bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 568 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SAR, 569 return1()) 570 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 571 value = []uint8([]byte{0x00}) 572 expected = LeftPadBytes(value, 32) 573 assert.Equal(t, expected, output) 574 575 t.Logf("Result: %v == %v\n", output, expected) 576 577 if err != nil { 578 t.Fatal(err) 579 } 580 581 //Shift arith right 257 (reset) 582 bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SAR, 584 return1()) 585 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 586 expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 587 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) 588 589 assert.Equal(t, expected, output) 590 591 t.Logf("Result: %v == %v\n", output, expected) 592 593 if err != nil { 594 t.Fatal(err) 595 } 596 597 require.NoError(t, cache.Error()) 598 } 599 600 //Test attempt to jump to bad destination (position 16) 601 func TestJumpErr(t *testing.T) { 602 cache := NewState(newAppState(), blockHashGetter) 603 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 604 605 // Create accounts 606 account1 := newAccount(cache, "1") 607 account2 := newAccount(cache, "2") 608 609 var gas uint64 = 100000 610 611 bytecode := MustSplice(PUSH1, 0x10, JUMP) 612 613 var err error 614 ch := make(chan struct{}) 615 go func() { 616 _, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 617 ch <- struct{}{} 618 }() 619 tick := time.NewTicker(time.Second * 2) 620 select { 621 case <-tick.C: 622 t.Fatal("VM ended up in an infinite loop from bad jump dest (it took too long!)") 623 case <-ch: 624 if err == nil { 625 t.Fatal("Expected invalid jump dest err") 626 } 627 } 628 } 629 630 // Tests the code for a subcurrency contract compiled by serpent 631 func TestSubcurrency(t *testing.T) { 632 st := newAppState() 633 cache := NewState(st, blockHashGetter) 634 // Create accounts 635 account1 := newAccount(cache, "1, 2, 3") 636 account2 := newAccount(cache, "3, 2, 1") 637 cache.Sync() 638 639 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 640 641 var gas uint64 = 1000 642 643 bytecode := MustSplice(PUSH3, 0x0F, 0x42, 0x40, CALLER, SSTORE, PUSH29, 0x01, 0x00, 0x00, 0x00, 644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 646 0x00, CALLDATALOAD, DIV, PUSH4, 0x15, 0xCF, 0x26, 0x84, DUP2, EQ, ISZERO, PUSH2, 647 0x00, 0x46, JUMPI, PUSH1, 0x04, CALLDATALOAD, PUSH1, 0x40, MSTORE, PUSH1, 0x40, 648 MLOAD, SLOAD, PUSH1, 0x60, MSTORE, PUSH1, 0x20, PUSH1, 0x60, RETURN, JUMPDEST, 649 PUSH4, 0x69, 0x32, 0x00, 0xCE, DUP2, EQ, ISZERO, PUSH2, 0x00, 0x87, JUMPI, PUSH1, 650 0x04, CALLDATALOAD, PUSH1, 0x80, MSTORE, PUSH1, 0x24, CALLDATALOAD, PUSH1, 0xA0, 651 MSTORE, CALLER, SLOAD, PUSH1, 0xC0, MSTORE, CALLER, PUSH1, 0xE0, MSTORE, PUSH1, 652 0xA0, MLOAD, PUSH1, 0xC0, MLOAD, SLT, ISZERO, ISZERO, PUSH2, 0x00, 0x86, JUMPI, 653 PUSH1, 0xA0, MLOAD, PUSH1, 0xC0, MLOAD, SUB, PUSH1, 0xE0, MLOAD, SSTORE, PUSH1, 654 0xA0, MLOAD, PUSH1, 0x80, MLOAD, SLOAD, ADD, PUSH1, 0x80, MLOAD, SSTORE, JUMPDEST, 655 JUMPDEST, POP, JUMPDEST, PUSH1, 0x00, PUSH1, 0x00, RETURN) 656 657 data := hex.MustDecodeString("693200CE0000000000000000000000004B4363CDE27C2EB05E66357DB05BC5C88F850C1A0000000000000000000000000000000000000000000000000000000000000005") 658 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, data, 0, &gas) 659 t.Logf("Output: %v Error: %v\n", output, err) 660 if err != nil { 661 t.Fatal(err) 662 } 663 require.NoError(t, cache.Error()) 664 } 665 666 //This test case is taken from EIP-140 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md); 667 //it is meant to test the implementation of the REVERT opcode 668 func TestRevert(t *testing.T) { 669 cache := NewState(newAppState(), blockHashGetter) 670 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 671 672 // Create accounts 673 account1 := newAccount(cache, "1") 674 account2 := newAccount(cache, "1, 0, 1") 675 676 key, value := []byte{0x00}, []byte{0x00} 677 cache.SetStorage(account1, LeftPadWord256(key), LeftPadWord256(value)) 678 679 var gas uint64 = 100000 680 681 bytecode := MustSplice(PUSH13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 682 PUSH1, 0x00, SSTORE, PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 684 PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, REVERT) 685 686 /*bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 687 0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 688 0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, REVERT)*/ 689 690 output, cErr := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 691 assert.Error(t, cErr, "Expected execution reverted error") 692 693 storageVal := cache.GetStorage(account1, LeftPadWord256(key)) 694 assert.Equal(t, LeftPadWord256(value), storageVal) 695 696 t.Logf("Output: %v\n", output) 697 } 698 699 // Test sending tokens from a contract to another account 700 func TestSendCall(t *testing.T) { 701 cache := NewState(newAppState(), blockHashGetter) 702 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 703 704 // Create accounts 705 account1 := newAccount(cache, "1") 706 account2 := newAccount(cache, "2") 707 account3 := newAccount(cache, "3") 708 cache.Sync() 709 710 // account1 will call account2 which will trigger CALL opcode to account3 711 addr := account3 712 contractCode := callContractCode(addr) 713 714 //---------------------------------------------- 715 // account2 has insufficient balance, should fail 716 txe := runVM(cache, ourVm, account1, account2, contractCode, 100000) 717 exCalls := txe.ExceptionalCalls() 718 require.Len(t, exCalls, 1) 719 assertErrorCode(t, errors.ErrorCodeInsufficientBalance, exCalls[0].Header.Exception) 720 721 //---------------------------------------------- 722 // give account2 sufficient balance, should pass 723 cache.AddToBalance(account2, 100000) 724 txe = runVM(cache, ourVm, account1, account2, contractCode, 1000) 725 assert.Nil(t, txe.Exception, "Should have sufficient balance") 726 727 //---------------------------------------------- 728 // insufficient gas, should fail 729 txe = runVM(cache, ourVm, account1, account2, contractCode, 100) 730 assert.NotNil(t, txe.Exception, "Expected insufficient gas error") 731 } 732 733 // Test to ensure that contracts called with STATICCALL cannot modify state 734 // as per https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md 735 func TestStaticCallReadOnly(t *testing.T) { 736 gas1, gas2 := byte(0x1), byte(0x1) 737 value := byte(0x69) 738 var inOff, inSize, retOff, retSize byte 739 740 logDefault := MustSplice(PUSH1, inSize, PUSH1, inOff) 741 testRecipient := newAddress("1") 742 // check all illegal state modifications in child staticcall frame 743 for _, illegalContractCode := range []acm.Bytecode{ 744 MustSplice(PUSH9, "arbitrary", PUSH1, 0x00, SSTORE), 745 MustSplice(logDefault, LOG0), 746 MustSplice(logDefault, PUSH1, 0x1, LOG1), 747 MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, LOG2), 748 MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, LOG3), 749 MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, LOG4), 750 MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x69, CREATE), 751 MustSplice(PUSH20, testRecipient, SELFDESTRUCT), 752 } { 753 // TODO: CREATE2 754 755 t.Logf("Testing state-modifying bytecode: %v", illegalContractCode.MustTokens()) 756 cache := NewState(newAppState(), blockHashGetter) 757 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger, DebugOpcodes) 758 callee := makeAccountWithCode(cache, "callee", MustSplice(illegalContractCode, PUSH1, 0x1, return1())) 759 760 // equivalent to CALL, but enforce state immutability for children 761 caller := makeAccountWithCode(cache, "caller", 762 MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff, 763 PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize, 764 PUSH1, retOff, RETURN)) 765 766 txe := runVM(cache, ourVm, caller, callee, cache.GetCode(caller), 1000) 767 // the topmost caller can never *illegally* modify state 768 require.Error(t, txe.Exception) 769 assertErrorCode(t, errors.ErrorCodeIllegalWrite, txe.Exception, 770 "should get an error from child accounts that cache is read only") 771 } 772 } 773 774 func TestStaticCallWithValue(t *testing.T) { 775 gas1, gas2 := byte(0x1), byte(0x1) 776 value := byte(0x69) 777 var inOff, inSize, retOff, retSize byte 778 779 cache := NewState(newAppState(), blockHashGetter) 780 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 781 782 finalAddress := makeAccountWithCode(cache, "final", MustSplice(PUSH1, int64(20), return1())) 783 784 // intermediate account CALLs another contract *with* a value 785 callee := makeAccountWithCode(cache, "callee", MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 786 inOff, PUSH1, value, PUSH20, finalAddress, PUSH2, gas1, gas2, CALL, returnWord())) 787 788 caller := makeAccountWithCode(cache, "caller", 789 MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 790 inOff, PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize, 791 PUSH1, retOff, RETURN)) 792 793 cache.AddToBalance(callee, 100000) 794 txe := runVM(cache, ourVm, caller, callee, cache.GetCode(caller), 1000) 795 require.NotNil(t, txe.Exception) 796 assertErrorCode(t, errors.ErrorCodeIllegalWrite, txe.Exception, "expected static call violation because of call with value") 797 } 798 799 func TestStaticCallNoValue(t *testing.T) { 800 gas1, gas2 := byte(0x1), byte(0x1) 801 value := byte(0x69) 802 var inOff, inSize, retOff, retSize byte 803 804 // this final test just checks that STATICCALL actually works 805 cache := NewState(newAppState(), blockHashGetter) 806 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 807 808 finalAddress := makeAccountWithCode(cache, "final", MustSplice(PUSH1, int64(20), return1())) 809 // intermediate account CALLs another contract *without* a value 810 callee := makeAccountWithCode(cache, "callee", MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 811 inOff, PUSH1, 0x00, PUSH20, finalAddress, PUSH2, gas1, gas2, CALL, returnWord())) 812 813 caller := makeAccountWithCode(cache, "caller", 814 MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 815 inOff, PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize, 816 PUSH1, retOff, RETURN)) 817 818 cache.AddToBalance(callee, 100000) 819 txe := runVM(cache, ourVm, caller, callee, cache.GetCode(caller), 1000) 820 // no exceptions expected because value never set in children 821 require.NoError(t, txe.Exception.AsError()) 822 exCalls := txe.ExceptionalCalls() 823 require.Len(t, exCalls, 0) 824 } 825 826 // Test evm account creation 827 func TestCreate(t *testing.T) { 828 st := newAppState() 829 cache := NewState(st, blockHashGetter) 830 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 831 832 callee := makeAccountWithCode(cache, "callee", MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x0, CREATE, PUSH1, 0, MSTORE, PUSH1, 20, PUSH1, 12, RETURN)) 833 // ensure pre-generated address has same sequence number 834 nonce := make([]byte, txs.HashLength+uint64Length) 835 copy(nonce, ourVm.nonce) 836 PutUint64BE(nonce[txs.HashLength:], ourVm.sequence+1) 837 addr := crypto.NewContractAddress(callee, nonce) 838 839 var gas uint64 = 100000 840 caller := newAccount(cache, "1, 2, 3") 841 output, err := ourVm.Call(cache, NewNoopEventSink(), caller, callee, cache.GetCode(callee), []byte{}, 0, &gas) 842 assert.NoError(t, err, "Should return new address without error") 843 assert.Equal(t, addr.Bytes(), output, "Addresses should be equal") 844 } 845 846 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md 847 func TestCreate2(t *testing.T) { 848 st := newAppState() 849 cache := NewState(st, blockHashGetter) 850 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 851 852 // salt of 0s 853 var salt [32]byte 854 callee := makeAccountWithCode(cache, "callee", MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x0, PUSH32, salt[:], CREATE2, PUSH1, 0, MSTORE, PUSH1, 20, PUSH1, 12, RETURN)) 855 addr := crypto.NewContractAddress2(callee, salt, cache.GetCode(callee)) 856 857 var gas uint64 = 100000 858 caller := newAccount(cache, "1, 2, 3") 859 output, err := ourVm.Call(cache, NewNoopEventSink(), caller, callee, cache.GetCode(callee), []byte{}, 0, &gas) 860 assert.NoError(t, err, "Should return new address without error") 861 assert.Equal(t, addr.Bytes(), output, "Returned value not equal to create2 address") 862 } 863 864 // This test was introduced to cover an issues exposed in our handling of the 865 // gas limit passed from caller to callee on various forms of CALL. 866 // The idea of this test is to implement a simple DelegateCall in EVM code 867 // We first run the DELEGATECALL with _just_ enough gas expecting a simple return, 868 // and then run it with 1 gas unit less, expecting a failure 869 func TestDelegateCallGas(t *testing.T) { 870 cache := NewState(newAppState(), blockHashGetter) 871 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 872 873 inOff := 0 874 inSize := 0 // no call data 875 retOff := 0 876 retSize := 32 877 calleeReturnValue := int64(20) 878 879 callee := makeAccountWithCode(cache, "callee", 880 MustSplice(PUSH1, calleeReturnValue, PUSH1, 0, MSTORE, PUSH1, 32, PUSH1, 0, RETURN)) 881 882 // 6 op codes total 883 baseOpsCost := GasBaseOp * 6 884 // 4 pushes 885 pushCost := GasStackOp * 4 886 // 2 pushes 2 pops 887 returnCost := GasStackOp * 4 888 // To push success/failure 889 resumeCost := GasStackOp 890 891 // Gas is not allowed to drop to 0 so we add resumecost 892 delegateCallCost := baseOpsCost + pushCost + returnCost + resumeCost 893 894 // Here we split up the caller code so we can make a DELEGATE call with 895 // different amounts of gas. The value we sandwich in the middle is the amount 896 // we subtract from the available gas (that the caller has available), so: 897 // code := MustSplice(callerCodePrefix, <amount to subtract from GAS> , callerCodeSuffix) 898 // gives us the code to make the call 899 callerCodePrefix := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, 900 PUSH1, inOff, PUSH20, callee, PUSH1) 901 callerCodeSuffix := MustSplice(DELEGATECALL, returnWord()) 902 903 // Perform a delegate call 904 caller := makeAccountWithCode(cache, "caller", MustSplice(callerCodePrefix, 905 // Give just enough gas to make the DELEGATECALL 906 delegateCallCost, callerCodeSuffix)) 907 908 // Should pass 909 txe := runVM(cache, ourVm, caller, callee, cache.GetCode(caller), 100) 910 assert.Nil(t, txe.Exception, "Should have sufficient funds for call") 911 assert.Equal(t, Int64ToWord256(calleeReturnValue).Bytes(), txe.Result.Return) 912 913 caller2 := makeAccountWithCode(cache, "caller2", MustSplice(callerCodePrefix, 914 // Shouldn't be enough gas to make call 915 delegateCallCost-1, callerCodeSuffix)) 916 917 // Should fail 918 txe = runVM(cache, ourVm, caller2, callee, cache.GetCode(caller2), 100) 919 assert.NotNil(t, txe.Exception, "Should have insufficient gas for call") 920 } 921 922 func TestMemoryBounds(t *testing.T) { 923 cache := NewState(newAppState(), blockHashGetter) 924 memoryProvider := func(err errors.Sink) Memory { 925 return NewDynamicMemory(1024, 2048, err) 926 } 927 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger, MemoryProvider(memoryProvider)) 928 caller := makeAccountWithCode(cache, "caller", nil) 929 callee := makeAccountWithCode(cache, "callee", nil) 930 gas := uint64(100000) 931 // This attempts to store a value at the memory boundary and return it 932 word := One256 933 output, err := ourVm.Call(cache, NewNoopEventSink(), caller, callee, 934 MustSplice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()), 935 nil, 0, &gas) 936 assert.NoError(t, err) 937 assert.Equal(t, word.Bytes(), output) 938 939 // Same with number 940 word = Int64ToWord256(232234234432) 941 output, err = ourVm.Call(cache, NewNoopEventSink(), caller, callee, 942 MustSplice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()), 943 nil, 0, &gas) 944 assert.NoError(t, err) 945 assert.Equal(t, word.Bytes(), output) 946 947 // Now test a series of boundary stores 948 code := pushWord(word) 949 for i := 0; i < 10; i++ { 950 code = MustSplice(code, storeAtEnd(), MLOAD) 951 } 952 output, err = ourVm.Call(cache, NewNoopEventSink(), caller, callee, MustSplice(code, storeAtEnd(), returnAfterStore()), 953 nil, 0, &gas) 954 assert.NoError(t, err) 955 assert.Equal(t, word.Bytes(), output) 956 957 // Same as above but we should breach the upper memory limit set in memoryProvider 958 code = pushWord(word) 959 for i := 0; i < 100; i++ { 960 code = MustSplice(code, storeAtEnd(), MLOAD) 961 } 962 require.NoError(t, cache.Error()) 963 output, err = ourVm.Call(cache, NewNoopEventSink(), caller, callee, MustSplice(code, storeAtEnd(), returnAfterStore()), 964 nil, 0, &gas) 965 assert.Error(t, err, "Should hit memory out of bounds") 966 } 967 968 func TestMsgSender(t *testing.T) { 969 st := newAppState() 970 cache := NewState(st, blockHashGetter) 971 account1 := newAccount(cache, "1, 2, 3") 972 account2 := newAccount(cache, "3, 2, 1") 973 974 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 975 976 var gas uint64 = 100000 977 978 /* 979 pragma solidity ^0.5.4; 980 981 contract SimpleStorage { 982 function get() public constant returns (address) { 983 return msg.sender; 984 } 985 } 986 */ 987 988 // This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler 989 code := hex.MustDecodeString("6060604052341561000f57600080fd5b60ca8061001d6000396000f30060606040526004361060" + 990 "3f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14604457" + 991 "5b600080fd5b3415604e57600080fd5b60546096565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ff" + 992 "ffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000339050905600a165627a" + 993 "7a72305820b9ebf49535372094ae88f56d9ad18f2a79c146c8f56e7ef33b9402924045071e0029") 994 995 // Run the contract initialisation code to obtain the contract code that would be mounted at account2 996 contractCode, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, code, code, 0, &gas) 997 require.NoError(t, err) 998 999 // Not needed for this test (since contract code is passed as argument to vm), but this is what an execution 1000 // framework must do 1001 cache.InitCode(account2, contractCode) 1002 1003 // Input is the function hash of `get()` 1004 input := hex.MustDecodeString("6d4ce63c") 1005 1006 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, contractCode, input, 0, &gas) 1007 require.NoError(t, err) 1008 1009 assert.Equal(t, account1.Word256().Bytes(), output) 1010 1011 require.NoError(t, cache.Error()) 1012 } 1013 1014 func TestInvalid(t *testing.T) { 1015 cache := NewState(newAppState(), blockHashGetter) 1016 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 1017 1018 // Create accounts 1019 account1 := newAccount(cache, "1") 1020 account2 := newAccount(cache, "1, 0, 1") 1021 1022 var gas uint64 = 100000 1023 1024 bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 1025 0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1026 0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, INVALID) 1027 1028 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1029 assert.Equal(t, errors.ErrorCodeExecutionAborted, err.ErrorCode()) 1030 t.Logf("Output: %v Error: %v\n", output, err) 1031 } 1032 1033 func TestReturnDataSize(t *testing.T) { 1034 cache := NewState(newAppState(), blockHashGetter) 1035 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 1036 1037 accountName := "account2addresstests" 1038 1039 ret := "My return message" 1040 callcode := MustSplice(PUSH32, RightPadWord256([]byte(ret)), PUSH1, 0x00, MSTORE, PUSH1, len(ret), PUSH1, 0x00, RETURN) 1041 1042 // Create accounts 1043 account1 := newAccount(cache, "1") 1044 account2 := makeAccountWithCode(cache, accountName, callcode) 1045 1046 var gas uint64 = 100000 1047 1048 gas1, gas2 := byte(0x1), byte(0x1) 1049 value := byte(0x69) 1050 inOff, inSize := byte(0x0), byte(0x0) // no call data 1051 retOff, retSize := byte(0x0), byte(len(ret)) 1052 1053 bytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff, PUSH1, value, 1054 PUSH20, account2, PUSH2, gas1, gas2, CALL, 1055 RETURNDATASIZE, PUSH1, 0x00, MSTORE, PUSH1, 0x20, PUSH1, 0x00, RETURN) 1056 1057 expected := Uint64ToWord256(uint64(len(ret))).Bytes() 1058 1059 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1060 require.NoError(t, err) 1061 assert.Equal(t, expected, output) 1062 1063 t.Logf("Output: %v Error: %v\n", output, err) 1064 1065 if err != nil { 1066 t.Fatal(err) 1067 } 1068 require.NoError(t, cache.Error()) 1069 } 1070 1071 func TestReturnDataCopy(t *testing.T) { 1072 cache := NewState(newAppState(), blockHashGetter) 1073 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 1074 1075 accountName := "account2addresstests" 1076 1077 ret := "My return message" 1078 callcode := MustSplice(PUSH32, RightPadWord256([]byte(ret)), PUSH1, 0x00, MSTORE, PUSH1, len(ret), PUSH1, 0x00, RETURN) 1079 1080 // Create accounts 1081 account1 := newAccount(cache, "1") 1082 account2 := makeAccountWithCode(cache, accountName, callcode) 1083 1084 var gas uint64 = 100000 1085 1086 gas1, gas2 := byte(0x1), byte(0x1) 1087 value := byte(0x69) 1088 inOff, inSize := byte(0x0), byte(0x0) // no call data 1089 retOff, retSize := byte(0x0), byte(len(ret)) 1090 1091 bytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff, PUSH1, value, 1092 PUSH20, account2, PUSH2, gas1, gas2, CALL, RETURNDATASIZE, PUSH1, 0x00, PUSH1, 0x00, RETURNDATACOPY, 1093 RETURNDATASIZE, PUSH1, 0x00, RETURN) 1094 1095 expected := []byte(ret) 1096 1097 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1098 require.NoError(t, err) 1099 assert.Equal(t, expected, output) 1100 1101 t.Logf("Output: %v Error: %v\n", output, err) 1102 1103 require.NoError(t, cache.Error()) 1104 } 1105 1106 func TestCallNonExistent(t *testing.T) { 1107 cache := NewState(newAppState(), blockHashGetter) 1108 account1 := newAccount(cache, "1") 1109 cache.AddToBalance(account1, 10000) 1110 unknownAddress := newAddress("nonexistent") 1111 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 1112 var gas uint64 1113 amt := uint64(100) 1114 _, err := ourVm.Call(cache, NewNoopEventSink(), account1, unknownAddress, nil, nil, amt, &gas) 1115 assertErrorCode(t, errors.ErrorCodeIllegalWrite, err, 1116 "Should not be able to call account before creating it (even before initialising)") 1117 assert.Equal(t, uint64(0), cache.GetBalance(unknownAddress)) 1118 } 1119 1120 func (ts testState) GetBlockHash(blockNumber uint64) (binary.Word256, error) { 1121 return ts.BlockHashProvider(blockNumber) 1122 } 1123 1124 func TestGetBlockHash(t *testing.T) { 1125 cache := NewTestState(newAppState(), blockHashGetter) 1126 params := newParams() 1127 1128 // Create accounts 1129 account1 := newAccount(cache, "1") 1130 account2 := newAccount(cache, "101") 1131 1132 var gas uint64 = 100000 1133 1134 // Non existing block 1135 params.BlockHeight = 1 1136 ourVm := NewVM(params, crypto.ZeroAddress, nil, logger) 1137 bytecode := MustSplice(PUSH1, 2, BLOCKHASH) 1138 _, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1139 assertErrorCode(t, errors.ErrorCodeInvalidBlockNumber, err, "attempt to get block hash of a non-existent block") 1140 1141 // Excessive old block 1142 cache.error = nil 1143 params.BlockHeight = 258 1144 ourVm = NewVM(params, crypto.ZeroAddress, nil, logger) 1145 bytecode = MustSplice(PUSH1, 1, BLOCKHASH) 1146 1147 _, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1148 assertErrorCode(t, errors.ErrorCodeBlockNumberOutOfRange, err, "attempt to get block hash of a block outside of allowed range") 1149 1150 // Get block hash 1151 cache.error = nil 1152 params.BlockHeight = 257 1153 cache.BlockHashProvider = func(blockNumber uint64) (Word256, error) { 1154 // Should be just within range 257 - 2 = 255 (and the first and last block count in that range so add one = 256) 1155 assert.Equal(t, uint64(2), blockNumber) 1156 return One256, nil 1157 } 1158 ourVm = NewVM(params, crypto.ZeroAddress, nil, logger) 1159 bytecode = MustSplice(PUSH1, 2, BLOCKHASH, return1()) 1160 1161 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1162 assert.NoError(t, err) 1163 assert.Equal(t, One256, LeftPadWord256(output)) 1164 1165 // Get block hash fail 1166 cache.error = nil 1167 params.BlockHeight = 3 1168 cache.BlockHashProvider = func(blockNumber uint64) (Word256, error) { 1169 assert.Equal(t, uint64(1), blockNumber) 1170 return Zero256, fmt.Errorf("unknown block %v", blockNumber) 1171 } 1172 ourVm = NewVM(params, crypto.ZeroAddress, nil, logger) 1173 bytecode = MustSplice(PUSH1, 1, BLOCKHASH, return1()) 1174 1175 _, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1176 assertErrorCode(t, errors.ErrorCodeInvalidBlockNumber, err, "attempt to get block hash failed") 1177 } 1178 1179 // These code segment helpers exercise the MSTORE MLOAD MSTORE cycle to test 1180 // both of the memory operations. Each MSTORE is done on the memory boundary 1181 // (at MSIZE) which Solidity uses to find guaranteed unallocated memory. 1182 1183 // storeAtEnd expects the value to be stored to be on top of the stack, it then 1184 // stores that value at the current memory boundary 1185 func storeAtEnd() []byte { 1186 // Pull in MSIZE (to carry forward to MLOAD), swap in value to store, store it at MSIZE 1187 return MustSplice(MSIZE, SWAP1, DUP2, MSTORE) 1188 } 1189 1190 func returnAfterStore() []byte { 1191 return MustSplice(PUSH1, 32, DUP2, RETURN) 1192 } 1193 1194 // Store the top element of the stack (which is a 32-byte word) in memory 1195 // and return it. Useful for a simple return value. 1196 func return1() []byte { 1197 return MustSplice(PUSH1, 0, MSTORE, returnWord()) 1198 } 1199 1200 func returnWord() []byte { 1201 // PUSH1 => return size, PUSH1 => return offset, RETURN 1202 return MustSplice(PUSH1, 32, PUSH1, 0, RETURN) 1203 } 1204 1205 // Subscribes to an AccCall, runs the vm, returns the output any direct exception 1206 // and then waits for any exceptions transmitted by Data in the AccCall 1207 // event (in the case of no direct error from call we will block waiting for 1208 // at least 1 AccCall event) 1209 func runVM(vmCache Interface, ourVm *VM, caller, callee crypto.Address, contractCode []byte, 1210 gas uint64) *exec.TxExecution { 1211 gasBefore := gas 1212 txe := new(exec.TxExecution) 1213 output, err := ourVm.Call(vmCache, txe, caller, callee, contractCode, []byte{}, 0, &gas) 1214 txe.PushError(err) 1215 for _, ev := range txe.ExceptionalCalls() { 1216 txe.PushError(ev.Header.Exception) 1217 } 1218 txe.Return(output, gasBefore-gas) 1219 return txe 1220 } 1221 1222 // this is code to call another contract (hardcoded as addr) 1223 func callContractCode(addr crypto.Address) []byte { 1224 gas1, gas2 := byte(0x1), byte(0x1) 1225 value := byte(0x69) 1226 inOff, inSize := byte(0x0), byte(0x0) // no call data 1227 retOff, retSize := byte(0x0), byte(0x20) 1228 // this is the code we want to run (send funds to an account and return) 1229 return MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 1230 inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize, 1231 PUSH1, retOff, RETURN) 1232 } 1233 1234 // Produce bytecode for a PUSH<N>, b_1, ..., b_N where the N is number of bytes 1235 // contained in the unpadded word 1236 func pushWord(word Word256) []byte { 1237 leadingZeros := byte(0) 1238 for leadingZeros < 32 { 1239 if word[leadingZeros] == 0 { 1240 leadingZeros++ 1241 } else { 1242 return MustSplice(byte(PUSH32)-leadingZeros, word[leadingZeros:]) 1243 } 1244 } 1245 return MustSplice(PUSH1, 0) 1246 } 1247 1248 func TestPushWord(t *testing.T) { 1249 word := Int64ToWord256(int64(2133213213)) 1250 assert.Equal(t, MustSplice(PUSH4, 0x7F, 0x26, 0x40, 0x1D), pushWord(word)) 1251 word[0] = 1 1252 assert.Equal(t, MustSplice(PUSH32, 1253 1, 0, 0, 0, 0, 0, 0, 0, 1254 0, 0, 0, 0, 0, 0, 0, 0, 1255 0, 0, 0, 0, 0, 0, 0, 0, 1256 0, 0, 0, 0, 0x7F, 0x26, 0x40, 0x1D), pushWord(word)) 1257 assert.Equal(t, MustSplice(PUSH1, 0), pushWord(Word256{})) 1258 assert.Equal(t, MustSplice(PUSH1, 1), pushWord(Int64ToWord256(1))) 1259 } 1260 1261 // Kind of indirect test of Splice, but here to avoid import cycles 1262 func TestBytecode(t *testing.T) { 1263 assert.Equal(t, 1264 MustSplice(1, 2, 3, 4, 5, 6), 1265 MustSplice(1, 2, 3, MustSplice(4, 5, 6))) 1266 assert.Equal(t, 1267 MustSplice(1, 2, 3, 4, 5, 6, 7, 8), 1268 MustSplice(1, 2, 3, MustSplice(4, MustSplice(5), 6), 7, 8)) 1269 assert.Equal(t, 1270 MustSplice(PUSH1, 2), 1271 MustSplice(byte(PUSH1), 0x02)) 1272 assert.Equal(t, 1273 []byte{}, 1274 MustSplice(MustSplice(MustSplice()))) 1275 1276 contractAccount := &acm.Account{Address: crypto.AddressFromWord256(Int64ToWord256(102))} 1277 addr := contractAccount.Address 1278 gas1, gas2 := byte(0x1), byte(0x1) 1279 value := byte(0x69) 1280 inOff, inSize := byte(0x0), byte(0x0) // no call data 1281 retOff, retSize := byte(0x0), byte(0x20) 1282 contractCodeBytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, 1283 inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize, 1284 PUSH1, retOff, RETURN) 1285 contractCode := []byte{0x60, retSize, 0x60, retOff, 0x60, inSize, 0x60, inOff, 0x60, value, 0x73} 1286 contractCode = append(contractCode, addr[:]...) 1287 contractCode = append(contractCode, []byte{0x61, gas1, gas2, 0xf1, 0x60, 0x20, 0x60, 0x0, 0xf3}...) 1288 assert.Equal(t, contractCode, contractCodeBytecode) 1289 } 1290 1291 func TestConcat(t *testing.T) { 1292 assert.Equal(t, 1293 []byte{0x01, 0x02, 0x03, 0x04}, 1294 Concat([]byte{0x01, 0x02}, []byte{0x03, 0x04})) 1295 } 1296 1297 func TestSubslice(t *testing.T) { 1298 const size = 10 1299 data := make([]byte, size) 1300 for i := 0; i < size; i++ { 1301 data[i] = byte(i) 1302 } 1303 err := errors.FirstOnly() 1304 for n := int64(0); n < size; n++ { 1305 data = data[:n] 1306 for offset := int64(-size); offset < size; offset++ { 1307 for length := int64(-size); length < size; length++ { 1308 err.Reset() 1309 subslice(data, offset, length, err) 1310 if offset < 0 || length < 0 || n < offset { 1311 assert.NotNil(t, err.Error()) 1312 } else { 1313 assert.Nil(t, err.Error()) 1314 } 1315 } 1316 } 1317 } 1318 1319 err.Reset() 1320 assert.Equal(t, []byte{ 1321 5, 6, 7, 8, 0, 0, 0, 0, 1322 0, 0, 0, 0, 0, 0, 0, 0, 1323 0, 0, 0, 0, 0, 0, 0, 0, 1324 0, 0, 0, 0, 0, 0, 0, 0, 1325 }, subslice([]byte{1, 2, 3, 4, 5, 6, 7, 8}, 4, 32, err)) 1326 } 1327 1328 func TestHasPermission(t *testing.T) { 1329 st := newAppState() 1330 acc := &acm.Account{ 1331 Address: newAddress("frog"), 1332 Permissions: permission.AccountPermissions{ 1333 Base: BasePermissionsFromStrings(t, 1334 "00100000001000111", 1335 "11011100010111000"), 1336 }, 1337 } 1338 require.NoError(t, st.UpdateAccount(acc)) 1339 // Ensure we are falling through to global permissions on those bits not set 1340 cache := NewState(st, blockHashGetter) 1341 assert.True(t, HasPermission(cache, acc.Address, PermFlagFromString(t, "100000001000110"))) 1342 require.NoError(t, cache.Error()) 1343 } 1344 1345 func TestDataStackOverflow(t *testing.T) { 1346 st := newAppState() 1347 cache := NewState(st, blockHashGetter) 1348 account1 := newAccount(cache, "1, 2, 3") 1349 account2 := newAccount(cache, "3, 2, 1") 1350 1351 params := newParams() 1352 params.DataStackMaxDepth = 4 1353 ourVm := NewVM(params, crypto.ZeroAddress, nil, logger) 1354 1355 var gas uint64 = 100000 1356 1357 /* 1358 pragma solidity ^0.5.4; 1359 1360 contract SimpleStorage { 1361 function get() public constant returns (address) { 1362 return get(); 1363 } 1364 } 1365 */ 1366 1367 // This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler 1368 code, err := hex.DecodeString("608060405234801561001057600080fd5b5060d18061001f6000396000f300608060405260043610" + 1369 "603f576000357c0100000000000000000000000000000000000000000000000000000000900463ff" + 1370 "ffffff1680636d4ce63c146044575b600080fd5b348015604f57600080fd5b5060566098565b6040" + 1371 "51808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffff" + 1372 "ffffffffffff16815260200191505060405180910390f35b600060a06098565b9050905600a16562" + 1373 "7a7a72305820daacfba0c21afacb5b67f26bc8021de63eaa560db82f98357d4e513f3249cf350029") 1374 require.NoError(t, err) 1375 1376 // Run the contract initialisation code to obtain the contract code that would be mounted at account2 1377 eventSink := NewNoopEventSink() 1378 contractCode, err := ourVm.Call(cache, eventSink, account1, account2, code, code, 0, &gas) 1379 require.NoError(t, err) 1380 1381 // Input is the function hash of `get()` 1382 input, err := hex.DecodeString("6d4ce63c") 1383 1384 _, err = ourVm.Call(cache, eventSink, account1, account2, contractCode, input, 0, &gas) 1385 assertErrorCode(t, errors.ErrorCodeDataStackOverflow, err, "Should be stack overflow") 1386 } 1387 1388 func TestCallStackOverflow(t *testing.T) { 1389 st := newAppState() 1390 cache := NewState(st, blockHashGetter) 1391 account1 := newAccount(cache, "1, 2, 3") 1392 account2 := newAccount(cache, "3, 2, 1") 1393 1394 params := newParams() 1395 1396 // Sender accepts lot of gaz but we run on a caped call stack node 1397 var gas uint64 = 100000 1398 params.CallStackMaxDepth = 2 1399 1400 ourVm := NewVM(params, crypto.ZeroAddress, nil, logger) 1401 1402 /* 1403 pragma solidity ^0.5.4; 1404 1405 contract A { 1406 function callMeBack() public { 1407 return require(msg.sender.call(bytes4(keccak256("callMeBack()")),this)); 1408 } 1409 } 1410 */ 1411 1412 // This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler 1413 code, err := hex.DecodeString("608060405234801561001057600080fd5b5061017a806100206000396000f3006080604052600436" + 1414 "10610041576000357c01000000000000000000000000000000000000000000000000000000009004" + 1415 "63ffffffff168063692c3b7c14610046575b600080fd5b34801561005257600080fd5b5061005b61" + 1416 "005d565b005b3373ffffffffffffffffffffffffffffffffffffffff1660405180807f63616c6c4d" + 1417 "654261636b28290000000000000000000000000000000000000000815250600c0190506040518091" + 1418 "0390207c010000000000000000000000000000000000000000000000000000000090043060405182" + 1419 "63ffffffff167c010000000000000000000000000000000000000000000000000000000002815260" + 1420 "0401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffff" + 1421 "ffffffffffffff1681526020019150506000604051808303816000875af192505050151561014c57" + 1422 "600080fd5b5600a165627a7a723058209315a40abb8b23b7c2a340e938b01367b419a23818475a2e" + 1423 "ee80d09da3f7ba780029") 1424 require.NoError(t, err) 1425 1426 // Run the contract initialisation code to obtain the contract code that would be mounted at account2 1427 contractCode, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, code, code, 0, &gas) 1428 require.NoError(t, err) 1429 1430 cache.InitCode(account1, contractCode) 1431 cache.InitCode(account2, contractCode) 1432 1433 // keccak256 hash of 'callMeBack()' 1434 input, err := hex.DecodeString("692c3b7c") 1435 require.NoError(t, err) 1436 1437 txe := new(exec.TxExecution) 1438 _, err = ourVm.Call(cache, txe, account1, account2, contractCode, input, 0, &gas) 1439 txe.PushError(err) 1440 require.Error(t, err) 1441 callError := txe.CallError() 1442 require.Error(t, callError) 1443 assertErrorCode(t, errors.ErrorCodeExecutionReverted, callError) 1444 // Errors are post-order so first is deepest 1445 deepestErr := callError.NestedErrors[0] 1446 assertErrorCode(t, errors.ErrorCodeCallStackOverflow, deepestErr) 1447 assert.Equal(t, params.CallStackMaxDepth, deepestErr.StackDepth) 1448 assert.Equal(t, account2, deepestErr.Callee) 1449 assert.Equal(t, account1, deepestErr.Caller) 1450 } 1451 1452 func TestExtCodeHash(t *testing.T) { 1453 cache := NewState(newAppState(), blockHashGetter) 1454 ourVm := NewVM(newParams(), crypto.ZeroAddress, nil, logger) 1455 account1 := newAccount(cache, "1") 1456 account2 := newAccount(cache, "101") 1457 1458 var gas uint64 = 100000 1459 1460 // 1. The EXTCODEHASH of the account without code is c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 1461 // what is the keccack256 hash of empty data. 1462 bytecode := MustSplice(PUSH20, account1, EXTCODEHASH, return1()) 1463 output, err := ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1464 assert.NoError(t, err) 1465 assert.Equal(t, hex.MustDecodeString("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), output) 1466 1467 // 2. The EXTCODEHASH of non-existent account is 0. 1468 bytecode = MustSplice(PUSH1, 0x03, EXTCODEHASH, return1()) 1469 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1470 assert.NoError(t, err) 1471 assert.Equal(t, LeftPadBytes([]uint8([]byte{0x00}), 32), output) 1472 1473 // 3. EXTCODEHASH is the hash of an account code 1474 acc := makeAccountWithCode(cache, "trustedCode", MustSplice(BLOCKHASH, return1())) 1475 bytecode = MustSplice(PUSH20, acc, EXTCODEHASH, return1()) 1476 output, err = ourVm.Call(cache, NewNoopEventSink(), account1, account2, bytecode, []byte{}, 0, &gas) 1477 assert.NoError(t, err) 1478 assert.Equal(t, hex.MustDecodeString("010da270094b5199d3e54f89afe4c66cdd658dd8111a41998714227e14e171bd"), output) 1479 } 1480 1481 func BasePermissionsFromStrings(t *testing.T, perms, setBit string) permission.BasePermissions { 1482 return permission.BasePermissions{ 1483 Perms: PermFlagFromString(t, perms), 1484 SetBit: PermFlagFromString(t, setBit), 1485 } 1486 } 1487 1488 func PermFlagFromString(t *testing.T, binaryString string) permission.PermFlag { 1489 permFlag, err := strconv.ParseUint(binaryString, 2, 64) 1490 require.NoError(t, err) 1491 return permission.PermFlag(permFlag) 1492 } 1493 1494 func assertErrorCode(t *testing.T, expectedCode errors.Code, err error, msgAndArgs ...interface{}) { 1495 if assert.Error(t, err, msgAndArgs...) { 1496 actualCode := errors.AsException(err).Code 1497 if !assert.Equal(t, expectedCode, actualCode, "expected error code %v", expectedCode) { 1498 t.Logf("Expected '%v' but got '%v'", expectedCode, actualCode) 1499 } 1500 } 1501 }