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