github.com/onflow/flow-go@v0.33.17/fvm/evm/testutils/emulator.go (about) 1 package testutils 2 3 import ( 4 cryptoRand "crypto/rand" 5 "math/big" 6 "math/rand" 7 "testing" 8 9 gethCommon "github.com/ethereum/go-ethereum/common" 10 gethTypes "github.com/ethereum/go-ethereum/core/types" 11 "github.com/stretchr/testify/require" 12 13 "github.com/onflow/flow-go/fvm/evm/types" 14 ) 15 16 type TestEmulator struct { 17 BalanceOfFunc func(address types.Address) (*big.Int, error) 18 NonceOfFunc func(address types.Address) (uint64, error) 19 CodeOfFunc func(address types.Address) (types.Code, error) 20 DirectCallFunc func(call *types.DirectCall) (*types.Result, error) 21 RunTransactionFunc func(tx *gethTypes.Transaction) (*types.Result, error) 22 } 23 24 var _ types.Emulator = &TestEmulator{} 25 26 // NewBlock returns a new block 27 func (em *TestEmulator) NewBlockView(_ types.BlockContext) (types.BlockView, error) { 28 return em, nil 29 } 30 31 // NewBlock returns a new block view 32 func (em *TestEmulator) NewReadOnlyBlockView(_ types.BlockContext) (types.ReadOnlyBlockView, error) { 33 return em, nil 34 } 35 36 // BalanceOf returns the balance of this address 37 func (em *TestEmulator) BalanceOf(address types.Address) (*big.Int, error) { 38 if em.BalanceOfFunc == nil { 39 panic("method not set") 40 } 41 return em.BalanceOfFunc(address) 42 } 43 44 // NonceOfFunc returns the nonce for this address 45 func (em *TestEmulator) NonceOf(address types.Address) (uint64, error) { 46 if em.NonceOfFunc == nil { 47 panic("method not set") 48 } 49 return em.NonceOfFunc(address) 50 } 51 52 // CodeOf returns the code for this address (if smart contract is deployed at this address) 53 func (em *TestEmulator) CodeOf(address types.Address) (types.Code, error) { 54 if em.CodeOfFunc == nil { 55 panic("method not set") 56 } 57 return em.CodeOfFunc(address) 58 } 59 60 // DirectCall executes a direct call 61 func (em *TestEmulator) DirectCall(call *types.DirectCall) (*types.Result, error) { 62 if em.DirectCallFunc == nil { 63 panic("method not set") 64 } 65 return em.DirectCallFunc(call) 66 } 67 68 // RunTransaction runs a transaction and collect gas fees to the coinbase account 69 func (em *TestEmulator) RunTransaction(tx *gethTypes.Transaction) (*types.Result, error) { 70 if em.RunTransactionFunc == nil { 71 panic("method not set") 72 } 73 return em.RunTransactionFunc(tx) 74 } 75 76 func RandomCommonHash(t testing.TB) gethCommon.Hash { 77 ret := gethCommon.Hash{} 78 _, err := cryptoRand.Read(ret[:gethCommon.HashLength]) 79 require.NoError(t, err) 80 return ret 81 } 82 83 func RandomBigInt(limit int64) *big.Int { 84 return big.NewInt(rand.Int63n(limit) + 1) 85 } 86 87 func RandomAddress(t testing.TB) types.Address { 88 return types.NewAddress(RandomCommonAddress(t)) 89 } 90 91 func RandomCommonAddress(t testing.TB) gethCommon.Address { 92 ret := gethCommon.Address{} 93 _, err := cryptoRand.Read(ret[:gethCommon.AddressLength]) 94 require.NoError(t, err) 95 return ret 96 } 97 98 func RandomGas(limit int64) uint64 { 99 return uint64(rand.Int63n(limit) + 1) 100 } 101 102 func RandomData(t testing.TB) []byte { 103 // byte size [1, 100] 104 size := rand.Intn(100) + 1 105 ret := make([]byte, size) 106 _, err := cryptoRand.Read(ret[:]) 107 require.NoError(t, err) 108 return ret 109 } 110 111 func GetRandomLogFixture(t testing.TB) *gethTypes.Log { 112 return &gethTypes.Log{ 113 Address: RandomCommonAddress(t), 114 Topics: []gethCommon.Hash{ 115 RandomCommonHash(t), 116 RandomCommonHash(t), 117 }, 118 Data: RandomData(t), 119 } 120 }