github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/accounts/abi/bind/backends/simulated_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package backends 18 19 import ( 20 "bytes" 21 "context" 22 "errors" 23 "math/big" 24 "reflect" 25 "strings" 26 "testing" 27 "time" 28 29 "github.com/zhiqiangxu/go-ethereum" 30 "github.com/zhiqiangxu/go-ethereum/accounts/abi" 31 "github.com/zhiqiangxu/go-ethereum/accounts/abi/bind" 32 "github.com/zhiqiangxu/go-ethereum/common" 33 "github.com/zhiqiangxu/go-ethereum/core" 34 "github.com/zhiqiangxu/go-ethereum/core/types" 35 "github.com/zhiqiangxu/go-ethereum/crypto" 36 "github.com/zhiqiangxu/go-ethereum/params" 37 ) 38 39 func TestSimulatedBackend(t *testing.T) { 40 var gasLimit uint64 = 8000029 41 key, _ := crypto.GenerateKey() // nolint: gosec 42 auth := bind.NewKeyedTransactor(key) 43 genAlloc := make(core.GenesisAlloc) 44 genAlloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(9223372036854775807)} 45 46 sim := NewSimulatedBackend(genAlloc, gasLimit) 47 defer sim.Close() 48 49 // should return an error if the tx is not found 50 txHash := common.HexToHash("2") 51 _, isPending, err := sim.TransactionByHash(context.Background(), txHash) 52 53 if isPending { 54 t.Fatal("transaction should not be pending") 55 } 56 if err != ethereum.NotFound { 57 t.Fatalf("err should be `ethereum.NotFound` but received %v", err) 58 } 59 60 // generate a transaction and confirm you can retrieve it 61 code := `6060604052600a8060106000396000f360606040526008565b00` 62 var gas uint64 = 3000000 63 tx := types.NewContractCreation(0, big.NewInt(0), gas, big.NewInt(1), common.FromHex(code)) 64 tx, _ = types.SignTx(tx, types.HomesteadSigner{}, key) 65 66 err = sim.SendTransaction(context.Background(), tx) 67 if err != nil { 68 t.Fatal("error sending transaction") 69 } 70 71 txHash = tx.Hash() 72 _, isPending, err = sim.TransactionByHash(context.Background(), txHash) 73 if err != nil { 74 t.Fatalf("error getting transaction with hash: %v", txHash.String()) 75 } 76 if !isPending { 77 t.Fatal("transaction should have pending status") 78 } 79 80 sim.Commit() 81 _, isPending, err = sim.TransactionByHash(context.Background(), txHash) 82 if err != nil { 83 t.Fatalf("error getting transaction with hash: %v", txHash.String()) 84 } 85 if isPending { 86 t.Fatal("transaction should not have pending status") 87 } 88 } 89 90 var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 91 92 // the following is based on this contract: 93 // contract T { 94 // event received(address sender, uint amount, bytes memo); 95 // event receivedAddr(address sender); 96 // 97 // function receive(bytes calldata memo) external payable returns (string memory res) { 98 // emit received(msg.sender, msg.value, memo); 99 // emit receivedAddr(msg.sender); 100 // return "hello world"; 101 // } 102 // } 103 const abiJSON = `[ { "constant": false, "inputs": [ { "name": "memo", "type": "bytes" } ], "name": "receive", "outputs": [ { "name": "res", "type": "string" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" }, { "indexed": false, "name": "amount", "type": "uint256" }, { "indexed": false, "name": "memo", "type": "bytes" } ], "name": "received", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" } ], "name": "receivedAddr", "type": "event" } ]` 104 const abiBin = `0x608060405234801561001057600080fd5b506102a0806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029` 105 const deployedCode = `60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029` 106 107 // expected return value contains "hello world" 108 var expectedReturn = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 109 110 func simTestBackend(testAddr common.Address) *SimulatedBackend { 111 return NewSimulatedBackend( 112 core.GenesisAlloc{ 113 testAddr: {Balance: big.NewInt(10000000000)}, 114 }, 10000000, 115 ) 116 } 117 118 func TestNewSimulatedBackend(t *testing.T) { 119 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 120 expectedBal := big.NewInt(10000000000) 121 sim := simTestBackend(testAddr) 122 defer sim.Close() 123 124 if sim.config != params.AllEthashProtocolChanges { 125 t.Errorf("expected sim config to equal params.AllEthashProtocolChanges, got %v", sim.config) 126 } 127 128 if sim.blockchain.Config() != params.AllEthashProtocolChanges { 129 t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config) 130 } 131 132 statedb, _ := sim.blockchain.State() 133 bal := statedb.GetBalance(testAddr) 134 if bal.Cmp(expectedBal) != 0 { 135 t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal) 136 } 137 } 138 139 func TestSimulatedBackend_AdjustTime(t *testing.T) { 140 sim := NewSimulatedBackend( 141 core.GenesisAlloc{}, 10000000, 142 ) 143 defer sim.Close() 144 145 prevTime := sim.pendingBlock.Time() 146 err := sim.AdjustTime(time.Second) 147 if err != nil { 148 t.Error(err) 149 } 150 newTime := sim.pendingBlock.Time() 151 152 if newTime-prevTime != uint64(time.Second.Seconds()) { 153 t.Errorf("adjusted time not equal to a second. prev: %v, new: %v", prevTime, newTime) 154 } 155 } 156 157 func TestSimulatedBackend_BalanceAt(t *testing.T) { 158 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 159 expectedBal := big.NewInt(10000000000) 160 sim := simTestBackend(testAddr) 161 defer sim.Close() 162 bgCtx := context.Background() 163 164 bal, err := sim.BalanceAt(bgCtx, testAddr, nil) 165 if err != nil { 166 t.Error(err) 167 } 168 169 if bal.Cmp(expectedBal) != 0 { 170 t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal) 171 } 172 } 173 174 func TestSimulatedBackend_BlockByHash(t *testing.T) { 175 sim := NewSimulatedBackend( 176 core.GenesisAlloc{}, 10000000, 177 ) 178 defer sim.Close() 179 bgCtx := context.Background() 180 181 block, err := sim.BlockByNumber(bgCtx, nil) 182 if err != nil { 183 t.Errorf("could not get recent block: %v", err) 184 } 185 blockByHash, err := sim.BlockByHash(bgCtx, block.Hash()) 186 if err != nil { 187 t.Errorf("could not get recent block: %v", err) 188 } 189 190 if block.Hash() != blockByHash.Hash() { 191 t.Errorf("did not get expected block") 192 } 193 } 194 195 func TestSimulatedBackend_BlockByNumber(t *testing.T) { 196 sim := NewSimulatedBackend( 197 core.GenesisAlloc{}, 10000000, 198 ) 199 defer sim.Close() 200 bgCtx := context.Background() 201 202 block, err := sim.BlockByNumber(bgCtx, nil) 203 if err != nil { 204 t.Errorf("could not get recent block: %v", err) 205 } 206 if block.NumberU64() != 0 { 207 t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64()) 208 } 209 210 // create one block 211 sim.Commit() 212 213 block, err = sim.BlockByNumber(bgCtx, nil) 214 if err != nil { 215 t.Errorf("could not get recent block: %v", err) 216 } 217 if block.NumberU64() != 1 { 218 t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64()) 219 } 220 221 blockByNumber, err := sim.BlockByNumber(bgCtx, big.NewInt(1)) 222 if err != nil { 223 t.Errorf("could not get block by number: %v", err) 224 } 225 if blockByNumber.Hash() != block.Hash() { 226 t.Errorf("did not get the same block with height of 1 as before") 227 } 228 } 229 230 func TestSimulatedBackend_NonceAt(t *testing.T) { 231 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 232 233 sim := simTestBackend(testAddr) 234 defer sim.Close() 235 bgCtx := context.Background() 236 237 nonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(0)) 238 if err != nil { 239 t.Errorf("could not get nonce for test addr: %v", err) 240 } 241 242 if nonce != uint64(0) { 243 t.Errorf("received incorrect nonce. expected 0, got %v", nonce) 244 } 245 246 // create a signed transaction to send 247 tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) 248 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 249 if err != nil { 250 t.Errorf("could not sign tx: %v", err) 251 } 252 253 // send tx to simulated backend 254 err = sim.SendTransaction(bgCtx, signedTx) 255 if err != nil { 256 t.Errorf("could not add tx to pending block: %v", err) 257 } 258 sim.Commit() 259 260 newNonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(1)) 261 if err != nil { 262 t.Errorf("could not get nonce for test addr: %v", err) 263 } 264 265 if newNonce != nonce+uint64(1) { 266 t.Errorf("received incorrect nonce. expected 1, got %v", nonce) 267 } 268 // create some more blocks 269 sim.Commit() 270 // Check that we can get data for an older block/state 271 newNonce, err = sim.NonceAt(bgCtx, testAddr, big.NewInt(1)) 272 if err != nil { 273 t.Fatalf("could not get nonce for test addr: %v", err) 274 } 275 if newNonce != nonce+uint64(1) { 276 t.Fatalf("received incorrect nonce. expected 1, got %v", nonce) 277 } 278 } 279 280 func TestSimulatedBackend_SendTransaction(t *testing.T) { 281 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 282 283 sim := simTestBackend(testAddr) 284 defer sim.Close() 285 bgCtx := context.Background() 286 287 // create a signed transaction to send 288 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) 289 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 290 if err != nil { 291 t.Errorf("could not sign tx: %v", err) 292 } 293 294 // send tx to simulated backend 295 err = sim.SendTransaction(bgCtx, signedTx) 296 if err != nil { 297 t.Errorf("could not add tx to pending block: %v", err) 298 } 299 sim.Commit() 300 301 block, err := sim.BlockByNumber(bgCtx, big.NewInt(1)) 302 if err != nil { 303 t.Errorf("could not get block at height 1: %v", err) 304 } 305 306 if signedTx.Hash() != block.Transactions()[0].Hash() { 307 t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash()) 308 } 309 } 310 311 func TestSimulatedBackend_TransactionByHash(t *testing.T) { 312 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 313 314 sim := NewSimulatedBackend( 315 core.GenesisAlloc{ 316 testAddr: {Balance: big.NewInt(10000000000)}, 317 }, 10000000, 318 ) 319 defer sim.Close() 320 bgCtx := context.Background() 321 322 // create a signed transaction to send 323 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) 324 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 325 if err != nil { 326 t.Errorf("could not sign tx: %v", err) 327 } 328 329 // send tx to simulated backend 330 err = sim.SendTransaction(bgCtx, signedTx) 331 if err != nil { 332 t.Errorf("could not add tx to pending block: %v", err) 333 } 334 335 // ensure tx is committed pending 336 receivedTx, pending, err := sim.TransactionByHash(bgCtx, signedTx.Hash()) 337 if err != nil { 338 t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err) 339 } 340 if !pending { 341 t.Errorf("expected transaction to be in pending state") 342 } 343 if receivedTx.Hash() != signedTx.Hash() { 344 t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash()) 345 } 346 347 sim.Commit() 348 349 // ensure tx is not and committed pending 350 receivedTx, pending, err = sim.TransactionByHash(bgCtx, signedTx.Hash()) 351 if err != nil { 352 t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err) 353 } 354 if pending { 355 t.Errorf("expected transaction to not be in pending state") 356 } 357 if receivedTx.Hash() != signedTx.Hash() { 358 t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash()) 359 } 360 } 361 362 func TestSimulatedBackend_EstimateGas(t *testing.T) { 363 /* 364 pragma solidity ^0.6.4; 365 contract GasEstimation { 366 function PureRevert() public { revert(); } 367 function Revert() public { revert("revert reason");} 368 function OOG() public { for (uint i = 0; ; i++) {}} 369 function Assert() public { assert(false);} 370 function Valid() public {} 371 }*/ 372 const contractAbi = "[{\"inputs\":[],\"name\":\"Assert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OOG\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PureRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Revert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Valid\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" 373 const contractBin = "0x60806040523480156100115760006000fd5b50610017565b61016e806100266000396000f3fe60806040523480156100115760006000fd5b506004361061005c5760003560e01c806350f6fe3414610062578063aa8b1d301461006c578063b9b046f914610076578063d8b9839114610080578063e09fface1461008a5761005c565b60006000fd5b61006a610094565b005b6100746100ad565b005b61007e6100b5565b005b6100886100c2565b005b610092610135565b005b6000600090505b5b808060010191505061009b565b505b565b60006000fd5b565b600015156100bf57fe5b5b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f72657665727420726561736f6e0000000000000000000000000000000000000081526020015060200191505060405180910390fd5b565b5b56fea2646970667358221220345bbcbb1a5ecf22b53a78eaebf95f8ee0eceff6d10d4b9643495084d2ec934a64736f6c63430006040033" 374 375 key, _ := crypto.GenerateKey() 376 addr := crypto.PubkeyToAddress(key.PublicKey) 377 opts := bind.NewKeyedTransactor(key) 378 379 sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether)}}, 10000000) 380 defer sim.Close() 381 382 parsed, _ := abi.JSON(strings.NewReader(contractAbi)) 383 contractAddr, _, _, _ := bind.DeployContract(opts, parsed, common.FromHex(contractBin), sim) 384 sim.Commit() 385 386 var cases = []struct { 387 name string 388 message ethereum.CallMsg 389 expect uint64 390 expectError error 391 expectData interface{} 392 }{ 393 {"plain transfer(valid)", ethereum.CallMsg{ 394 From: addr, 395 To: &addr, 396 Gas: 0, 397 GasPrice: big.NewInt(0), 398 Value: big.NewInt(1), 399 Data: nil, 400 }, params.TxGas, nil, nil}, 401 402 {"plain transfer(invalid)", ethereum.CallMsg{ 403 From: addr, 404 To: &contractAddr, 405 Gas: 0, 406 GasPrice: big.NewInt(0), 407 Value: big.NewInt(1), 408 Data: nil, 409 }, 0, errors.New("execution reverted"), nil}, 410 411 {"Revert", ethereum.CallMsg{ 412 From: addr, 413 To: &contractAddr, 414 Gas: 0, 415 GasPrice: big.NewInt(0), 416 Value: nil, 417 Data: common.Hex2Bytes("d8b98391"), 418 }, 0, errors.New("execution reverted: revert reason"), "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000"}, 419 420 {"PureRevert", ethereum.CallMsg{ 421 From: addr, 422 To: &contractAddr, 423 Gas: 0, 424 GasPrice: big.NewInt(0), 425 Value: nil, 426 Data: common.Hex2Bytes("aa8b1d30"), 427 }, 0, errors.New("execution reverted"), nil}, 428 429 {"OOG", ethereum.CallMsg{ 430 From: addr, 431 To: &contractAddr, 432 Gas: 100000, 433 GasPrice: big.NewInt(0), 434 Value: nil, 435 Data: common.Hex2Bytes("50f6fe34"), 436 }, 0, errors.New("gas required exceeds allowance (100000)"), nil}, 437 438 {"Assert", ethereum.CallMsg{ 439 From: addr, 440 To: &contractAddr, 441 Gas: 100000, 442 GasPrice: big.NewInt(0), 443 Value: nil, 444 Data: common.Hex2Bytes("b9b046f9"), 445 }, 0, errors.New("invalid opcode: opcode 0xfe not defined"), nil}, 446 447 {"Valid", ethereum.CallMsg{ 448 From: addr, 449 To: &contractAddr, 450 Gas: 100000, 451 GasPrice: big.NewInt(0), 452 Value: nil, 453 Data: common.Hex2Bytes("e09fface"), 454 }, 21275, nil, nil}, 455 } 456 for _, c := range cases { 457 got, err := sim.EstimateGas(context.Background(), c.message) 458 if c.expectError != nil { 459 if err == nil { 460 t.Fatalf("Expect error, got nil") 461 } 462 if c.expectError.Error() != err.Error() { 463 t.Fatalf("Expect error, want %v, got %v", c.expectError, err) 464 } 465 if c.expectData != nil { 466 if err, ok := err.(*revertError); !ok { 467 t.Fatalf("Expect revert error, got %T", err) 468 } else if !reflect.DeepEqual(err.ErrorData(), c.expectData) { 469 t.Fatalf("Error data mismatch, want %v, got %v", c.expectData, err.ErrorData()) 470 } 471 } 472 continue 473 } 474 if got != c.expect { 475 t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got) 476 } 477 } 478 } 479 480 func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) { 481 key, _ := crypto.GenerateKey() 482 addr := crypto.PubkeyToAddress(key.PublicKey) 483 484 sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether*2 + 2e17)}}, 10000000) 485 defer sim.Close() 486 487 receipant := common.HexToAddress("deadbeef") 488 var cases = []struct { 489 name string 490 message ethereum.CallMsg 491 expect uint64 492 expectError error 493 }{ 494 {"EstimateWithoutPrice", ethereum.CallMsg{ 495 From: addr, 496 To: &receipant, 497 Gas: 0, 498 GasPrice: big.NewInt(0), 499 Value: big.NewInt(1000), 500 Data: nil, 501 }, 21000, nil}, 502 503 {"EstimateWithPrice", ethereum.CallMsg{ 504 From: addr, 505 To: &receipant, 506 Gas: 0, 507 GasPrice: big.NewInt(1000), 508 Value: big.NewInt(1000), 509 Data: nil, 510 }, 21000, nil}, 511 512 {"EstimateWithVeryHighPrice", ethereum.CallMsg{ 513 From: addr, 514 To: &receipant, 515 Gas: 0, 516 GasPrice: big.NewInt(1e14), // gascost = 2.1ether 517 Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether 518 Data: nil, 519 }, 21000, nil}, 520 521 {"EstimateWithSuperhighPrice", ethereum.CallMsg{ 522 From: addr, 523 To: &receipant, 524 Gas: 0, 525 GasPrice: big.NewInt(2e14), // gascost = 4.2ether 526 Value: big.NewInt(1000), 527 Data: nil, 528 }, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14) 529 } 530 for _, c := range cases { 531 got, err := sim.EstimateGas(context.Background(), c.message) 532 if c.expectError != nil { 533 if err == nil { 534 t.Fatalf("Expect error, got nil") 535 } 536 if c.expectError.Error() != err.Error() { 537 t.Fatalf("Expect error, want %v, got %v", c.expectError, err) 538 } 539 continue 540 } 541 if got != c.expect { 542 t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got) 543 } 544 } 545 } 546 547 func TestSimulatedBackend_HeaderByHash(t *testing.T) { 548 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 549 550 sim := simTestBackend(testAddr) 551 defer sim.Close() 552 bgCtx := context.Background() 553 554 header, err := sim.HeaderByNumber(bgCtx, nil) 555 if err != nil { 556 t.Errorf("could not get recent block: %v", err) 557 } 558 headerByHash, err := sim.HeaderByHash(bgCtx, header.Hash()) 559 if err != nil { 560 t.Errorf("could not get recent block: %v", err) 561 } 562 563 if header.Hash() != headerByHash.Hash() { 564 t.Errorf("did not get expected block") 565 } 566 } 567 568 func TestSimulatedBackend_HeaderByNumber(t *testing.T) { 569 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 570 571 sim := simTestBackend(testAddr) 572 defer sim.Close() 573 bgCtx := context.Background() 574 575 latestBlockHeader, err := sim.HeaderByNumber(bgCtx, nil) 576 if err != nil { 577 t.Errorf("could not get header for tip of chain: %v", err) 578 } 579 if latestBlockHeader == nil { 580 t.Errorf("received a nil block header") 581 } 582 if latestBlockHeader.Number.Uint64() != uint64(0) { 583 t.Errorf("expected block header number 0, instead got %v", latestBlockHeader.Number.Uint64()) 584 } 585 586 sim.Commit() 587 588 latestBlockHeader, err = sim.HeaderByNumber(bgCtx, nil) 589 if err != nil { 590 t.Errorf("could not get header for blockheight of 1: %v", err) 591 } 592 593 blockHeader, err := sim.HeaderByNumber(bgCtx, big.NewInt(1)) 594 if err != nil { 595 t.Errorf("could not get header for blockheight of 1: %v", err) 596 } 597 598 if blockHeader.Hash() != latestBlockHeader.Hash() { 599 t.Errorf("block header and latest block header are not the same") 600 } 601 if blockHeader.Number.Int64() != int64(1) { 602 t.Errorf("did not get blockheader for block 1. instead got block %v", blockHeader.Number.Int64()) 603 } 604 605 block, err := sim.BlockByNumber(bgCtx, big.NewInt(1)) 606 if err != nil { 607 t.Errorf("could not get block for blockheight of 1: %v", err) 608 } 609 610 if block.Hash() != blockHeader.Hash() { 611 t.Errorf("block hash and block header hash do not match. expected %v, got %v", block.Hash(), blockHeader.Hash()) 612 } 613 } 614 615 func TestSimulatedBackend_TransactionCount(t *testing.T) { 616 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 617 618 sim := simTestBackend(testAddr) 619 defer sim.Close() 620 bgCtx := context.Background() 621 currentBlock, err := sim.BlockByNumber(bgCtx, nil) 622 if err != nil || currentBlock == nil { 623 t.Error("could not get current block") 624 } 625 626 count, err := sim.TransactionCount(bgCtx, currentBlock.Hash()) 627 if err != nil { 628 t.Error("could not get current block's transaction count") 629 } 630 631 if count != 0 { 632 t.Errorf("expected transaction count of %v does not match actual count of %v", 0, count) 633 } 634 635 // create a signed transaction to send 636 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) 637 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 638 if err != nil { 639 t.Errorf("could not sign tx: %v", err) 640 } 641 642 // send tx to simulated backend 643 err = sim.SendTransaction(bgCtx, signedTx) 644 if err != nil { 645 t.Errorf("could not add tx to pending block: %v", err) 646 } 647 648 sim.Commit() 649 650 lastBlock, err := sim.BlockByNumber(bgCtx, nil) 651 if err != nil { 652 t.Errorf("could not get header for tip of chain: %v", err) 653 } 654 655 count, err = sim.TransactionCount(bgCtx, lastBlock.Hash()) 656 if err != nil { 657 t.Error("could not get current block's transaction count") 658 } 659 660 if count != 1 { 661 t.Errorf("expected transaction count of %v does not match actual count of %v", 1, count) 662 } 663 } 664 665 func TestSimulatedBackend_TransactionInBlock(t *testing.T) { 666 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 667 668 sim := simTestBackend(testAddr) 669 defer sim.Close() 670 bgCtx := context.Background() 671 672 transaction, err := sim.TransactionInBlock(bgCtx, sim.pendingBlock.Hash(), uint(0)) 673 if err == nil && err != errTransactionDoesNotExist { 674 t.Errorf("expected a transaction does not exist error to be received but received %v", err) 675 } 676 if transaction != nil { 677 t.Errorf("expected transaction to be nil but received %v", transaction) 678 } 679 680 // expect pending nonce to be 0 since account has not been used 681 pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr) 682 if err != nil { 683 t.Errorf("did not get the pending nonce: %v", err) 684 } 685 686 if pendingNonce != uint64(0) { 687 t.Errorf("expected pending nonce of 0 got %v", pendingNonce) 688 } 689 690 // create a signed transaction to send 691 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) 692 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 693 if err != nil { 694 t.Errorf("could not sign tx: %v", err) 695 } 696 697 // send tx to simulated backend 698 err = sim.SendTransaction(bgCtx, signedTx) 699 if err != nil { 700 t.Errorf("could not add tx to pending block: %v", err) 701 } 702 703 sim.Commit() 704 705 lastBlock, err := sim.BlockByNumber(bgCtx, nil) 706 if err != nil { 707 t.Errorf("could not get header for tip of chain: %v", err) 708 } 709 710 transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(1)) 711 if err == nil && err != errTransactionDoesNotExist { 712 t.Errorf("expected a transaction does not exist error to be received but received %v", err) 713 } 714 if transaction != nil { 715 t.Errorf("expected transaction to be nil but received %v", transaction) 716 } 717 718 transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(0)) 719 if err != nil { 720 t.Errorf("could not get transaction in the lastest block with hash %v: %v", lastBlock.Hash().String(), err) 721 } 722 723 if signedTx.Hash().String() != transaction.Hash().String() { 724 t.Errorf("received transaction that did not match the sent transaction. expected hash %v, got hash %v", signedTx.Hash().String(), transaction.Hash().String()) 725 } 726 } 727 728 func TestSimulatedBackend_PendingNonceAt(t *testing.T) { 729 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 730 731 sim := simTestBackend(testAddr) 732 defer sim.Close() 733 bgCtx := context.Background() 734 735 // expect pending nonce to be 0 since account has not been used 736 pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr) 737 if err != nil { 738 t.Errorf("did not get the pending nonce: %v", err) 739 } 740 741 if pendingNonce != uint64(0) { 742 t.Errorf("expected pending nonce of 0 got %v", pendingNonce) 743 } 744 745 // create a signed transaction to send 746 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) 747 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 748 if err != nil { 749 t.Errorf("could not sign tx: %v", err) 750 } 751 752 // send tx to simulated backend 753 err = sim.SendTransaction(bgCtx, signedTx) 754 if err != nil { 755 t.Errorf("could not add tx to pending block: %v", err) 756 } 757 758 // expect pending nonce to be 1 since account has submitted one transaction 759 pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr) 760 if err != nil { 761 t.Errorf("did not get the pending nonce: %v", err) 762 } 763 764 if pendingNonce != uint64(1) { 765 t.Errorf("expected pending nonce of 1 got %v", pendingNonce) 766 } 767 768 // make a new transaction with a nonce of 1 769 tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) 770 signedTx, err = types.SignTx(tx, types.HomesteadSigner{}, testKey) 771 if err != nil { 772 t.Errorf("could not sign tx: %v", err) 773 } 774 err = sim.SendTransaction(bgCtx, signedTx) 775 if err != nil { 776 t.Errorf("could not send tx: %v", err) 777 } 778 779 // expect pending nonce to be 2 since account now has two transactions 780 pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr) 781 if err != nil { 782 t.Errorf("did not get the pending nonce: %v", err) 783 } 784 785 if pendingNonce != uint64(2) { 786 t.Errorf("expected pending nonce of 2 got %v", pendingNonce) 787 } 788 } 789 790 func TestSimulatedBackend_TransactionReceipt(t *testing.T) { 791 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 792 793 sim := simTestBackend(testAddr) 794 defer sim.Close() 795 bgCtx := context.Background() 796 797 // create a signed transaction to send 798 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) 799 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 800 if err != nil { 801 t.Errorf("could not sign tx: %v", err) 802 } 803 804 // send tx to simulated backend 805 err = sim.SendTransaction(bgCtx, signedTx) 806 if err != nil { 807 t.Errorf("could not add tx to pending block: %v", err) 808 } 809 sim.Commit() 810 811 receipt, err := sim.TransactionReceipt(bgCtx, signedTx.Hash()) 812 if err != nil { 813 t.Errorf("could not get transaction receipt: %v", err) 814 } 815 816 if receipt.ContractAddress != testAddr && receipt.TxHash != signedTx.Hash() { 817 t.Errorf("received receipt is not correct: %v", receipt) 818 } 819 } 820 821 func TestSimulatedBackend_SuggestGasPrice(t *testing.T) { 822 sim := NewSimulatedBackend( 823 core.GenesisAlloc{}, 824 10000000, 825 ) 826 defer sim.Close() 827 bgCtx := context.Background() 828 gasPrice, err := sim.SuggestGasPrice(bgCtx) 829 if err != nil { 830 t.Errorf("could not get gas price: %v", err) 831 } 832 if gasPrice.Uint64() != uint64(1) { 833 t.Errorf("gas price was not expected value of 1. actual: %v", gasPrice.Uint64()) 834 } 835 } 836 837 func TestSimulatedBackend_PendingCodeAt(t *testing.T) { 838 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 839 sim := simTestBackend(testAddr) 840 defer sim.Close() 841 bgCtx := context.Background() 842 code, err := sim.CodeAt(bgCtx, testAddr, nil) 843 if err != nil { 844 t.Errorf("could not get code at test addr: %v", err) 845 } 846 if len(code) != 0 { 847 t.Errorf("got code for account that does not have contract code") 848 } 849 850 parsed, err := abi.JSON(strings.NewReader(abiJSON)) 851 if err != nil { 852 t.Errorf("could not get code at test addr: %v", err) 853 } 854 auth := bind.NewKeyedTransactor(testKey) 855 contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim) 856 if err != nil { 857 t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract) 858 } 859 860 code, err = sim.PendingCodeAt(bgCtx, contractAddr) 861 if err != nil { 862 t.Errorf("could not get code at test addr: %v", err) 863 } 864 if len(code) == 0 { 865 t.Errorf("did not get code for account that has contract code") 866 } 867 // ensure code received equals code deployed 868 if !bytes.Equal(code, common.FromHex(deployedCode)) { 869 t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code) 870 } 871 } 872 873 func TestSimulatedBackend_CodeAt(t *testing.T) { 874 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 875 sim := simTestBackend(testAddr) 876 defer sim.Close() 877 bgCtx := context.Background() 878 code, err := sim.CodeAt(bgCtx, testAddr, nil) 879 if err != nil { 880 t.Errorf("could not get code at test addr: %v", err) 881 } 882 if len(code) != 0 { 883 t.Errorf("got code for account that does not have contract code") 884 } 885 886 parsed, err := abi.JSON(strings.NewReader(abiJSON)) 887 if err != nil { 888 t.Errorf("could not get code at test addr: %v", err) 889 } 890 auth := bind.NewKeyedTransactor(testKey) 891 contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim) 892 if err != nil { 893 t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract) 894 } 895 896 sim.Commit() 897 code, err = sim.CodeAt(bgCtx, contractAddr, nil) 898 if err != nil { 899 t.Errorf("could not get code at test addr: %v", err) 900 } 901 if len(code) == 0 { 902 t.Errorf("did not get code for account that has contract code") 903 } 904 // ensure code received equals code deployed 905 if !bytes.Equal(code, common.FromHex(deployedCode)) { 906 t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code) 907 } 908 } 909 910 // When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt: 911 // receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]} 912 func TestSimulatedBackend_PendingAndCallContract(t *testing.T) { 913 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 914 sim := simTestBackend(testAddr) 915 defer sim.Close() 916 bgCtx := context.Background() 917 918 parsed, err := abi.JSON(strings.NewReader(abiJSON)) 919 if err != nil { 920 t.Errorf("could not get code at test addr: %v", err) 921 } 922 contractAuth := bind.NewKeyedTransactor(testKey) 923 addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(abiBin), sim) 924 if err != nil { 925 t.Errorf("could not deploy contract: %v", err) 926 } 927 928 input, err := parsed.Pack("receive", []byte("X")) 929 if err != nil { 930 t.Errorf("could not pack receive function on contract: %v", err) 931 } 932 933 // make sure you can call the contract in pending state 934 res, err := sim.PendingCallContract(bgCtx, ethereum.CallMsg{ 935 From: testAddr, 936 To: &addr, 937 Data: input, 938 }) 939 if err != nil { 940 t.Errorf("could not call receive method on contract: %v", err) 941 } 942 if len(res) == 0 { 943 t.Errorf("result of contract call was empty: %v", res) 944 } 945 946 // while comparing against the byte array is more exact, also compare against the human readable string for readability 947 if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") { 948 t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res)) 949 } 950 951 sim.Commit() 952 953 // make sure you can call the contract 954 res, err = sim.CallContract(bgCtx, ethereum.CallMsg{ 955 From: testAddr, 956 To: &addr, 957 Data: input, 958 }, nil) 959 if err != nil { 960 t.Errorf("could not call receive method on contract: %v", err) 961 } 962 if len(res) == 0 { 963 t.Errorf("result of contract call was empty: %v", res) 964 } 965 966 if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") { 967 t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res)) 968 } 969 } 970 971 // This test is based on the following contract: 972 /* 973 contract Reverter { 974 function revertString() public pure{ 975 require(false, "some error"); 976 } 977 function revertNoString() public pure { 978 require(false, ""); 979 } 980 function revertASM() public pure { 981 assembly { 982 revert(0x0, 0x0) 983 } 984 } 985 function noRevert() public pure { 986 assembly { 987 // Assembles something that looks like require(false, "some error") but is not reverted 988 mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000) 989 mstore(0x4, 0x0000000000000000000000000000000000000000000000000000000000000020) 990 mstore(0x24, 0x000000000000000000000000000000000000000000000000000000000000000a) 991 mstore(0x44, 0x736f6d65206572726f7200000000000000000000000000000000000000000000) 992 return(0x0, 0x64) 993 } 994 } 995 }*/ 996 func TestSimulatedBackend_CallContractRevert(t *testing.T) { 997 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 998 sim := simTestBackend(testAddr) 999 defer sim.Close() 1000 bgCtx := context.Background() 1001 1002 reverterABI := `[{"inputs": [],"name": "noRevert","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertASM","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertNoString","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertString","outputs": [],"stateMutability": "pure","type": "function"}]` 1003 reverterBin := "608060405234801561001057600080fd5b506101d3806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634b409e01146100515780639b340e361461005b5780639bd6103714610065578063b7246fc11461006f575b600080fd5b610059610079565b005b6100636100ca565b005b61006d6100cf565b005b610077610145565b005b60006100c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526000815260200160200191505060405180910390fd5b565b600080fd5b6000610143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f736f6d65206572726f720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b7f08c379a0000000000000000000000000000000000000000000000000000000006000526020600452600a6024527f736f6d65206572726f720000000000000000000000000000000000000000000060445260646000f3fea2646970667358221220cdd8af0609ec4996b7360c7c780bad5c735740c64b1fffc3445aa12d37f07cb164736f6c63430006070033" 1004 1005 parsed, err := abi.JSON(strings.NewReader(reverterABI)) 1006 if err != nil { 1007 t.Errorf("could not get code at test addr: %v", err) 1008 } 1009 contractAuth := bind.NewKeyedTransactor(testKey) 1010 addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(reverterBin), sim) 1011 if err != nil { 1012 t.Errorf("could not deploy contract: %v", err) 1013 } 1014 1015 inputs := make(map[string]interface{}, 3) 1016 inputs["revertASM"] = nil 1017 inputs["revertNoString"] = "" 1018 inputs["revertString"] = "some error" 1019 1020 call := make([]func([]byte) ([]byte, error), 2) 1021 call[0] = func(input []byte) ([]byte, error) { 1022 return sim.PendingCallContract(bgCtx, ethereum.CallMsg{ 1023 From: testAddr, 1024 To: &addr, 1025 Data: input, 1026 }) 1027 } 1028 call[1] = func(input []byte) ([]byte, error) { 1029 return sim.CallContract(bgCtx, ethereum.CallMsg{ 1030 From: testAddr, 1031 To: &addr, 1032 Data: input, 1033 }, nil) 1034 } 1035 1036 // Run pending calls then commit 1037 for _, cl := range call { 1038 for key, val := range inputs { 1039 input, err := parsed.Pack(key) 1040 if err != nil { 1041 t.Errorf("could not pack %v function on contract: %v", key, err) 1042 } 1043 1044 res, err := cl(input) 1045 if err == nil { 1046 t.Errorf("call to %v was not reverted", key) 1047 } 1048 if res != nil { 1049 t.Errorf("result from %v was not nil: %v", key, res) 1050 } 1051 if val != nil { 1052 rerr, ok := err.(*revertError) 1053 if !ok { 1054 t.Errorf("expect revert error") 1055 } 1056 if rerr.Error() != "execution reverted: "+val.(string) { 1057 t.Errorf("error was malformed: got %v want %v", rerr.Error(), val) 1058 } 1059 } else { 1060 // revert(0x0,0x0) 1061 if err.Error() != "execution reverted" { 1062 t.Errorf("error was malformed: got %v want %v", err, "execution reverted") 1063 } 1064 } 1065 } 1066 input, err := parsed.Pack("noRevert") 1067 if err != nil { 1068 t.Errorf("could not pack noRevert function on contract: %v", err) 1069 } 1070 res, err := cl(input) 1071 if err != nil { 1072 t.Error("call to noRevert was reverted") 1073 } 1074 if res == nil { 1075 t.Errorf("result from noRevert was nil") 1076 } 1077 sim.Commit() 1078 } 1079 }