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