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