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  }