github.com/jimmyx0x/go-ethereum@v1.10.28/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 "math/rand" 25 "reflect" 26 "strings" 27 "testing" 28 "time" 29 30 "github.com/ethereum/go-ethereum" 31 "github.com/ethereum/go-ethereum/accounts/abi" 32 "github.com/ethereum/go-ethereum/accounts/abi/bind" 33 "github.com/ethereum/go-ethereum/common" 34 "github.com/ethereum/go-ethereum/core" 35 "github.com/ethereum/go-ethereum/core/types" 36 "github.com/ethereum/go-ethereum/crypto" 37 "github.com/ethereum/go-ethereum/params" 38 ) 39 40 func TestSimulatedBackend(t *testing.T) { 41 var gasLimit uint64 = 8000029 42 key, _ := crypto.GenerateKey() // nolint: gosec 43 auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) 44 genAlloc := make(core.GenesisAlloc) 45 genAlloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(9223372036854775807)} 46 47 sim := NewSimulatedBackend(genAlloc, gasLimit) 48 defer sim.Close() 49 50 // should return an error if the tx is not found 51 txHash := common.HexToHash("2") 52 _, isPending, err := sim.TransactionByHash(context.Background(), txHash) 53 54 if isPending { 55 t.Fatal("transaction should not be pending") 56 } 57 if err != ethereum.NotFound { 58 t.Fatalf("err should be `ethereum.NotFound` but received %v", err) 59 } 60 61 // generate a transaction and confirm you can retrieve it 62 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 63 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 64 65 code := `6060604052600a8060106000396000f360606040526008565b00` 66 var gas uint64 = 3000000 67 tx := types.NewContractCreation(0, big.NewInt(0), gas, gasPrice, common.FromHex(code)) 68 tx, _ = types.SignTx(tx, types.HomesteadSigner{}, key) 69 70 err = sim.SendTransaction(context.Background(), tx) 71 if err != nil { 72 t.Fatal("error sending transaction") 73 } 74 75 txHash = tx.Hash() 76 _, isPending, err = sim.TransactionByHash(context.Background(), txHash) 77 if err != nil { 78 t.Fatalf("error getting transaction with hash: %v", txHash.String()) 79 } 80 if !isPending { 81 t.Fatal("transaction should have pending status") 82 } 83 84 sim.Commit() 85 _, isPending, err = sim.TransactionByHash(context.Background(), txHash) 86 if err != nil { 87 t.Fatalf("error getting transaction with hash: %v", txHash.String()) 88 } 89 if isPending { 90 t.Fatal("transaction should not have pending status") 91 } 92 } 93 94 var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 95 96 // the following is based on this contract: 97 // 98 // contract T { 99 // event received(address sender, uint amount, bytes memo); 100 // event receivedAddr(address sender); 101 // 102 // function receive(bytes calldata memo) external payable returns (string memory res) { 103 // emit received(msg.sender, msg.value, memo); 104 // emit receivedAddr(msg.sender); 105 // return "hello world"; 106 // } 107 // } 108 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" } ]` 109 const abiBin = `0x608060405234801561001057600080fd5b506102a0806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029` 110 const deployedCode = `60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029` 111 112 // expected return value contains "hello world" 113 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} 114 115 func simTestBackend(testAddr common.Address) *SimulatedBackend { 116 return NewSimulatedBackend( 117 core.GenesisAlloc{ 118 testAddr: {Balance: big.NewInt(10000000000000000)}, 119 }, 10000000, 120 ) 121 } 122 123 func TestNewSimulatedBackend(t *testing.T) { 124 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 125 expectedBal := big.NewInt(10000000000000000) 126 sim := simTestBackend(testAddr) 127 defer sim.Close() 128 129 if sim.config != params.AllEthashProtocolChanges { 130 t.Errorf("expected sim config to equal params.AllEthashProtocolChanges, got %v", sim.config) 131 } 132 133 if sim.blockchain.Config() != params.AllEthashProtocolChanges { 134 t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config) 135 } 136 137 stateDB, _ := sim.blockchain.State() 138 bal := stateDB.GetBalance(testAddr) 139 if bal.Cmp(expectedBal) != 0 { 140 t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal) 141 } 142 } 143 144 func TestAdjustTime(t *testing.T) { 145 sim := NewSimulatedBackend( 146 core.GenesisAlloc{}, 10000000, 147 ) 148 defer sim.Close() 149 150 prevTime := sim.pendingBlock.Time() 151 if err := sim.AdjustTime(time.Second); err != nil { 152 t.Error(err) 153 } 154 newTime := sim.pendingBlock.Time() 155 156 if newTime-prevTime != uint64(time.Second.Seconds()) { 157 t.Errorf("adjusted time not equal to a second. prev: %v, new: %v", prevTime, newTime) 158 } 159 } 160 161 func TestNewAdjustTimeFail(t *testing.T) { 162 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 163 sim := simTestBackend(testAddr) 164 165 // Create tx and send 166 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 167 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 168 169 tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 170 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 171 if err != nil { 172 t.Errorf("could not sign tx: %v", err) 173 } 174 sim.SendTransaction(context.Background(), signedTx) 175 // AdjustTime should fail on non-empty block 176 if err := sim.AdjustTime(time.Second); err == nil { 177 t.Error("Expected adjust time to error on non-empty block") 178 } 179 sim.Commit() 180 181 prevTime := sim.pendingBlock.Time() 182 if err := sim.AdjustTime(time.Minute); err != nil { 183 t.Error(err) 184 } 185 newTime := sim.pendingBlock.Time() 186 if newTime-prevTime != uint64(time.Minute.Seconds()) { 187 t.Errorf("adjusted time not equal to a minute. prev: %v, new: %v", prevTime, newTime) 188 } 189 // Put a transaction after adjusting time 190 tx2 := types.NewTransaction(1, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 191 signedTx2, err := types.SignTx(tx2, types.HomesteadSigner{}, testKey) 192 if err != nil { 193 t.Errorf("could not sign tx: %v", err) 194 } 195 sim.SendTransaction(context.Background(), signedTx2) 196 sim.Commit() 197 newTime = sim.pendingBlock.Time() 198 if newTime-prevTime >= uint64(time.Minute.Seconds()) { 199 t.Errorf("time adjusted, but shouldn't be: prev: %v, new: %v", prevTime, newTime) 200 } 201 } 202 203 func TestBalanceAt(t *testing.T) { 204 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 205 expectedBal := big.NewInt(10000000000000000) 206 sim := simTestBackend(testAddr) 207 defer sim.Close() 208 bgCtx := context.Background() 209 210 bal, err := sim.BalanceAt(bgCtx, testAddr, nil) 211 if err != nil { 212 t.Error(err) 213 } 214 215 if bal.Cmp(expectedBal) != 0 { 216 t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal) 217 } 218 } 219 220 func TestBlockByHash(t *testing.T) { 221 sim := NewSimulatedBackend( 222 core.GenesisAlloc{}, 10000000, 223 ) 224 defer sim.Close() 225 bgCtx := context.Background() 226 227 block, err := sim.BlockByNumber(bgCtx, nil) 228 if err != nil { 229 t.Errorf("could not get recent block: %v", err) 230 } 231 blockByHash, err := sim.BlockByHash(bgCtx, block.Hash()) 232 if err != nil { 233 t.Errorf("could not get recent block: %v", err) 234 } 235 236 if block.Hash() != blockByHash.Hash() { 237 t.Errorf("did not get expected block") 238 } 239 } 240 241 func TestBlockByNumber(t *testing.T) { 242 sim := NewSimulatedBackend( 243 core.GenesisAlloc{}, 10000000, 244 ) 245 defer sim.Close() 246 bgCtx := context.Background() 247 248 block, err := sim.BlockByNumber(bgCtx, nil) 249 if err != nil { 250 t.Errorf("could not get recent block: %v", err) 251 } 252 if block.NumberU64() != 0 { 253 t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64()) 254 } 255 256 // create one block 257 sim.Commit() 258 259 block, err = sim.BlockByNumber(bgCtx, nil) 260 if err != nil { 261 t.Errorf("could not get recent block: %v", err) 262 } 263 if block.NumberU64() != 1 { 264 t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64()) 265 } 266 267 blockByNumber, err := sim.BlockByNumber(bgCtx, big.NewInt(1)) 268 if err != nil { 269 t.Errorf("could not get block by number: %v", err) 270 } 271 if blockByNumber.Hash() != block.Hash() { 272 t.Errorf("did not get the same block with height of 1 as before") 273 } 274 } 275 276 func TestNonceAt(t *testing.T) { 277 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 278 279 sim := simTestBackend(testAddr) 280 defer sim.Close() 281 bgCtx := context.Background() 282 283 nonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(0)) 284 if err != nil { 285 t.Errorf("could not get nonce for test addr: %v", err) 286 } 287 288 if nonce != uint64(0) { 289 t.Errorf("received incorrect nonce. expected 0, got %v", nonce) 290 } 291 292 // create a signed transaction to send 293 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 294 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 295 296 tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 297 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 298 if err != nil { 299 t.Errorf("could not sign tx: %v", err) 300 } 301 302 // send tx to simulated backend 303 err = sim.SendTransaction(bgCtx, signedTx) 304 if err != nil { 305 t.Errorf("could not add tx to pending block: %v", err) 306 } 307 sim.Commit() 308 309 newNonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(1)) 310 if err != nil { 311 t.Errorf("could not get nonce for test addr: %v", err) 312 } 313 314 if newNonce != nonce+uint64(1) { 315 t.Errorf("received incorrect nonce. expected 1, got %v", nonce) 316 } 317 // create some more blocks 318 sim.Commit() 319 // Check that we can get data for an older block/state 320 newNonce, err = sim.NonceAt(bgCtx, testAddr, big.NewInt(1)) 321 if err != nil { 322 t.Fatalf("could not get nonce for test addr: %v", err) 323 } 324 if newNonce != nonce+uint64(1) { 325 t.Fatalf("received incorrect nonce. expected 1, got %v", nonce) 326 } 327 } 328 329 func TestSendTransaction(t *testing.T) { 330 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 331 332 sim := simTestBackend(testAddr) 333 defer sim.Close() 334 bgCtx := context.Background() 335 336 // create a signed transaction to send 337 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 338 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 339 340 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 341 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 342 if err != nil { 343 t.Errorf("could not sign tx: %v", err) 344 } 345 346 // send tx to simulated backend 347 err = sim.SendTransaction(bgCtx, signedTx) 348 if err != nil { 349 t.Errorf("could not add tx to pending block: %v", err) 350 } 351 sim.Commit() 352 353 block, err := sim.BlockByNumber(bgCtx, big.NewInt(1)) 354 if err != nil { 355 t.Errorf("could not get block at height 1: %v", err) 356 } 357 358 if signedTx.Hash() != block.Transactions()[0].Hash() { 359 t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash()) 360 } 361 } 362 363 func TestTransactionByHash(t *testing.T) { 364 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 365 366 sim := NewSimulatedBackend( 367 core.GenesisAlloc{ 368 testAddr: {Balance: big.NewInt(10000000000000000)}, 369 }, 10000000, 370 ) 371 defer sim.Close() 372 bgCtx := context.Background() 373 374 // create a signed transaction to send 375 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 376 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 377 378 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 379 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 380 if err != nil { 381 t.Errorf("could not sign tx: %v", err) 382 } 383 384 // send tx to simulated backend 385 err = sim.SendTransaction(bgCtx, signedTx) 386 if err != nil { 387 t.Errorf("could not add tx to pending block: %v", err) 388 } 389 390 // ensure tx is committed pending 391 receivedTx, pending, err := sim.TransactionByHash(bgCtx, signedTx.Hash()) 392 if err != nil { 393 t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err) 394 } 395 if !pending { 396 t.Errorf("expected transaction to be in pending state") 397 } 398 if receivedTx.Hash() != signedTx.Hash() { 399 t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash()) 400 } 401 402 sim.Commit() 403 404 // ensure tx is not and committed pending 405 receivedTx, pending, err = sim.TransactionByHash(bgCtx, signedTx.Hash()) 406 if err != nil { 407 t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err) 408 } 409 if pending { 410 t.Errorf("expected transaction to not be in pending state") 411 } 412 if receivedTx.Hash() != signedTx.Hash() { 413 t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash()) 414 } 415 } 416 417 func TestEstimateGas(t *testing.T) { 418 /* 419 pragma solidity ^0.6.4; 420 contract GasEstimation { 421 function PureRevert() public { revert(); } 422 function Revert() public { revert("revert reason");} 423 function OOG() public { for (uint i = 0; ; i++) {}} 424 function Assert() public { assert(false);} 425 function Valid() public {} 426 } 427 */ 428 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\"}]" 429 const contractBin = "0x60806040523480156100115760006000fd5b50610017565b61016e806100266000396000f3fe60806040523480156100115760006000fd5b506004361061005c5760003560e01c806350f6fe3414610062578063aa8b1d301461006c578063b9b046f914610076578063d8b9839114610080578063e09fface1461008a5761005c565b60006000fd5b61006a610094565b005b6100746100ad565b005b61007e6100b5565b005b6100886100c2565b005b610092610135565b005b6000600090505b5b808060010191505061009b565b505b565b60006000fd5b565b600015156100bf57fe5b5b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f72657665727420726561736f6e0000000000000000000000000000000000000081526020015060200191505060405180910390fd5b565b5b56fea2646970667358221220345bbcbb1a5ecf22b53a78eaebf95f8ee0eceff6d10d4b9643495084d2ec934a64736f6c63430006040033" 430 431 key, _ := crypto.GenerateKey() 432 addr := crypto.PubkeyToAddress(key.PublicKey) 433 opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) 434 435 sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether)}}, 10000000) 436 defer sim.Close() 437 438 parsed, _ := abi.JSON(strings.NewReader(contractAbi)) 439 contractAddr, _, _, _ := bind.DeployContract(opts, parsed, common.FromHex(contractBin), sim) 440 sim.Commit() 441 442 var cases = []struct { 443 name string 444 message ethereum.CallMsg 445 expect uint64 446 expectError error 447 expectData interface{} 448 }{ 449 {"plain transfer(valid)", ethereum.CallMsg{ 450 From: addr, 451 To: &addr, 452 Gas: 0, 453 GasPrice: big.NewInt(0), 454 Value: big.NewInt(1), 455 Data: nil, 456 }, params.TxGas, nil, nil}, 457 458 {"plain transfer(invalid)", ethereum.CallMsg{ 459 From: addr, 460 To: &contractAddr, 461 Gas: 0, 462 GasPrice: big.NewInt(0), 463 Value: big.NewInt(1), 464 Data: nil, 465 }, 0, errors.New("execution reverted"), nil}, 466 467 {"Revert", ethereum.CallMsg{ 468 From: addr, 469 To: &contractAddr, 470 Gas: 0, 471 GasPrice: big.NewInt(0), 472 Value: nil, 473 Data: common.Hex2Bytes("d8b98391"), 474 }, 0, errors.New("execution reverted: revert reason"), "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000"}, 475 476 {"PureRevert", ethereum.CallMsg{ 477 From: addr, 478 To: &contractAddr, 479 Gas: 0, 480 GasPrice: big.NewInt(0), 481 Value: nil, 482 Data: common.Hex2Bytes("aa8b1d30"), 483 }, 0, errors.New("execution reverted"), nil}, 484 485 {"OOG", ethereum.CallMsg{ 486 From: addr, 487 To: &contractAddr, 488 Gas: 100000, 489 GasPrice: big.NewInt(0), 490 Value: nil, 491 Data: common.Hex2Bytes("50f6fe34"), 492 }, 0, errors.New("gas required exceeds allowance (100000)"), nil}, 493 494 {"Assert", ethereum.CallMsg{ 495 From: addr, 496 To: &contractAddr, 497 Gas: 100000, 498 GasPrice: big.NewInt(0), 499 Value: nil, 500 Data: common.Hex2Bytes("b9b046f9"), 501 }, 0, errors.New("invalid opcode: INVALID"), nil}, 502 503 {"Valid", ethereum.CallMsg{ 504 From: addr, 505 To: &contractAddr, 506 Gas: 100000, 507 GasPrice: big.NewInt(0), 508 Value: nil, 509 Data: common.Hex2Bytes("e09fface"), 510 }, 21275, nil, nil}, 511 } 512 for _, c := range cases { 513 got, err := sim.EstimateGas(context.Background(), c.message) 514 if c.expectError != nil { 515 if err == nil { 516 t.Fatalf("Expect error, got nil") 517 } 518 if c.expectError.Error() != err.Error() { 519 t.Fatalf("Expect error, want %v, got %v", c.expectError, err) 520 } 521 if c.expectData != nil { 522 if err, ok := err.(*revertError); !ok { 523 t.Fatalf("Expect revert error, got %T", err) 524 } else if !reflect.DeepEqual(err.ErrorData(), c.expectData) { 525 t.Fatalf("Error data mismatch, want %v, got %v", c.expectData, err.ErrorData()) 526 } 527 } 528 continue 529 } 530 if got != c.expect { 531 t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got) 532 } 533 } 534 } 535 536 func TestEstimateGasWithPrice(t *testing.T) { 537 key, _ := crypto.GenerateKey() 538 addr := crypto.PubkeyToAddress(key.PublicKey) 539 540 sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether*2 + 2e17)}}, 10000000) 541 defer sim.Close() 542 543 recipient := common.HexToAddress("deadbeef") 544 var cases = []struct { 545 name string 546 message ethereum.CallMsg 547 expect uint64 548 expectError error 549 }{ 550 {"EstimateWithoutPrice", ethereum.CallMsg{ 551 From: addr, 552 To: &recipient, 553 Gas: 0, 554 GasPrice: big.NewInt(0), 555 Value: big.NewInt(100000000000), 556 Data: nil, 557 }, 21000, nil}, 558 559 {"EstimateWithPrice", ethereum.CallMsg{ 560 From: addr, 561 To: &recipient, 562 Gas: 0, 563 GasPrice: big.NewInt(100000000000), 564 Value: big.NewInt(100000000000), 565 Data: nil, 566 }, 21000, nil}, 567 568 {"EstimateWithVeryHighPrice", ethereum.CallMsg{ 569 From: addr, 570 To: &recipient, 571 Gas: 0, 572 GasPrice: big.NewInt(1e14), // gascost = 2.1ether 573 Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether 574 Data: nil, 575 }, 21000, nil}, 576 577 {"EstimateWithSuperhighPrice", ethereum.CallMsg{ 578 From: addr, 579 To: &recipient, 580 Gas: 0, 581 GasPrice: big.NewInt(2e14), // gascost = 4.2ether 582 Value: big.NewInt(100000000000), 583 Data: nil, 584 }, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14) 585 586 {"EstimateEIP1559WithHighFees", ethereum.CallMsg{ 587 From: addr, 588 To: &addr, 589 Gas: 0, 590 GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether 591 GasTipCap: big.NewInt(1), 592 Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether 593 Data: nil, 594 }, params.TxGas, nil}, 595 596 {"EstimateEIP1559WithSuperHighFees", ethereum.CallMsg{ 597 From: addr, 598 To: &addr, 599 Gas: 0, 600 GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether 601 GasTipCap: big.NewInt(1), 602 Value: big.NewInt(1e17 + 1), // the remaining balance for fee is 2.1ether 603 Data: nil, 604 }, params.TxGas, errors.New("gas required exceeds allowance (20999)")}, // 20999=(2.2ether-0.1ether-1wei)/(1e14) 605 } 606 for i, c := range cases { 607 got, err := sim.EstimateGas(context.Background(), c.message) 608 if c.expectError != nil { 609 if err == nil { 610 t.Fatalf("test %d: expect error, got nil", i) 611 } 612 if c.expectError.Error() != err.Error() { 613 t.Fatalf("test %d: expect error, want %v, got %v", i, c.expectError, err) 614 } 615 continue 616 } 617 if c.expectError == nil && err != nil { 618 t.Fatalf("test %d: didn't expect error, got %v", i, err) 619 } 620 if got != c.expect { 621 t.Fatalf("test %d: gas estimation mismatch, want %d, got %d", i, c.expect, got) 622 } 623 } 624 } 625 626 func TestHeaderByHash(t *testing.T) { 627 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 628 629 sim := simTestBackend(testAddr) 630 defer sim.Close() 631 bgCtx := context.Background() 632 633 header, err := sim.HeaderByNumber(bgCtx, nil) 634 if err != nil { 635 t.Errorf("could not get recent block: %v", err) 636 } 637 headerByHash, err := sim.HeaderByHash(bgCtx, header.Hash()) 638 if err != nil { 639 t.Errorf("could not get recent block: %v", err) 640 } 641 642 if header.Hash() != headerByHash.Hash() { 643 t.Errorf("did not get expected block") 644 } 645 } 646 647 func TestHeaderByNumber(t *testing.T) { 648 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 649 650 sim := simTestBackend(testAddr) 651 defer sim.Close() 652 bgCtx := context.Background() 653 654 latestBlockHeader, err := sim.HeaderByNumber(bgCtx, nil) 655 if err != nil { 656 t.Errorf("could not get header for tip of chain: %v", err) 657 } 658 if latestBlockHeader == nil { 659 t.Errorf("received a nil block header") 660 } else if latestBlockHeader.Number.Uint64() != uint64(0) { 661 t.Errorf("expected block header number 0, instead got %v", latestBlockHeader.Number.Uint64()) 662 } 663 664 sim.Commit() 665 666 latestBlockHeader, err = sim.HeaderByNumber(bgCtx, nil) 667 if err != nil { 668 t.Errorf("could not get header for blockheight of 1: %v", err) 669 } 670 671 blockHeader, err := sim.HeaderByNumber(bgCtx, big.NewInt(1)) 672 if err != nil { 673 t.Errorf("could not get header for blockheight of 1: %v", err) 674 } 675 676 if blockHeader.Hash() != latestBlockHeader.Hash() { 677 t.Errorf("block header and latest block header are not the same") 678 } 679 if blockHeader.Number.Int64() != int64(1) { 680 t.Errorf("did not get blockheader for block 1. instead got block %v", blockHeader.Number.Int64()) 681 } 682 683 block, err := sim.BlockByNumber(bgCtx, big.NewInt(1)) 684 if err != nil { 685 t.Errorf("could not get block for blockheight of 1: %v", err) 686 } 687 688 if block.Hash() != blockHeader.Hash() { 689 t.Errorf("block hash and block header hash do not match. expected %v, got %v", block.Hash(), blockHeader.Hash()) 690 } 691 } 692 693 func TestTransactionCount(t *testing.T) { 694 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 695 696 sim := simTestBackend(testAddr) 697 defer sim.Close() 698 bgCtx := context.Background() 699 currentBlock, err := sim.BlockByNumber(bgCtx, nil) 700 if err != nil || currentBlock == nil { 701 t.Error("could not get current block") 702 } 703 704 count, err := sim.TransactionCount(bgCtx, currentBlock.Hash()) 705 if err != nil { 706 t.Error("could not get current block's transaction count") 707 } 708 709 if count != 0 { 710 t.Errorf("expected transaction count of %v does not match actual count of %v", 0, count) 711 } 712 // create a signed transaction to send 713 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 714 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 715 716 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 717 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 718 if err != nil { 719 t.Errorf("could not sign tx: %v", err) 720 } 721 722 // send tx to simulated backend 723 err = sim.SendTransaction(bgCtx, signedTx) 724 if err != nil { 725 t.Errorf("could not add tx to pending block: %v", err) 726 } 727 728 sim.Commit() 729 730 lastBlock, err := sim.BlockByNumber(bgCtx, nil) 731 if err != nil { 732 t.Errorf("could not get header for tip of chain: %v", err) 733 } 734 735 count, err = sim.TransactionCount(bgCtx, lastBlock.Hash()) 736 if err != nil { 737 t.Error("could not get current block's transaction count") 738 } 739 740 if count != 1 { 741 t.Errorf("expected transaction count of %v does not match actual count of %v", 1, count) 742 } 743 } 744 745 func TestTransactionInBlock(t *testing.T) { 746 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 747 748 sim := simTestBackend(testAddr) 749 defer sim.Close() 750 bgCtx := context.Background() 751 752 transaction, err := sim.TransactionInBlock(bgCtx, sim.pendingBlock.Hash(), uint(0)) 753 if err == nil && err != errTransactionDoesNotExist { 754 t.Errorf("expected a transaction does not exist error to be received but received %v", err) 755 } 756 if transaction != nil { 757 t.Errorf("expected transaction to be nil but received %v", transaction) 758 } 759 760 // expect pending nonce to be 0 since account has not been used 761 pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr) 762 if err != nil { 763 t.Errorf("did not get the pending nonce: %v", err) 764 } 765 766 if pendingNonce != uint64(0) { 767 t.Errorf("expected pending nonce of 0 got %v", pendingNonce) 768 } 769 // create a signed transaction to send 770 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 771 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 772 773 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 774 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 775 if err != nil { 776 t.Errorf("could not sign tx: %v", err) 777 } 778 779 // send tx to simulated backend 780 err = sim.SendTransaction(bgCtx, signedTx) 781 if err != nil { 782 t.Errorf("could not add tx to pending block: %v", err) 783 } 784 785 sim.Commit() 786 787 lastBlock, err := sim.BlockByNumber(bgCtx, nil) 788 if err != nil { 789 t.Errorf("could not get header for tip of chain: %v", err) 790 } 791 792 transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(1)) 793 if err == nil && err != errTransactionDoesNotExist { 794 t.Errorf("expected a transaction does not exist error to be received but received %v", err) 795 } 796 if transaction != nil { 797 t.Errorf("expected transaction to be nil but received %v", transaction) 798 } 799 800 transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(0)) 801 if err != nil { 802 t.Errorf("could not get transaction in the lastest block with hash %v: %v", lastBlock.Hash().String(), err) 803 } 804 805 if signedTx.Hash().String() != transaction.Hash().String() { 806 t.Errorf("received transaction that did not match the sent transaction. expected hash %v, got hash %v", signedTx.Hash().String(), transaction.Hash().String()) 807 } 808 } 809 810 func TestPendingNonceAt(t *testing.T) { 811 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 812 813 sim := simTestBackend(testAddr) 814 defer sim.Close() 815 bgCtx := context.Background() 816 817 // expect pending nonce to be 0 since account has not been used 818 pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr) 819 if err != nil { 820 t.Errorf("did not get the pending nonce: %v", err) 821 } 822 823 if pendingNonce != uint64(0) { 824 t.Errorf("expected pending nonce of 0 got %v", pendingNonce) 825 } 826 827 // create a signed transaction to send 828 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 829 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 830 831 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 832 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 833 if err != nil { 834 t.Errorf("could not sign tx: %v", err) 835 } 836 837 // send tx to simulated backend 838 err = sim.SendTransaction(bgCtx, signedTx) 839 if err != nil { 840 t.Errorf("could not add tx to pending block: %v", err) 841 } 842 843 // expect pending nonce to be 1 since account has submitted one transaction 844 pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr) 845 if err != nil { 846 t.Errorf("did not get the pending nonce: %v", err) 847 } 848 849 if pendingNonce != uint64(1) { 850 t.Errorf("expected pending nonce of 1 got %v", pendingNonce) 851 } 852 853 // make a new transaction with a nonce of 1 854 tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 855 signedTx, err = types.SignTx(tx, types.HomesteadSigner{}, testKey) 856 if err != nil { 857 t.Errorf("could not sign tx: %v", err) 858 } 859 err = sim.SendTransaction(bgCtx, signedTx) 860 if err != nil { 861 t.Errorf("could not send tx: %v", err) 862 } 863 864 // expect pending nonce to be 2 since account now has two transactions 865 pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr) 866 if err != nil { 867 t.Errorf("did not get the pending nonce: %v", err) 868 } 869 870 if pendingNonce != uint64(2) { 871 t.Errorf("expected pending nonce of 2 got %v", pendingNonce) 872 } 873 } 874 875 func TestTransactionReceipt(t *testing.T) { 876 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 877 878 sim := simTestBackend(testAddr) 879 defer sim.Close() 880 bgCtx := context.Background() 881 882 // create a signed transaction to send 883 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 884 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 885 886 tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 887 signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) 888 if err != nil { 889 t.Errorf("could not sign tx: %v", err) 890 } 891 892 // send tx to simulated backend 893 err = sim.SendTransaction(bgCtx, signedTx) 894 if err != nil { 895 t.Errorf("could not add tx to pending block: %v", err) 896 } 897 sim.Commit() 898 899 receipt, err := sim.TransactionReceipt(bgCtx, signedTx.Hash()) 900 if err != nil { 901 t.Errorf("could not get transaction receipt: %v", err) 902 } 903 904 if receipt.ContractAddress != testAddr && receipt.TxHash != signedTx.Hash() { 905 t.Errorf("received receipt is not correct: %v", receipt) 906 } 907 } 908 909 func TestSuggestGasPrice(t *testing.T) { 910 sim := NewSimulatedBackend( 911 core.GenesisAlloc{}, 912 10000000, 913 ) 914 defer sim.Close() 915 bgCtx := context.Background() 916 gasPrice, err := sim.SuggestGasPrice(bgCtx) 917 if err != nil { 918 t.Errorf("could not get gas price: %v", err) 919 } 920 if gasPrice.Uint64() != sim.pendingBlock.Header().BaseFee.Uint64() { 921 t.Errorf("gas price was not expected value of %v. actual: %v", sim.pendingBlock.Header().BaseFee.Uint64(), gasPrice.Uint64()) 922 } 923 } 924 925 func TestPendingCodeAt(t *testing.T) { 926 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 927 sim := simTestBackend(testAddr) 928 defer sim.Close() 929 bgCtx := context.Background() 930 code, err := sim.CodeAt(bgCtx, testAddr, nil) 931 if err != nil { 932 t.Errorf("could not get code at test addr: %v", err) 933 } 934 if len(code) != 0 { 935 t.Errorf("got code for account that does not have contract code") 936 } 937 938 parsed, err := abi.JSON(strings.NewReader(abiJSON)) 939 if err != nil { 940 t.Errorf("could not get code at test addr: %v", err) 941 } 942 auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337)) 943 contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim) 944 if err != nil { 945 t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract) 946 } 947 948 code, err = sim.PendingCodeAt(bgCtx, contractAddr) 949 if err != nil { 950 t.Errorf("could not get code at test addr: %v", err) 951 } 952 if len(code) == 0 { 953 t.Errorf("did not get code for account that has contract code") 954 } 955 // ensure code received equals code deployed 956 if !bytes.Equal(code, common.FromHex(deployedCode)) { 957 t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code) 958 } 959 } 960 961 func TestCodeAt(t *testing.T) { 962 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 963 sim := simTestBackend(testAddr) 964 defer sim.Close() 965 bgCtx := context.Background() 966 code, err := sim.CodeAt(bgCtx, testAddr, nil) 967 if err != nil { 968 t.Errorf("could not get code at test addr: %v", err) 969 } 970 if len(code) != 0 { 971 t.Errorf("got code for account that does not have contract code") 972 } 973 974 parsed, err := abi.JSON(strings.NewReader(abiJSON)) 975 if err != nil { 976 t.Errorf("could not get code at test addr: %v", err) 977 } 978 auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337)) 979 contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim) 980 if err != nil { 981 t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract) 982 } 983 984 sim.Commit() 985 code, err = sim.CodeAt(bgCtx, contractAddr, nil) 986 if err != nil { 987 t.Errorf("could not get code at test addr: %v", err) 988 } 989 if len(code) == 0 { 990 t.Errorf("did not get code for account that has contract code") 991 } 992 // ensure code received equals code deployed 993 if !bytes.Equal(code, common.FromHex(deployedCode)) { 994 t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code) 995 } 996 } 997 998 // When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt: 999 // 1000 // receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]} 1001 func TestPendingAndCallContract(t *testing.T) { 1002 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 1003 sim := simTestBackend(testAddr) 1004 defer sim.Close() 1005 bgCtx := context.Background() 1006 1007 parsed, err := abi.JSON(strings.NewReader(abiJSON)) 1008 if err != nil { 1009 t.Errorf("could not get code at test addr: %v", err) 1010 } 1011 contractAuth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337)) 1012 addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(abiBin), sim) 1013 if err != nil { 1014 t.Errorf("could not deploy contract: %v", err) 1015 } 1016 1017 input, err := parsed.Pack("receive", []byte("X")) 1018 if err != nil { 1019 t.Errorf("could not pack receive function on contract: %v", err) 1020 } 1021 1022 // make sure you can call the contract in pending state 1023 res, err := sim.PendingCallContract(bgCtx, ethereum.CallMsg{ 1024 From: testAddr, 1025 To: &addr, 1026 Data: input, 1027 }) 1028 if err != nil { 1029 t.Errorf("could not call receive method on contract: %v", err) 1030 } 1031 if len(res) == 0 { 1032 t.Errorf("result of contract call was empty: %v", res) 1033 } 1034 1035 // while comparing against the byte array is more exact, also compare against the human readable string for readability 1036 if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") { 1037 t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res)) 1038 } 1039 1040 sim.Commit() 1041 1042 // make sure you can call the contract 1043 res, err = sim.CallContract(bgCtx, ethereum.CallMsg{ 1044 From: testAddr, 1045 To: &addr, 1046 Data: input, 1047 }, nil) 1048 if err != nil { 1049 t.Errorf("could not call receive method on contract: %v", err) 1050 } 1051 if len(res) == 0 { 1052 t.Errorf("result of contract call was empty: %v", res) 1053 } 1054 1055 if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") { 1056 t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res)) 1057 } 1058 } 1059 1060 // This test is based on the following contract: 1061 /* 1062 contract Reverter { 1063 function revertString() public pure{ 1064 require(false, "some error"); 1065 } 1066 function revertNoString() public pure { 1067 require(false, ""); 1068 } 1069 function revertASM() public pure { 1070 assembly { 1071 revert(0x0, 0x0) 1072 } 1073 } 1074 function noRevert() public pure { 1075 assembly { 1076 // Assembles something that looks like require(false, "some error") but is not reverted 1077 mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000) 1078 mstore(0x4, 0x0000000000000000000000000000000000000000000000000000000000000020) 1079 mstore(0x24, 0x000000000000000000000000000000000000000000000000000000000000000a) 1080 mstore(0x44, 0x736f6d65206572726f7200000000000000000000000000000000000000000000) 1081 return(0x0, 0x64) 1082 } 1083 } 1084 }*/ 1085 func TestCallContractRevert(t *testing.T) { 1086 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 1087 sim := simTestBackend(testAddr) 1088 defer sim.Close() 1089 bgCtx := context.Background() 1090 1091 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"}]` 1092 reverterBin := "608060405234801561001057600080fd5b506101d3806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634b409e01146100515780639b340e361461005b5780639bd6103714610065578063b7246fc11461006f575b600080fd5b610059610079565b005b6100636100ca565b005b61006d6100cf565b005b610077610145565b005b60006100c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526000815260200160200191505060405180910390fd5b565b600080fd5b6000610143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f736f6d65206572726f720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b7f08c379a0000000000000000000000000000000000000000000000000000000006000526020600452600a6024527f736f6d65206572726f720000000000000000000000000000000000000000000060445260646000f3fea2646970667358221220cdd8af0609ec4996b7360c7c780bad5c735740c64b1fffc3445aa12d37f07cb164736f6c63430006070033" 1093 1094 parsed, err := abi.JSON(strings.NewReader(reverterABI)) 1095 if err != nil { 1096 t.Errorf("could not get code at test addr: %v", err) 1097 } 1098 contractAuth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337)) 1099 addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(reverterBin), sim) 1100 if err != nil { 1101 t.Errorf("could not deploy contract: %v", err) 1102 } 1103 1104 inputs := make(map[string]interface{}, 3) 1105 inputs["revertASM"] = nil 1106 inputs["revertNoString"] = "" 1107 inputs["revertString"] = "some error" 1108 1109 call := make([]func([]byte) ([]byte, error), 2) 1110 call[0] = func(input []byte) ([]byte, error) { 1111 return sim.PendingCallContract(bgCtx, ethereum.CallMsg{ 1112 From: testAddr, 1113 To: &addr, 1114 Data: input, 1115 }) 1116 } 1117 call[1] = func(input []byte) ([]byte, error) { 1118 return sim.CallContract(bgCtx, ethereum.CallMsg{ 1119 From: testAddr, 1120 To: &addr, 1121 Data: input, 1122 }, nil) 1123 } 1124 1125 // Run pending calls then commit 1126 for _, cl := range call { 1127 for key, val := range inputs { 1128 input, err := parsed.Pack(key) 1129 if err != nil { 1130 t.Errorf("could not pack %v function on contract: %v", key, err) 1131 } 1132 1133 res, err := cl(input) 1134 if err == nil { 1135 t.Errorf("call to %v was not reverted", key) 1136 } 1137 if res != nil { 1138 t.Errorf("result from %v was not nil: %v", key, res) 1139 } 1140 if val != nil { 1141 rerr, ok := err.(*revertError) 1142 if !ok { 1143 t.Errorf("expect revert error") 1144 } 1145 if rerr.Error() != "execution reverted: "+val.(string) { 1146 t.Errorf("error was malformed: got %v want %v", rerr.Error(), val) 1147 } 1148 } else { 1149 // revert(0x0,0x0) 1150 if err.Error() != "execution reverted" { 1151 t.Errorf("error was malformed: got %v want %v", err, "execution reverted") 1152 } 1153 } 1154 } 1155 input, err := parsed.Pack("noRevert") 1156 if err != nil { 1157 t.Errorf("could not pack noRevert function on contract: %v", err) 1158 } 1159 res, err := cl(input) 1160 if err != nil { 1161 t.Error("call to noRevert was reverted") 1162 } 1163 if res == nil { 1164 t.Errorf("result from noRevert was nil") 1165 } 1166 sim.Commit() 1167 } 1168 } 1169 1170 // TestFork check that the chain length after a reorg is correct. 1171 // Steps: 1172 // 1. Save the current block which will serve as parent for the fork. 1173 // 2. Mine n blocks with n ∈ [0, 20]. 1174 // 3. Assert that the chain length is n. 1175 // 4. Fork by using the parent block as ancestor. 1176 // 5. Mine n+1 blocks which should trigger a reorg. 1177 // 6. Assert that the chain length is n+1. 1178 // Since Commit() was called 2n+1 times in total, 1179 // having a chain length of just n+1 means that a reorg occurred. 1180 func TestFork(t *testing.T) { 1181 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 1182 sim := simTestBackend(testAddr) 1183 defer sim.Close() 1184 // 1. 1185 parent := sim.blockchain.CurrentBlock() 1186 // 2. 1187 n := int(rand.Int31n(21)) 1188 for i := 0; i < n; i++ { 1189 sim.Commit() 1190 } 1191 // 3. 1192 if sim.blockchain.CurrentBlock().NumberU64() != uint64(n) { 1193 t.Error("wrong chain length") 1194 } 1195 // 4. 1196 sim.Fork(context.Background(), parent.Hash()) 1197 // 5. 1198 for i := 0; i < n+1; i++ { 1199 sim.Commit() 1200 } 1201 // 6. 1202 if sim.blockchain.CurrentBlock().NumberU64() != uint64(n+1) { 1203 t.Error("wrong chain length") 1204 } 1205 } 1206 1207 /* 1208 Example contract to test event emission: 1209 1210 pragma solidity >=0.7.0 <0.9.0; 1211 contract Callable { 1212 event Called(); 1213 function Call() public { emit Called(); } 1214 } 1215 */ 1216 const callableAbi = "[{\"anonymous\":false,\"inputs\":[],\"name\":\"Called\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"Call\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" 1217 1218 const callableBin = "6080604052348015600f57600080fd5b5060998061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806334e2292114602d575b600080fd5b60336035565b005b7f81fab7a4a0aa961db47eefc81f143a5220e8c8495260dd65b1356f1d19d3c7b860405160405180910390a156fea2646970667358221220029436d24f3ac598ceca41d4d712e13ced6d70727f4cdc580667de66d2f51d8b64736f6c63430008010033" 1219 1220 // TestForkLogsReborn check that the simulated reorgs 1221 // correctly remove and reborn logs. 1222 // Steps: 1223 // 1. Deploy the Callable contract. 1224 // 2. Set up an event subscription. 1225 // 3. Save the current block which will serve as parent for the fork. 1226 // 4. Send a transaction. 1227 // 5. Check that the event was included. 1228 // 6. Fork by using the parent block as ancestor. 1229 // 7. Mine two blocks to trigger a reorg. 1230 // 8. Check that the event was removed. 1231 // 9. Re-send the transaction and mine a block. 1232 // 10. Check that the event was reborn. 1233 func TestForkLogsReborn(t *testing.T) { 1234 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 1235 sim := simTestBackend(testAddr) 1236 defer sim.Close() 1237 // 1. 1238 parsed, _ := abi.JSON(strings.NewReader(callableAbi)) 1239 auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337)) 1240 _, _, contract, err := bind.DeployContract(auth, parsed, common.FromHex(callableBin), sim) 1241 if err != nil { 1242 t.Errorf("deploying contract: %v", err) 1243 } 1244 sim.Commit() 1245 // 2. 1246 logs, sub, err := contract.WatchLogs(nil, "Called") 1247 if err != nil { 1248 t.Errorf("watching logs: %v", err) 1249 } 1250 defer sub.Unsubscribe() 1251 // 3. 1252 parent := sim.blockchain.CurrentBlock() 1253 // 4. 1254 tx, err := contract.Transact(auth, "Call") 1255 if err != nil { 1256 t.Errorf("transacting: %v", err) 1257 } 1258 sim.Commit() 1259 // 5. 1260 log := <-logs 1261 if log.TxHash != tx.Hash() { 1262 t.Error("wrong event tx hash") 1263 } 1264 if log.Removed { 1265 t.Error("Event should be included") 1266 } 1267 // 6. 1268 if err := sim.Fork(context.Background(), parent.Hash()); err != nil { 1269 t.Errorf("forking: %v", err) 1270 } 1271 // 7. 1272 sim.Commit() 1273 sim.Commit() 1274 // 8. 1275 log = <-logs 1276 if log.TxHash != tx.Hash() { 1277 t.Error("wrong event tx hash") 1278 } 1279 if !log.Removed { 1280 t.Error("Event should be removed") 1281 } 1282 // 9. 1283 if err := sim.SendTransaction(context.Background(), tx); err != nil { 1284 t.Errorf("sending transaction: %v", err) 1285 } 1286 sim.Commit() 1287 // 10. 1288 log = <-logs 1289 if log.TxHash != tx.Hash() { 1290 t.Error("wrong event tx hash") 1291 } 1292 if log.Removed { 1293 t.Error("Event should be included") 1294 } 1295 } 1296 1297 // TestForkResendTx checks that re-sending a TX after a fork 1298 // is possible and does not cause a "nonce mismatch" panic. 1299 // Steps: 1300 // 1. Save the current block which will serve as parent for the fork. 1301 // 2. Send a transaction. 1302 // 3. Check that the TX is included in block 1. 1303 // 4. Fork by using the parent block as ancestor. 1304 // 5. Mine a block, Re-send the transaction and mine another one. 1305 // 6. Check that the TX is now included in block 2. 1306 func TestForkResendTx(t *testing.T) { 1307 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 1308 sim := simTestBackend(testAddr) 1309 defer sim.Close() 1310 // 1. 1311 parent := sim.blockchain.CurrentBlock() 1312 // 2. 1313 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 1314 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 1315 1316 _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 1317 tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey) 1318 sim.SendTransaction(context.Background(), tx) 1319 sim.Commit() 1320 // 3. 1321 receipt, _ := sim.TransactionReceipt(context.Background(), tx.Hash()) 1322 if h := receipt.BlockNumber.Uint64(); h != 1 { 1323 t.Errorf("TX included in wrong block: %d", h) 1324 } 1325 // 4. 1326 if err := sim.Fork(context.Background(), parent.Hash()); err != nil { 1327 t.Errorf("forking: %v", err) 1328 } 1329 // 5. 1330 sim.Commit() 1331 if err := sim.SendTransaction(context.Background(), tx); err != nil { 1332 t.Errorf("sending transaction: %v", err) 1333 } 1334 sim.Commit() 1335 // 6. 1336 receipt, _ = sim.TransactionReceipt(context.Background(), tx.Hash()) 1337 if h := receipt.BlockNumber.Uint64(); h != 2 { 1338 t.Errorf("TX included in wrong block: %d", h) 1339 } 1340 } 1341 1342 func TestCommitReturnValue(t *testing.T) { 1343 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 1344 sim := simTestBackend(testAddr) 1345 defer sim.Close() 1346 1347 startBlockHeight := sim.blockchain.CurrentBlock().NumberU64() 1348 1349 // Test if Commit returns the correct block hash 1350 h1 := sim.Commit() 1351 if h1 != sim.blockchain.CurrentBlock().Hash() { 1352 t.Error("Commit did not return the hash of the last block.") 1353 } 1354 1355 // Create a block in the original chain (containing a transaction to force different block hashes) 1356 head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough 1357 gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) 1358 _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) 1359 tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey) 1360 sim.SendTransaction(context.Background(), tx) 1361 h2 := sim.Commit() 1362 1363 // Create another block in the original chain 1364 sim.Commit() 1365 1366 // Fork at the first bock 1367 if err := sim.Fork(context.Background(), h1); err != nil { 1368 t.Errorf("forking: %v", err) 1369 } 1370 1371 // Test if Commit returns the correct block hash after the reorg 1372 h2fork := sim.Commit() 1373 if h2 == h2fork { 1374 t.Error("The block in the fork and the original block are the same block!") 1375 } 1376 if sim.blockchain.GetHeader(h2fork, startBlockHeight+2) == nil { 1377 t.Error("Could not retrieve the just created block (side-chain)") 1378 } 1379 } 1380 1381 // TestAdjustTimeAfterFork ensures that after a fork, AdjustTime uses the pending fork 1382 // block's parent rather than the canonical head's parent. 1383 func TestAdjustTimeAfterFork(t *testing.T) { 1384 testAddr := crypto.PubkeyToAddress(testKey.PublicKey) 1385 sim := simTestBackend(testAddr) 1386 defer sim.Close() 1387 1388 sim.Commit() // h1 1389 h1 := sim.blockchain.CurrentHeader().Hash() 1390 sim.Commit() // h2 1391 sim.Fork(context.Background(), h1) 1392 sim.AdjustTime(1 * time.Second) 1393 sim.Commit() 1394 1395 head := sim.blockchain.CurrentHeader() 1396 if head.Number == common.Big2 && head.ParentHash != h1 { 1397 t.Errorf("failed to build block on fork") 1398 } 1399 }