github.com/onflow/flow-go@v0.33.17/fvm/evm/evm_test.go (about) 1 package evm_test 2 3 import ( 4 "fmt" 5 "math/big" 6 "testing" 7 8 "github.com/onflow/cadence" 9 "github.com/onflow/cadence/encoding/json" 10 "github.com/stretchr/testify/require" 11 12 "github.com/onflow/flow-go/fvm" 13 "github.com/onflow/flow-go/fvm/evm/stdlib" 14 "github.com/onflow/flow-go/fvm/evm/testutils" 15 . "github.com/onflow/flow-go/fvm/evm/testutils" 16 "github.com/onflow/flow-go/fvm/storage/snapshot" 17 "github.com/onflow/flow-go/fvm/systemcontracts" 18 "github.com/onflow/flow-go/model/flow" 19 "github.com/onflow/flow-go/utils/unittest" 20 ) 21 22 func TestEVMRun(t *testing.T) { 23 24 t.Parallel() 25 26 t.Run("testing EVM.run (happy case)", func(t *testing.T) { 27 RunWithTestBackend(t, func(backend *testutils.TestBackend) { 28 RunWithTestFlowEVMRootAddress(t, backend, func(rootAddr flow.Address) { 29 tc := GetStorageTestContract(t) 30 RunWithDeployedContract(t, tc, backend, rootAddr, func(testContract *TestContract) { 31 RunWithEOATestAccount(t, backend, rootAddr, func(testAccount *EOATestAccount) { 32 num := int64(12) 33 chain := flow.Emulator.Chain() 34 35 RunWithNewTestVM(t, chain, func(ctx fvm.Context, vm fvm.VM, snapshot snapshot.SnapshotTree) { 36 sc := systemcontracts.SystemContractsForChain(chain.ChainID()) 37 code := []byte(fmt.Sprintf( 38 ` 39 import EVM from %s 40 41 access(all) 42 fun main(tx: [UInt8], coinbaseBytes: [UInt8; 20]) { 43 let coinbase = EVM.EVMAddress(bytes: coinbaseBytes) 44 EVM.run(tx: tx, coinbase: coinbase) 45 } 46 `, 47 sc.EVMContract.Address.HexWithPrefix(), 48 )) 49 50 gasLimit := uint64(100_000) 51 52 txBytes := testAccount.PrepareSignAndEncodeTx(t, 53 testContract.DeployedAt.ToCommon(), 54 testContract.MakeCallData(t, "store", big.NewInt(num)), 55 big.NewInt(0), 56 gasLimit, 57 big.NewInt(0), 58 ) 59 60 tx := cadence.NewArray( 61 ConvertToCadence(txBytes), 62 ).WithType(stdlib.EVMTransactionBytesCadenceType) 63 64 coinbase := cadence.NewArray( 65 ConvertToCadence(testAccount.Address().Bytes()), 66 ).WithType(stdlib.EVMAddressBytesCadenceType) 67 68 script := fvm.Script(code).WithArguments( 69 json.MustEncode(tx), 70 json.MustEncode(coinbase), 71 ) 72 73 _, output, err := vm.Run( 74 ctx, 75 script, 76 snapshot) 77 require.NoError(t, err) 78 require.NoError(t, output.Err) 79 }) 80 }) 81 }) 82 }) 83 }) 84 }) 85 } 86 87 func RunWithNewTestVM(t *testing.T, chain flow.Chain, f func(fvm.Context, fvm.VM, snapshot.SnapshotTree)) { 88 opts := []fvm.Option{ 89 fvm.WithChain(chain), 90 fvm.WithAuthorizationChecksEnabled(false), 91 fvm.WithSequenceNumberCheckAndIncrementEnabled(false), 92 } 93 ctx := fvm.NewContext(opts...) 94 95 vm := fvm.NewVirtualMachine() 96 snapshotTree := snapshot.NewSnapshotTree(nil) 97 98 baseBootstrapOpts := []fvm.BootstrapProcedureOption{ 99 fvm.WithInitialTokenSupply(unittest.GenesisTokenSupply), 100 fvm.WithSetupEVMEnabled(true), 101 } 102 103 executionSnapshot, _, err := vm.Run( 104 ctx, 105 fvm.Bootstrap(unittest.ServiceAccountPublicKey, baseBootstrapOpts...), 106 snapshotTree) 107 require.NoError(t, err) 108 109 snapshotTree = snapshotTree.Append(executionSnapshot) 110 111 f(fvm.NewContextFromParent(ctx, fvm.WithEVMEnabled(true)), vm, snapshotTree) 112 } 113 114 func TestEVMAddressDeposit(t *testing.T) { 115 116 t.Parallel() 117 118 RunWithTestBackend(t, func(backend *testutils.TestBackend) { 119 RunWithTestFlowEVMRootAddress(t, backend, func(rootAddr flow.Address) { 120 tc := GetStorageTestContract(t) 121 RunWithDeployedContract(t, tc, backend, rootAddr, func(testContract *TestContract) { 122 RunWithEOATestAccount(t, backend, rootAddr, func(testAccount *EOATestAccount) { 123 chain := flow.Emulator.Chain() 124 sc := systemcontracts.SystemContractsForChain(chain.ChainID()) 125 126 RunWithNewTestVM(t, chain, func(ctx fvm.Context, vm fvm.VM, snapshot snapshot.SnapshotTree) { 127 128 code := []byte(fmt.Sprintf( 129 ` 130 import EVM from %s 131 import FlowToken from %s 132 133 access(all) 134 fun main() { 135 let admin = getAuthAccount(%s) 136 .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin)! 137 let minter <- admin.createNewMinter(allowedAmount: 1.23) 138 let vault <- minter.mintTokens(amount: 1.23) 139 destroy minter 140 141 let address = EVM.EVMAddress( 142 bytes: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 143 ) 144 address.deposit(from: <-vault) 145 } 146 `, 147 sc.EVMContract.Address.HexWithPrefix(), 148 sc.FlowToken.Address.HexWithPrefix(), 149 sc.FlowServiceAccount.Address.HexWithPrefix(), 150 )) 151 152 script := fvm.Script(code) 153 154 executionSnapshot, output, err := vm.Run( 155 ctx, 156 script, 157 snapshot) 158 require.NoError(t, err) 159 require.NoError(t, output.Err) 160 161 // TODO: 162 _ = executionSnapshot 163 }) 164 }) 165 }) 166 }) 167 }) 168 } 169 170 func TestBridgedAccountWithdraw(t *testing.T) { 171 172 t.Parallel() 173 174 RunWithTestBackend(t, func(backend *testutils.TestBackend) { 175 RunWithTestFlowEVMRootAddress(t, backend, func(rootAddr flow.Address) { 176 tc := GetStorageTestContract(t) 177 RunWithDeployedContract(t, tc, backend, rootAddr, func(testContract *TestContract) { 178 RunWithEOATestAccount(t, backend, rootAddr, func(testAccount *EOATestAccount) { 179 chain := flow.Emulator.Chain() 180 sc := systemcontracts.SystemContractsForChain(chain.ChainID()) 181 182 RunWithNewTestVM(t, chain, func(ctx fvm.Context, vm fvm.VM, snapshot snapshot.SnapshotTree) { 183 184 code := []byte(fmt.Sprintf( 185 ` 186 import EVM from %s 187 import FlowToken from %s 188 189 access(all) 190 fun main(): UFix64 { 191 let admin = getAuthAccount(%s) 192 .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin)! 193 let minter <- admin.createNewMinter(allowedAmount: 2.34) 194 let vault <- minter.mintTokens(amount: 2.34) 195 destroy minter 196 197 let bridgedAccount <- EVM.createBridgedAccount() 198 bridgedAccount.address().deposit(from: <-vault) 199 200 let vault2 <- bridgedAccount.withdraw(balance: EVM.Balance(flow: 1.23)) 201 let balance = vault2.balance 202 destroy bridgedAccount 203 destroy vault2 204 205 return balance 206 } 207 `, 208 sc.EVMContract.Address.HexWithPrefix(), 209 sc.FlowToken.Address.HexWithPrefix(), 210 sc.FlowServiceAccount.Address.HexWithPrefix(), 211 )) 212 213 script := fvm.Script(code) 214 215 executionSnapshot, output, err := vm.Run( 216 ctx, 217 script, 218 snapshot) 219 require.NoError(t, err) 220 require.NoError(t, output.Err) 221 222 // TODO: 223 _ = executionSnapshot 224 }) 225 }) 226 }) 227 }) 228 }) 229 } 230 231 // TODO: provide proper contract code 232 func TestBridgedAccountDeploy(t *testing.T) { 233 234 t.Parallel() 235 236 RunWithTestBackend(t, func(backend *testutils.TestBackend) { 237 RunWithTestFlowEVMRootAddress(t, backend, func(rootAddr flow.Address) { 238 tc := GetStorageTestContract(t) 239 RunWithDeployedContract(t, tc, backend, rootAddr, func(testContract *TestContract) { 240 RunWithEOATestAccount(t, backend, rootAddr, func(testAccount *EOATestAccount) { 241 chain := flow.Emulator.Chain() 242 sc := systemcontracts.SystemContractsForChain(chain.ChainID()) 243 244 RunWithNewTestVM(t, chain, func(ctx fvm.Context, vm fvm.VM, snapshot snapshot.SnapshotTree) { 245 246 code := []byte(fmt.Sprintf( 247 ` 248 import EVM from %s 249 import FlowToken from %s 250 251 access(all) 252 fun main(): [UInt8; 20] { 253 let admin = getAuthAccount(%s) 254 .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin)! 255 let minter <- admin.createNewMinter(allowedAmount: 2.34) 256 let vault <- minter.mintTokens(amount: 2.34) 257 destroy minter 258 259 let bridgedAccount <- EVM.createBridgedAccount() 260 bridgedAccount.address().deposit(from: <-vault) 261 262 let address = bridgedAccount.deploy( 263 code: [], 264 gasLimit: 53000, 265 value: EVM.Balance(flow: 1.23) 266 ) 267 destroy bridgedAccount 268 return address.bytes 269 } 270 `, 271 sc.EVMContract.Address.HexWithPrefix(), 272 sc.FlowToken.Address.HexWithPrefix(), 273 sc.FlowServiceAccount.Address.HexWithPrefix(), 274 )) 275 276 script := fvm.Script(code) 277 278 executionSnapshot, output, err := vm.Run( 279 ctx, 280 script, 281 snapshot) 282 require.NoError(t, err) 283 require.NoError(t, output.Err) 284 285 // TODO: 286 _ = executionSnapshot 287 }) 288 }) 289 }) 290 }) 291 }) 292 }