simulated_test.go 41 KB

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