github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/evm/testutils/accounts.go (about) 1 package testutils 2 3 import ( 4 "bytes" 5 "crypto/ecdsa" 6 "io" 7 "math/big" 8 "sync" 9 "testing" 10 11 gethCommon "github.com/onflow/go-ethereum/common" 12 gethTypes "github.com/onflow/go-ethereum/core/types" 13 gethCrypto "github.com/onflow/go-ethereum/crypto" 14 "github.com/stretchr/testify/require" 15 16 "github.com/onflow/atree" 17 18 "github.com/onflow/flow-go/fvm/evm/emulator" 19 "github.com/onflow/flow-go/fvm/evm/types" 20 "github.com/onflow/flow-go/model/flow" 21 ) 22 23 // address: 658bdf435d810c91414ec09147daa6db62406379 24 const EOATestAccount1KeyHex = "9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c" 25 26 type EOATestAccount struct { 27 address gethCommon.Address 28 key *ecdsa.PrivateKey 29 nonce uint64 30 signer gethTypes.Signer 31 lock sync.Mutex 32 } 33 34 func (a *EOATestAccount) Address() types.Address { 35 return types.Address(a.address) 36 } 37 38 func (a *EOATestAccount) PrepareSignAndEncodeTx( 39 t testing.TB, 40 to gethCommon.Address, 41 data []byte, 42 amount *big.Int, 43 gasLimit uint64, 44 gasPrice *big.Int, 45 ) []byte { 46 tx := a.PrepareAndSignTx(t, to, data, amount, gasLimit, gasPrice) 47 var b bytes.Buffer 48 writer := io.Writer(&b) 49 err := tx.EncodeRLP(writer) 50 require.NoError(t, err) 51 return b.Bytes() 52 } 53 54 func (a *EOATestAccount) PrepareAndSignTx( 55 t testing.TB, 56 to gethCommon.Address, 57 data []byte, 58 amount *big.Int, 59 gasLimit uint64, 60 gasPrice *big.Int, 61 ) *gethTypes.Transaction { 62 a.lock.Lock() 63 defer a.lock.Unlock() 64 65 tx := a.signTx( 66 t, 67 gethTypes.NewTransaction( 68 a.nonce, 69 to, 70 amount, 71 gasLimit, 72 gasPrice, 73 data, 74 ), 75 ) 76 a.nonce++ 77 78 return tx 79 } 80 81 func (a *EOATestAccount) SignTx( 82 t testing.TB, 83 tx *gethTypes.Transaction, 84 ) *gethTypes.Transaction { 85 a.lock.Lock() 86 defer a.lock.Unlock() 87 88 return a.signTx(t, tx) 89 } 90 91 func (a *EOATestAccount) signTx( 92 t testing.TB, 93 tx *gethTypes.Transaction, 94 ) *gethTypes.Transaction { 95 tx, err := gethTypes.SignTx(tx, a.signer, a.key) 96 require.NoError(t, err) 97 return tx 98 } 99 100 func (a *EOATestAccount) Nonce() uint64 { 101 return a.nonce 102 } 103 104 func (a *EOATestAccount) SetNonce(nonce uint64) { 105 a.lock.Lock() 106 defer a.lock.Unlock() 107 108 a.nonce = nonce 109 } 110 111 func GetTestEOAAccount(t testing.TB, keyHex string) *EOATestAccount { 112 key, _ := gethCrypto.HexToECDSA(keyHex) 113 address := gethCrypto.PubkeyToAddress(key.PublicKey) 114 signer := emulator.GetDefaultSigner() 115 return &EOATestAccount{ 116 address: address, 117 key: key, 118 signer: signer, 119 lock: sync.Mutex{}, 120 } 121 } 122 123 func RunWithEOATestAccount(t testing.TB, led atree.Ledger, flowEVMRootAddress flow.Address, f func(*EOATestAccount)) { 124 account := FundAndGetEOATestAccount(t, led, flowEVMRootAddress) 125 f(account) 126 } 127 128 func FundAndGetEOATestAccount(t testing.TB, led atree.Ledger, flowEVMRootAddress flow.Address) *EOATestAccount { 129 account := GetTestEOAAccount(t, EOATestAccount1KeyHex) 130 131 // fund account 132 e := emulator.NewEmulator(led, flowEVMRootAddress) 133 134 blk, err := e.NewBlockView(types.NewDefaultBlockContext(2)) 135 require.NoError(t, err) 136 137 _, err = blk.DirectCall( 138 types.NewDepositCall( 139 RandomAddress(t), // any random non-empty address works here 140 account.Address(), 141 new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1000)), 142 account.nonce, 143 ), 144 ) 145 require.NoError(t, err) 146 147 blk2, err := e.NewReadOnlyBlockView(types.NewDefaultBlockContext(2)) 148 require.NoError(t, err) 149 150 bal, err := blk2.BalanceOf(account.Address()) 151 require.NoError(t, err) 152 require.Greater(t, bal.Uint64(), uint64(0)) 153 154 return account 155 }