github.com/onflow/flow-go@v0.33.17/fvm/evm/stdlib/contract_test.go (about)

     1  package stdlib_test
     2  
     3  import (
     4  	"encoding/binary"
     5  	"testing"
     6  
     7  	"github.com/ethereum/go-ethereum/crypto"
     8  	"github.com/onflow/cadence"
     9  	"github.com/onflow/cadence/encoding/json"
    10  	"github.com/onflow/cadence/runtime"
    11  	"github.com/onflow/cadence/runtime/common"
    12  	"github.com/onflow/cadence/runtime/tests/utils"
    13  	coreContracts "github.com/onflow/flow-core-contracts/lib/go/contracts"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/onflow/flow-go/fvm/blueprints"
    18  	"github.com/onflow/flow-go/fvm/environment"
    19  	"github.com/onflow/flow-go/fvm/evm/stdlib"
    20  	. "github.com/onflow/flow-go/fvm/evm/testutils"
    21  	"github.com/onflow/flow-go/fvm/evm/types"
    22  	"github.com/onflow/flow-go/model/flow"
    23  )
    24  
    25  type testContractHandler struct {
    26  	flowTokenAddress  common.Address
    27  	allocateAddress   func() types.Address
    28  	addressIndex      uint64
    29  	accountByAddress  func(types.Address, bool) types.Account
    30  	lastExecutedBlock func() *types.Block
    31  	run               func(tx []byte, coinbase types.Address)
    32  }
    33  
    34  func (t *testContractHandler) FlowTokenAddress() common.Address {
    35  	return t.flowTokenAddress
    36  }
    37  
    38  var _ types.ContractHandler = &testContractHandler{}
    39  
    40  func (t *testContractHandler) AllocateAddress() types.Address {
    41  	if t.allocateAddress == nil {
    42  		t.addressIndex++
    43  		var address types.Address
    44  		binary.LittleEndian.PutUint64(address[:], t.addressIndex)
    45  		return address
    46  	}
    47  	return t.allocateAddress()
    48  }
    49  
    50  func (t *testContractHandler) AccountByAddress(addr types.Address, isAuthorized bool) types.Account {
    51  	if t.accountByAddress == nil {
    52  		panic("unexpected AccountByAddress")
    53  	}
    54  	return t.accountByAddress(addr, isAuthorized)
    55  }
    56  
    57  func (t *testContractHandler) LastExecutedBlock() *types.Block {
    58  	if t.lastExecutedBlock == nil {
    59  		panic("unexpected LastExecutedBlock")
    60  	}
    61  	return t.lastExecutedBlock()
    62  }
    63  
    64  func (t *testContractHandler) Run(tx []byte, coinbase types.Address) {
    65  	if t.run == nil {
    66  		panic("unexpected Run")
    67  	}
    68  	t.run(tx, coinbase)
    69  }
    70  
    71  type testFlowAccount struct {
    72  	address  types.Address
    73  	balance  func() types.Balance
    74  	transfer func(address types.Address, balance types.Balance)
    75  	deposit  func(vault *types.FLOWTokenVault)
    76  	withdraw func(balance types.Balance) *types.FLOWTokenVault
    77  	deploy   func(code types.Code, limit types.GasLimit, balance types.Balance) types.Address
    78  	call     func(address types.Address, data types.Data, limit types.GasLimit, balance types.Balance) types.Data
    79  }
    80  
    81  var _ types.Account = &testFlowAccount{}
    82  
    83  func (t *testFlowAccount) Address() types.Address {
    84  	return t.address
    85  }
    86  
    87  func (t *testFlowAccount) Balance() types.Balance {
    88  	if t.balance == nil {
    89  		return types.Balance(0)
    90  	}
    91  	return t.balance()
    92  }
    93  
    94  func (t *testFlowAccount) Transfer(address types.Address, balance types.Balance) {
    95  	if t.transfer == nil {
    96  		panic("unexpected Transfer")
    97  	}
    98  	t.transfer(address, balance)
    99  }
   100  
   101  func (t *testFlowAccount) Deposit(vault *types.FLOWTokenVault) {
   102  	if t.deposit == nil {
   103  		panic("unexpected Deposit")
   104  	}
   105  	t.deposit(vault)
   106  }
   107  
   108  func (t *testFlowAccount) Withdraw(balance types.Balance) *types.FLOWTokenVault {
   109  	if t.withdraw == nil {
   110  		panic("unexpected Withdraw")
   111  	}
   112  	return t.withdraw(balance)
   113  }
   114  
   115  func (t *testFlowAccount) Deploy(code types.Code, limit types.GasLimit, balance types.Balance) types.Address {
   116  	if t.deploy == nil {
   117  		panic("unexpected Deploy")
   118  	}
   119  	return t.deploy(code, limit, balance)
   120  }
   121  
   122  func (t *testFlowAccount) Call(address types.Address, data types.Data, limit types.GasLimit, balance types.Balance) types.Data {
   123  	if t.call == nil {
   124  		panic("unexpected Call")
   125  	}
   126  	return t.call(address, data, limit, balance)
   127  }
   128  
   129  func deployContracts(
   130  	t *testing.T,
   131  	rt runtime.Runtime,
   132  	contractsAddress flow.Address,
   133  	runtimeInterface *TestRuntimeInterface,
   134  	transactionEnvironment runtime.Environment,
   135  	nextTransactionLocation func() common.TransactionLocation,
   136  	evmAbiOnly bool,
   137  ) {
   138  
   139  	contractsAddressHex := contractsAddress.Hex()
   140  
   141  	contracts := []struct {
   142  		name     string
   143  		code     []byte
   144  		deployTx []byte
   145  	}{
   146  		{
   147  			name: "FungibleToken",
   148  			code: coreContracts.FungibleToken(),
   149  		},
   150  		{
   151  			name: "NonFungibleToken",
   152  			code: coreContracts.NonFungibleToken(),
   153  		},
   154  		{
   155  			name: "MetadataViews",
   156  			code: coreContracts.MetadataViews(
   157  				contractsAddressHex,
   158  				contractsAddressHex,
   159  			),
   160  		},
   161  		{
   162  			name: "FungibleTokenMetadataViews",
   163  			code: coreContracts.FungibleTokenMetadataViews(
   164  				contractsAddressHex,
   165  				contractsAddressHex,
   166  			),
   167  		},
   168  		{
   169  			name: "ViewResolver",
   170  			code: coreContracts.ViewResolver(),
   171  		},
   172  		{
   173  			name: "FlowToken",
   174  			code: coreContracts.FlowToken(
   175  				contractsAddressHex,
   176  				contractsAddressHex,
   177  				contractsAddressHex,
   178  			),
   179  			deployTx: []byte(`
   180                transaction(name: String, code: String) {
   181                  prepare(signer: AuthAccount) {
   182                    signer.contracts.add(name: name, code: code.utf8, signer)
   183                  }
   184                }
   185              `),
   186  		},
   187  		{
   188  			name: stdlib.ContractName,
   189  			code: stdlib.ContractCode(contractsAddress, evmAbiOnly),
   190  		},
   191  	}
   192  
   193  	for _, contract := range contracts {
   194  
   195  		deployTx := contract.deployTx
   196  		if len(deployTx) == 0 {
   197  			deployTx = blueprints.DeployContractTransactionTemplate
   198  		}
   199  
   200  		err := rt.ExecuteTransaction(
   201  			runtime.Script{
   202  				Source: deployTx,
   203  				Arguments: EncodeArgs([]cadence.Value{
   204  					cadence.String(contract.name),
   205  					cadence.String(contract.code),
   206  				}),
   207  			},
   208  			runtime.Context{
   209  				Interface:   runtimeInterface,
   210  				Environment: transactionEnvironment,
   211  				Location:    nextTransactionLocation(),
   212  			},
   213  		)
   214  		require.NoError(t, err)
   215  	}
   216  
   217  }
   218  
   219  func newEVMTransactionEnvironment(handler types.ContractHandler, service flow.Address) runtime.Environment {
   220  	transactionEnvironment := runtime.NewBaseInterpreterEnvironment(runtime.Config{})
   221  
   222  	stdlib.SetupEnvironment(
   223  		transactionEnvironment,
   224  		handler,
   225  		service,
   226  	)
   227  
   228  	return transactionEnvironment
   229  }
   230  
   231  func newEVMScriptEnvironment(handler types.ContractHandler, service flow.Address) runtime.Environment {
   232  	scriptEnvironment := runtime.NewScriptInterpreterEnvironment(runtime.Config{})
   233  
   234  	stdlib.SetupEnvironment(
   235  		scriptEnvironment,
   236  		handler,
   237  		service,
   238  	)
   239  
   240  	return scriptEnvironment
   241  }
   242  
   243  func TestEVMEncodeABI(t *testing.T) {
   244  
   245  	t.Parallel()
   246  
   247  	handler := &testContractHandler{}
   248  
   249  	contractsAddress := flow.BytesToAddress([]byte{0x1})
   250  
   251  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
   252  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
   253  
   254  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
   255  
   256  	script := []byte(`
   257        import EVM from 0x1
   258  
   259        access(all)
   260        fun main(): [UInt8] {
   261          return EVM.encodeABI(["John Doe", UInt64(33), false])
   262        }
   263  	`)
   264  
   265  	accountCodes := map[common.Location][]byte{}
   266  	var events []cadence.Event
   267  
   268  	computation := uint(0)
   269  	runtimeInterface := &TestRuntimeInterface{
   270  		Storage: NewTestLedger(nil, nil),
   271  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
   272  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
   273  		},
   274  		OnResolveLocation: SingleIdentifierLocationResolver(t),
   275  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
   276  			accountCodes[location] = code
   277  			return nil
   278  		},
   279  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
   280  			code = accountCodes[location]
   281  			return code, nil
   282  		},
   283  		OnEmitEvent: func(event cadence.Event) error {
   284  			events = append(events, event)
   285  			return nil
   286  		},
   287  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
   288  			return json.Decode(nil, b)
   289  		},
   290  		OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error {
   291  			if compKind == environment.ComputationKindEVMEncodeABI {
   292  				computation += intensity
   293  			}
   294  			return nil
   295  		},
   296  	}
   297  
   298  	nextTransactionLocation := NewTransactionLocationGenerator()
   299  	nextScriptLocation := NewScriptLocationGenerator()
   300  
   301  	// Deploy contracts
   302  
   303  	deployContracts(
   304  		t,
   305  		rt,
   306  		contractsAddress,
   307  		runtimeInterface,
   308  		transactionEnvironment,
   309  		nextTransactionLocation,
   310  		true,
   311  	)
   312  
   313  	// Run script
   314  
   315  	result, err := rt.ExecuteScript(
   316  		runtime.Script{
   317  			Source:    script,
   318  			Arguments: [][]byte{},
   319  		},
   320  		runtime.Context{
   321  			Interface:   runtimeInterface,
   322  			Environment: scriptEnvironment,
   323  			Location:    nextScriptLocation(),
   324  		},
   325  	)
   326  	require.NoError(t, err)
   327  
   328  	abiBytes := []byte{
   329  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   330  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   331  		0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   332  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   333  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   334  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   335  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   336  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   337  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   338  		0x0, 0x8, 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x44, 0x6f, 0x65, 0x0, 0x0,
   339  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   340  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   341  	}
   342  	cdcBytes := make([]cadence.Value, 0)
   343  	for _, bt := range abiBytes {
   344  		cdcBytes = append(cdcBytes, cadence.UInt8(bt))
   345  	}
   346  	encodedABI := cadence.NewArray(
   347  		cdcBytes,
   348  	).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type))
   349  
   350  	assert.Equal(t,
   351  		encodedABI,
   352  		result,
   353  	)
   354  	assert.Equal(t, computation, uint(len(cdcBytes)))
   355  }
   356  
   357  func TestEVMEncodeABIComputation(t *testing.T) {
   358  
   359  	t.Parallel()
   360  
   361  	handler := &testContractHandler{}
   362  
   363  	contractsAddress := flow.BytesToAddress([]byte{0x1})
   364  
   365  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
   366  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
   367  
   368  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
   369  
   370  	script := []byte(`
   371        import EVM from 0x1
   372  
   373        access(all)
   374        fun main(): [UInt8] {
   375          let address = EVM.EVMAddress(
   376            bytes: [
   377              122, 88, 192, 190, 114, 190, 33, 139, 65, 198,
   378              8, 183, 254, 124, 91, 182, 48, 115, 108, 113
   379            ]
   380          )
   381          let arr: [UInt8] = [1, 2, 3, 4, 5]
   382  
   383          return EVM.encodeABI([
   384            "John Doe",
   385            UInt64(33),
   386            false,
   387            address,
   388            [arr],
   389            ["one", "two", "three"]
   390          ])
   391        }
   392  	`)
   393  
   394  	accountCodes := map[common.Location][]byte{}
   395  	var events []cadence.Event
   396  
   397  	computation := uint(0)
   398  	runtimeInterface := &TestRuntimeInterface{
   399  		Storage: NewTestLedger(nil, nil),
   400  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
   401  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
   402  		},
   403  		OnResolveLocation: SingleIdentifierLocationResolver(t),
   404  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
   405  			accountCodes[location] = code
   406  			return nil
   407  		},
   408  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
   409  			code = accountCodes[location]
   410  			return code, nil
   411  		},
   412  		OnEmitEvent: func(event cadence.Event) error {
   413  			events = append(events, event)
   414  			return nil
   415  		},
   416  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
   417  			return json.Decode(nil, b)
   418  		},
   419  		OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error {
   420  			if compKind == environment.ComputationKindEVMEncodeABI {
   421  				computation += intensity
   422  			}
   423  			return nil
   424  		},
   425  	}
   426  
   427  	nextTransactionLocation := NewTransactionLocationGenerator()
   428  	nextScriptLocation := NewScriptLocationGenerator()
   429  
   430  	// Deploy contracts
   431  
   432  	deployContracts(
   433  		t,
   434  		rt,
   435  		contractsAddress,
   436  		runtimeInterface,
   437  		transactionEnvironment,
   438  		nextTransactionLocation,
   439  		true,
   440  	)
   441  
   442  	// Run script
   443  
   444  	result, err := rt.ExecuteScript(
   445  		runtime.Script{
   446  			Source:    script,
   447  			Arguments: [][]byte{},
   448  		},
   449  		runtime.Context{
   450  			Interface:   runtimeInterface,
   451  			Environment: scriptEnvironment,
   452  			Location:    nextScriptLocation(),
   453  		},
   454  	)
   455  	require.NoError(t, err)
   456  
   457  	cdcBytes, ok := result.(cadence.Array)
   458  	require.True(t, ok)
   459  	// computation & len(cdcBytes.Values) is equal to 832
   460  	assert.Equal(t, computation, uint(len(cdcBytes.Values)))
   461  }
   462  
   463  func TestEVMEncodeABIComputationEmptyDynamicVariables(t *testing.T) {
   464  
   465  	t.Parallel()
   466  
   467  	handler := &testContractHandler{}
   468  
   469  	contractsAddress := flow.BytesToAddress([]byte{0x1})
   470  
   471  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
   472  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
   473  
   474  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
   475  
   476  	script := []byte(`
   477        import EVM from 0x1
   478  
   479        access(all)
   480        fun main(): [UInt8] {
   481          return EVM.encodeABI([
   482            "",
   483            [[""], [] as [String]],
   484            [] as [UInt8],
   485            ["", "", ""]
   486          ])
   487        }
   488  	`)
   489  
   490  	accountCodes := map[common.Location][]byte{}
   491  	var events []cadence.Event
   492  
   493  	computation := uint(0)
   494  	runtimeInterface := &TestRuntimeInterface{
   495  		Storage: NewTestLedger(nil, nil),
   496  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
   497  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
   498  		},
   499  		OnResolveLocation: SingleIdentifierLocationResolver(t),
   500  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
   501  			accountCodes[location] = code
   502  			return nil
   503  		},
   504  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
   505  			code = accountCodes[location]
   506  			return code, nil
   507  		},
   508  		OnEmitEvent: func(event cadence.Event) error {
   509  			events = append(events, event)
   510  			return nil
   511  		},
   512  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
   513  			return json.Decode(nil, b)
   514  		},
   515  		OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error {
   516  			if compKind == environment.ComputationKindEVMEncodeABI {
   517  				computation += intensity
   518  			}
   519  			return nil
   520  		},
   521  	}
   522  
   523  	nextTransactionLocation := NewTransactionLocationGenerator()
   524  	nextScriptLocation := NewScriptLocationGenerator()
   525  
   526  	// Deploy contracts
   527  
   528  	deployContracts(
   529  		t,
   530  		rt,
   531  		contractsAddress,
   532  		runtimeInterface,
   533  		transactionEnvironment,
   534  		nextTransactionLocation,
   535  		true,
   536  	)
   537  
   538  	// Run script
   539  
   540  	result, err := rt.ExecuteScript(
   541  		runtime.Script{
   542  			Source:    script,
   543  			Arguments: [][]byte{},
   544  		},
   545  		runtime.Context{
   546  			Interface:   runtimeInterface,
   547  			Environment: scriptEnvironment,
   548  			Location:    nextScriptLocation(),
   549  		},
   550  	)
   551  	require.NoError(t, err)
   552  
   553  	cdcBytes, ok := result.(cadence.Array)
   554  	require.True(t, ok)
   555  	// computation & len(cdcBytes.Values) is equal to 832
   556  	assert.Equal(t, computation, uint(len(cdcBytes.Values)))
   557  }
   558  
   559  func TestEVMEncodeABIComputationDynamicVariablesAboveChunkSize(t *testing.T) {
   560  
   561  	t.Parallel()
   562  
   563  	handler := &testContractHandler{}
   564  
   565  	contractsAddress := flow.BytesToAddress([]byte{0x1})
   566  
   567  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
   568  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
   569  
   570  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
   571  
   572  	script := []byte(`
   573        import EVM from 0x1
   574  
   575        access(all)
   576        fun main(): [UInt8] {
   577          let str = "abcdefghijklmnopqrstuvwxyz"
   578          let arr: [UInt64] = [
   579            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
   580            20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
   581            37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53
   582          ]
   583  
   584          return EVM.encodeABI([
   585            str,
   586            str.concat(str).concat(str),
   587            [[str]],
   588            arr,
   589            [arr],
   590            arr.concat(arr).concat(arr)
   591          ])
   592        }
   593  	`)
   594  
   595  	accountCodes := map[common.Location][]byte{}
   596  	var events []cadence.Event
   597  
   598  	computation := uint(0)
   599  	runtimeInterface := &TestRuntimeInterface{
   600  		Storage: NewTestLedger(nil, nil),
   601  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
   602  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
   603  		},
   604  		OnResolveLocation: SingleIdentifierLocationResolver(t),
   605  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
   606  			accountCodes[location] = code
   607  			return nil
   608  		},
   609  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
   610  			code = accountCodes[location]
   611  			return code, nil
   612  		},
   613  		OnEmitEvent: func(event cadence.Event) error {
   614  			events = append(events, event)
   615  			return nil
   616  		},
   617  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
   618  			return json.Decode(nil, b)
   619  		},
   620  		OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error {
   621  			if compKind == environment.ComputationKindEVMEncodeABI {
   622  				computation += intensity
   623  			}
   624  			return nil
   625  		},
   626  	}
   627  
   628  	nextTransactionLocation := NewTransactionLocationGenerator()
   629  	nextScriptLocation := NewScriptLocationGenerator()
   630  
   631  	// Deploy contracts
   632  
   633  	deployContracts(
   634  		t,
   635  		rt,
   636  		contractsAddress,
   637  		runtimeInterface,
   638  		transactionEnvironment,
   639  		nextTransactionLocation,
   640  		true,
   641  	)
   642  
   643  	// Run script
   644  
   645  	result, err := rt.ExecuteScript(
   646  		runtime.Script{
   647  			Source:    script,
   648  			Arguments: [][]byte{},
   649  		},
   650  		runtime.Context{
   651  			Interface:   runtimeInterface,
   652  			Environment: scriptEnvironment,
   653  			Location:    nextScriptLocation(),
   654  		},
   655  	)
   656  	require.NoError(t, err)
   657  
   658  	cdcBytes, ok := result.(cadence.Array)
   659  	require.True(t, ok)
   660  	// computation & len(cdcBytes.Values) is equal to 832
   661  	assert.Equal(t, computation, uint(len(cdcBytes.Values)))
   662  }
   663  
   664  func TestEVMDecodeABI(t *testing.T) {
   665  
   666  	t.Parallel()
   667  
   668  	handler := &testContractHandler{}
   669  
   670  	contractsAddress := flow.BytesToAddress([]byte{0x1})
   671  
   672  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
   673  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
   674  
   675  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
   676  
   677  	script := []byte(`
   678        import EVM from 0x1
   679  
   680        access(all)
   681        fun main(data: [UInt8]): Bool {
   682          let types = [Type<String>(), Type<UInt64>(), Type<Bool>()]
   683          let values = EVM.decodeABI(types: types, data: data)
   684  
   685          assert(values.length == 3)
   686          assert((values[0] as! String) == "John Doe")
   687          assert((values[1] as! UInt64) == UInt64(33))
   688          assert((values[2] as! Bool) == false)
   689  
   690          return true
   691        }
   692  	`)
   693  
   694  	accountCodes := map[common.Location][]byte{}
   695  	var events []cadence.Event
   696  
   697  	computation := uint(0)
   698  	runtimeInterface := &TestRuntimeInterface{
   699  		Storage: NewTestLedger(nil, nil),
   700  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
   701  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
   702  		},
   703  		OnResolveLocation: SingleIdentifierLocationResolver(t),
   704  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
   705  			accountCodes[location] = code
   706  			return nil
   707  		},
   708  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
   709  			code = accountCodes[location]
   710  			return code, nil
   711  		},
   712  		OnEmitEvent: func(event cadence.Event) error {
   713  			events = append(events, event)
   714  			return nil
   715  		},
   716  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
   717  			return json.Decode(nil, b)
   718  		},
   719  		OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error {
   720  			if compKind == environment.ComputationKindEVMDecodeABI {
   721  				computation += intensity
   722  			}
   723  			return nil
   724  		},
   725  	}
   726  
   727  	nextTransactionLocation := NewTransactionLocationGenerator()
   728  	nextScriptLocation := NewScriptLocationGenerator()
   729  
   730  	// Deploy contracts
   731  
   732  	deployContracts(
   733  		t,
   734  		rt,
   735  		contractsAddress,
   736  		runtimeInterface,
   737  		transactionEnvironment,
   738  		nextTransactionLocation,
   739  		true,
   740  	)
   741  
   742  	// Run script
   743  	abiBytes := []byte{
   744  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   745  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   746  		0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   747  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   748  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   749  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   750  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   751  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   752  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   753  		0x0, 0x8, 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x44, 0x6f, 0x65, 0x0, 0x0,
   754  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   755  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   756  	}
   757  	cdcBytes := make([]cadence.Value, 0)
   758  	for _, bt := range abiBytes {
   759  		cdcBytes = append(cdcBytes, cadence.UInt8(bt))
   760  	}
   761  	encodedABI := cadence.NewArray(
   762  		cdcBytes,
   763  	).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type))
   764  
   765  	result, err := rt.ExecuteScript(
   766  		runtime.Script{
   767  			Source: script,
   768  			Arguments: EncodeArgs([]cadence.Value{
   769  				encodedABI,
   770  			}),
   771  		},
   772  		runtime.Context{
   773  			Interface:   runtimeInterface,
   774  			Environment: scriptEnvironment,
   775  			Location:    nextScriptLocation(),
   776  		},
   777  	)
   778  	require.NoError(t, err)
   779  
   780  	assert.Equal(t, cadence.NewBool(true), result)
   781  	assert.Equal(t, computation, uint(len(cdcBytes)))
   782  }
   783  
   784  func TestEVMDecodeABIComputation(t *testing.T) {
   785  
   786  	t.Parallel()
   787  
   788  	handler := &testContractHandler{}
   789  
   790  	contractsAddress := flow.BytesToAddress([]byte{0x1})
   791  
   792  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
   793  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
   794  
   795  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
   796  
   797  	script := []byte(`
   798        import EVM from 0x1
   799  
   800        access(all)
   801        fun main(): [UInt8] {
   802          let address = EVM.EVMAddress(
   803            bytes: [
   804              122, 88, 192, 190, 114, 190, 33, 139, 65, 198,
   805              8, 183, 254, 124, 91, 182, 48, 115, 108, 113
   806            ]
   807          )
   808          let arr: [UInt8] = [1, 2, 3, 4, 5]
   809  
   810          let data = EVM.encodeABI([
   811            "John Doe",
   812            UInt64(33),
   813            true,
   814            address,
   815            [arr],
   816            ["one", "two", "three"]
   817          ])
   818  
   819          let types = [
   820            Type<String>(), Type<UInt64>(), Type<Bool>(), Type<EVM.EVMAddress>(),
   821            Type<[[UInt8]]>(), Type<[String]>()
   822          ]
   823          let values = EVM.decodeABI(types: types, data: data)
   824  
   825          return data
   826        }
   827  	`)
   828  
   829  	accountCodes := map[common.Location][]byte{}
   830  	var events []cadence.Event
   831  
   832  	computation := uint(0)
   833  	runtimeInterface := &TestRuntimeInterface{
   834  		Storage: NewTestLedger(nil, nil),
   835  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
   836  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
   837  		},
   838  		OnResolveLocation: SingleIdentifierLocationResolver(t),
   839  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
   840  			accountCodes[location] = code
   841  			return nil
   842  		},
   843  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
   844  			code = accountCodes[location]
   845  			return code, nil
   846  		},
   847  		OnEmitEvent: func(event cadence.Event) error {
   848  			events = append(events, event)
   849  			return nil
   850  		},
   851  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
   852  			return json.Decode(nil, b)
   853  		},
   854  		OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error {
   855  			if compKind == environment.ComputationKindEVMDecodeABI {
   856  				computation += intensity
   857  			}
   858  			return nil
   859  		},
   860  	}
   861  
   862  	nextTransactionLocation := NewTransactionLocationGenerator()
   863  	nextScriptLocation := NewScriptLocationGenerator()
   864  
   865  	// Deploy contracts
   866  
   867  	deployContracts(
   868  		t,
   869  		rt,
   870  		contractsAddress,
   871  		runtimeInterface,
   872  		transactionEnvironment,
   873  		nextTransactionLocation,
   874  		true,
   875  	)
   876  
   877  	// Run script
   878  
   879  	result, err := rt.ExecuteScript(
   880  		runtime.Script{
   881  			Source:    script,
   882  			Arguments: [][]byte{},
   883  		},
   884  		runtime.Context{
   885  			Interface:   runtimeInterface,
   886  			Environment: scriptEnvironment,
   887  			Location:    nextScriptLocation(),
   888  		},
   889  	)
   890  	require.NoError(t, err)
   891  
   892  	cdcBytes, ok := result.(cadence.Array)
   893  	require.True(t, ok)
   894  	// computation & len(cdcBytes.Values) is equal to 832
   895  	assert.Equal(t, computation, uint(len(cdcBytes.Values)))
   896  }
   897  
   898  func TestEVMEncodeDecodeABIRoundtrip(t *testing.T) {
   899  
   900  	t.Parallel()
   901  
   902  	handler := &testContractHandler{}
   903  
   904  	contractsAddress := flow.BytesToAddress([]byte{0x1})
   905  
   906  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
   907  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
   908  
   909  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
   910  
   911  	script := []byte(`
   912        import EVM from 0x1
   913  
   914        access(all)
   915        fun main(): Bool {
   916          // Check EVM.EVMAddress encode/decode
   917          // bytes for address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71
   918          let address = EVM.EVMAddress(
   919            bytes: [
   920              122, 88, 192, 190, 114, 190, 33, 139, 65, 198,
   921              8, 183, 254, 124, 91, 182, 48, 115, 108, 113
   922            ]
   923          )
   924          var data = EVM.encodeABI([address])
   925          var values = EVM.decodeABI(types: [Type<EVM.EVMAddress>()], data: data)
   926          assert(values.length == 1)
   927          assert((values[0] as! EVM.EVMAddress).bytes == address.bytes)
   928  
   929          // Check String encode/decode
   930          data = EVM.encodeABI(["John Doe", ""])
   931          values = EVM.decodeABI(types: [Type<String>(), Type<String>()], data: data)
   932          assert((values[0] as! String) == "John Doe")
   933          assert((values[1] as! String) == "")
   934  
   935          // Check Bool encode/decode
   936          data = EVM.encodeABI([true, false])
   937          values = EVM.decodeABI(types: [Type<Bool>(), Type<Bool>()], data: data)
   938          assert((values[0] as! Bool) == true)
   939          assert((values[1] as! Bool) == false)
   940  
   941          // Check UInt*/Int* encode/decode
   942          data = EVM.encodeABI([
   943            UInt8(33),
   944            UInt16(33),
   945            UInt32(33),
   946            UInt64(33),
   947            UInt128(33),
   948            UInt256(33),
   949            Int8(-33),
   950            Int16(-33),
   951            Int32(-33),
   952            Int64(-33),
   953            Int128(-33),
   954            Int256(-33)
   955          ])
   956          values = EVM.decodeABI(
   957            types: [
   958              Type<UInt8>(),
   959              Type<UInt16>(),
   960              Type<UInt32>(),
   961              Type<UInt64>(),
   962              Type<UInt128>(),
   963              Type<UInt256>(),
   964              Type<Int8>(),
   965              Type<Int16>(),
   966              Type<Int32>(),
   967              Type<Int64>(),
   968              Type<Int128>(),
   969              Type<Int256>()
   970            ],
   971            data: data
   972          )
   973          assert((values[0] as! UInt8) == 33)
   974          assert((values[1] as! UInt16) == 33)
   975          assert((values[2] as! UInt32) == 33)
   976          assert((values[3] as! UInt64) == 33)
   977          assert((values[4] as! UInt128) == 33)
   978          assert((values[5] as! UInt256) == 33)
   979          assert((values[6] as! Int8) == -33)
   980          assert((values[7] as! Int16) == -33)
   981          assert((values[8] as! Int32) == -33)
   982          assert((values[9] as! Int64) == -33)
   983          assert((values[10] as! Int128) == -33)
   984          assert((values[11] as! Int256) == -33)
   985  
   986          // Check variable-size array of leaf types encode/decode
   987          data = EVM.encodeABI([
   988            ["one", "two"],
   989            [true, false],
   990            [5, 10] as [UInt8],
   991            [5, 10] as [UInt16],
   992            [5, 10] as [UInt32],
   993            [5, 10] as [UInt64],
   994            [5, 10] as [UInt128],
   995            [5, 10] as [UInt256],
   996            [-5, -10] as [Int8],
   997            [-5, -10] as [Int16],
   998            [-5, -10] as [Int32],
   999            [-5, -10] as [Int64],
  1000            [-5, -10] as [Int128],
  1001            [-5, -10] as [Int256],
  1002            [address] as [EVM.EVMAddress]
  1003          ])
  1004          values = EVM.decodeABI(
  1005            types: [
  1006              Type<[String]>(),
  1007              Type<[Bool]>(),
  1008              Type<[UInt8]>(),
  1009              Type<[UInt16]>(),
  1010              Type<[UInt32]>(),
  1011              Type<[UInt64]>(),
  1012              Type<[UInt128]>(),
  1013              Type<[UInt256]>(),
  1014              Type<[Int8]>(),
  1015              Type<[Int16]>(),
  1016              Type<[Int32]>(),
  1017              Type<[Int64]>(),
  1018              Type<[Int128]>(),
  1019              Type<[Int256]>(),
  1020              Type<[EVM.EVMAddress]>()
  1021            ],
  1022            data: data
  1023          )
  1024          assert((values[0] as! [String]) == ["one", "two"])
  1025          assert((values[1] as! [Bool]) == [true, false])
  1026          assert((values[2] as! [UInt8]) == [5, 10])
  1027          assert((values[3] as! [UInt16]) == [5, 10])
  1028          assert((values[4] as! [UInt32]) == [5, 10])
  1029          assert((values[5] as! [UInt64]) == [5, 10])
  1030          assert((values[6] as! [UInt128]) == [5, 10])
  1031          assert((values[7] as! [UInt256]) == [5, 10])
  1032          assert((values[8] as! [Int8]) == [-5, -10])
  1033          assert((values[9] as! [Int16]) == [-5, -10])
  1034          assert((values[10] as! [Int32]) == [-5, -10])
  1035          assert((values[11] as! [Int64]) == [-5, -10])
  1036          assert((values[12] as! [Int128]) == [-5, -10])
  1037          assert((values[13] as! [Int256]) == [-5, -10])
  1038          assert((values[14] as! [EVM.EVMAddress])[0].bytes == [address][0].bytes)
  1039  
  1040          // Check constant-size array of leaf types encode/decode
  1041          data = EVM.encodeABI([
  1042            ["one", "two"] as [String; 2],
  1043            [true, false] as [Bool; 2],
  1044            [5, 10] as [UInt8; 2],
  1045            [5, 10] as [UInt16; 2],
  1046            [5, 10] as [UInt32; 2],
  1047            [5, 10] as [UInt64; 2],
  1048            [5, 10] as [UInt128; 2],
  1049            [5, 10] as [UInt256; 2],
  1050            [-5, -10] as [Int8; 2],
  1051            [-5, -10] as [Int16; 2],
  1052            [-5, -10] as [Int32; 2],
  1053            [-5, -10] as [Int64; 2],
  1054            [-5, -10] as [Int128; 2],
  1055            [-5, -10] as [Int256; 2],
  1056            [address] as [EVM.EVMAddress; 1]
  1057          ])
  1058          values = EVM.decodeABI(
  1059            types: [
  1060              Type<[String; 2]>(),
  1061              Type<[Bool; 2]>(),
  1062              Type<[UInt8; 2]>(),
  1063              Type<[UInt16; 2]>(),
  1064              Type<[UInt32; 2]>(),
  1065              Type<[UInt64; 2]>(),
  1066              Type<[UInt128; 2]>(),
  1067              Type<[UInt256; 2]>(),
  1068              Type<[Int8; 2]>(),
  1069              Type<[Int16; 2]>(),
  1070              Type<[Int32; 2]>(),
  1071              Type<[Int64; 2]>(),
  1072              Type<[Int128; 2]>(),
  1073              Type<[Int256; 2]>(),
  1074              Type<[EVM.EVMAddress; 1]>()
  1075            ],
  1076            data: data
  1077          )
  1078          assert((values[0] as! [String; 2]) == ["one", "two"])
  1079          assert((values[1] as! [Bool; 2]) == [true, false])
  1080          assert((values[2] as! [UInt8; 2]) == [5, 10])
  1081          assert((values[3] as! [UInt16; 2]) == [5, 10])
  1082          assert((values[4] as! [UInt32; 2]) == [5, 10])
  1083          assert((values[5] as! [UInt64; 2]) == [5, 10])
  1084          assert((values[6] as! [UInt128; 2]) == [5, 10])
  1085          assert((values[7] as! [UInt256; 2]) == [5, 10])
  1086          assert((values[8] as! [Int8; 2]) == [-5, -10])
  1087          assert((values[9] as! [Int16; 2]) == [-5, -10])
  1088          assert((values[10] as! [Int32; 2]) == [-5, -10])
  1089          assert((values[11] as! [Int64; 2]) == [-5, -10])
  1090          assert((values[12] as! [Int128; 2]) == [-5, -10])
  1091          assert((values[13] as! [Int256; 2]) == [-5, -10])
  1092          assert((values[14] as! [EVM.EVMAddress; 1])[0].bytes == [address][0].bytes)
  1093  
  1094          // Check partial decoding of encoded data
  1095          data = EVM.encodeABI(["Peter", UInt64(9999)])
  1096          values = EVM.decodeABI(types: [Type<String>()], data: data)
  1097          assert(values.length == 1)
  1098          assert((values[0] as! String) == "Peter")
  1099  
  1100          // Check nested arrays of leaf values
  1101          data = EVM.encodeABI([[["Foo", "Bar"], ["Baz", "Qux"]]])
  1102          values = EVM.decodeABI(types: [Type<[[String]]>()], data: data)
  1103          assert(values.length == 1)
  1104          assert((values[0] as! [[String]]) == [["Foo", "Bar"], ["Baz", "Qux"]])
  1105  
  1106          return true
  1107        }
  1108  	`)
  1109  
  1110  	accountCodes := map[common.Location][]byte{}
  1111  	var events []cadence.Event
  1112  
  1113  	runtimeInterface := &TestRuntimeInterface{
  1114  		Storage: NewTestLedger(nil, nil),
  1115  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1116  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1117  		},
  1118  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  1119  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1120  			accountCodes[location] = code
  1121  			return nil
  1122  		},
  1123  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1124  			code = accountCodes[location]
  1125  			return code, nil
  1126  		},
  1127  		OnEmitEvent: func(event cadence.Event) error {
  1128  			events = append(events, event)
  1129  			return nil
  1130  		},
  1131  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1132  			return json.Decode(nil, b)
  1133  		},
  1134  	}
  1135  
  1136  	nextTransactionLocation := NewTransactionLocationGenerator()
  1137  	nextScriptLocation := NewScriptLocationGenerator()
  1138  
  1139  	// Deploy contracts
  1140  
  1141  	deployContracts(
  1142  		t,
  1143  		rt,
  1144  		contractsAddress,
  1145  		runtimeInterface,
  1146  		transactionEnvironment,
  1147  		nextTransactionLocation,
  1148  		true,
  1149  	)
  1150  
  1151  	// Run script
  1152  
  1153  	result, err := rt.ExecuteScript(
  1154  		runtime.Script{
  1155  			Source:    script,
  1156  			Arguments: [][]byte{},
  1157  		},
  1158  		runtime.Context{
  1159  			Interface:   runtimeInterface,
  1160  			Environment: scriptEnvironment,
  1161  			Location:    nextScriptLocation(),
  1162  		},
  1163  	)
  1164  	require.NoError(t, err)
  1165  
  1166  	assert.Equal(t,
  1167  		cadence.Bool(true),
  1168  		result,
  1169  	)
  1170  }
  1171  
  1172  func TestEVMEncodeDecodeABIErrors(t *testing.T) {
  1173  
  1174  	t.Parallel()
  1175  
  1176  	t.Run("encodeABI with unsupported Address type", func(t *testing.T) {
  1177  
  1178  		t.Parallel()
  1179  
  1180  		handler := &testContractHandler{}
  1181  
  1182  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1183  
  1184  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1185  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1186  
  1187  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1188  
  1189  		accountCodes := map[common.Location][]byte{}
  1190  		var events []cadence.Event
  1191  
  1192  		runtimeInterface := &TestRuntimeInterface{
  1193  			Storage: NewTestLedger(nil, nil),
  1194  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1195  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1196  			},
  1197  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1198  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1199  				accountCodes[location] = code
  1200  				return nil
  1201  			},
  1202  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1203  				code = accountCodes[location]
  1204  				return code, nil
  1205  			},
  1206  			OnEmitEvent: func(event cadence.Event) error {
  1207  				events = append(events, event)
  1208  				return nil
  1209  			},
  1210  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1211  				return json.Decode(nil, b)
  1212  			},
  1213  		}
  1214  
  1215  		nextTransactionLocation := NewTransactionLocationGenerator()
  1216  		nextScriptLocation := NewScriptLocationGenerator()
  1217  
  1218  		// Deploy contracts
  1219  
  1220  		deployContracts(
  1221  			t,
  1222  			rt,
  1223  			contractsAddress,
  1224  			runtimeInterface,
  1225  			transactionEnvironment,
  1226  			nextTransactionLocation,
  1227  			true,
  1228  		)
  1229  
  1230  		// Run script
  1231  
  1232  		script := []byte(`
  1233            import EVM from 0x1
  1234  
  1235            access(all)
  1236            fun main(): Bool {
  1237              let address: Address = 0x045a1763c93006ca
  1238              let data = EVM.encodeABI([address])
  1239  
  1240              return true
  1241            }
  1242  		`)
  1243  
  1244  		_, err := rt.ExecuteScript(
  1245  			runtime.Script{
  1246  				Source:    script,
  1247  				Arguments: [][]byte{},
  1248  			},
  1249  			runtime.Context{
  1250  				Interface:   runtimeInterface,
  1251  				Environment: scriptEnvironment,
  1252  				Location:    nextScriptLocation(),
  1253  			},
  1254  		)
  1255  		utils.RequireError(t, err)
  1256  		assert.ErrorContains(
  1257  			t,
  1258  			err,
  1259  			"failed to ABI encode value of type Address",
  1260  		)
  1261  	})
  1262  
  1263  	t.Run("encodeABI with unsupported fixed-point number type", func(t *testing.T) {
  1264  
  1265  		t.Parallel()
  1266  
  1267  		handler := &testContractHandler{}
  1268  
  1269  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1270  
  1271  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1272  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1273  
  1274  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1275  
  1276  		accountCodes := map[common.Location][]byte{}
  1277  		var events []cadence.Event
  1278  
  1279  		runtimeInterface := &TestRuntimeInterface{
  1280  			Storage: NewTestLedger(nil, nil),
  1281  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1282  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1283  			},
  1284  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1285  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1286  				accountCodes[location] = code
  1287  				return nil
  1288  			},
  1289  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1290  				code = accountCodes[location]
  1291  				return code, nil
  1292  			},
  1293  			OnEmitEvent: func(event cadence.Event) error {
  1294  				events = append(events, event)
  1295  				return nil
  1296  			},
  1297  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1298  				return json.Decode(nil, b)
  1299  			},
  1300  		}
  1301  
  1302  		nextTransactionLocation := NewTransactionLocationGenerator()
  1303  		nextScriptLocation := NewScriptLocationGenerator()
  1304  
  1305  		// Deploy contracts
  1306  
  1307  		deployContracts(
  1308  			t,
  1309  			rt,
  1310  			contractsAddress,
  1311  			runtimeInterface,
  1312  			transactionEnvironment,
  1313  			nextTransactionLocation,
  1314  			true,
  1315  		)
  1316  
  1317  		// Run script
  1318  
  1319  		script := []byte(`
  1320            import EVM from 0x1
  1321  
  1322            access(all)
  1323            fun main(): Bool {
  1324              let data = EVM.encodeABI([0.2])
  1325  
  1326              return true
  1327            }
  1328  		`)
  1329  
  1330  		_, err := rt.ExecuteScript(
  1331  			runtime.Script{
  1332  				Source:    script,
  1333  				Arguments: [][]byte{},
  1334  			},
  1335  			runtime.Context{
  1336  				Interface:   runtimeInterface,
  1337  				Environment: scriptEnvironment,
  1338  				Location:    nextScriptLocation(),
  1339  			},
  1340  		)
  1341  		utils.RequireError(t, err)
  1342  		assert.ErrorContains(
  1343  			t,
  1344  			err,
  1345  			"failed to ABI encode value of type UFix64",
  1346  		)
  1347  	})
  1348  
  1349  	t.Run("encodeABI with unsupported dictionary type", func(t *testing.T) {
  1350  
  1351  		t.Parallel()
  1352  
  1353  		handler := &testContractHandler{}
  1354  
  1355  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1356  
  1357  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1358  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1359  
  1360  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1361  
  1362  		accountCodes := map[common.Location][]byte{}
  1363  		var events []cadence.Event
  1364  
  1365  		runtimeInterface := &TestRuntimeInterface{
  1366  			Storage: NewTestLedger(nil, nil),
  1367  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1368  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1369  			},
  1370  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1371  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1372  				accountCodes[location] = code
  1373  				return nil
  1374  			},
  1375  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1376  				code = accountCodes[location]
  1377  				return code, nil
  1378  			},
  1379  			OnEmitEvent: func(event cadence.Event) error {
  1380  				events = append(events, event)
  1381  				return nil
  1382  			},
  1383  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1384  				return json.Decode(nil, b)
  1385  			},
  1386  		}
  1387  
  1388  		nextTransactionLocation := NewTransactionLocationGenerator()
  1389  		nextScriptLocation := NewScriptLocationGenerator()
  1390  
  1391  		// Deploy contracts
  1392  
  1393  		deployContracts(
  1394  			t,
  1395  			rt,
  1396  			contractsAddress,
  1397  			runtimeInterface,
  1398  			transactionEnvironment,
  1399  			nextTransactionLocation,
  1400  			true,
  1401  		)
  1402  
  1403  		// Run script
  1404  
  1405  		script := []byte(`
  1406            import EVM from 0x1
  1407  
  1408            access(all)
  1409            fun main(): Bool {
  1410              let dict: {Int: Bool} = {0: false, 1: true}
  1411              let data = EVM.encodeABI([dict])
  1412  
  1413              return true
  1414            }
  1415  		`)
  1416  
  1417  		_, err := rt.ExecuteScript(
  1418  			runtime.Script{
  1419  				Source:    script,
  1420  				Arguments: [][]byte{},
  1421  			},
  1422  			runtime.Context{
  1423  				Interface:   runtimeInterface,
  1424  				Environment: scriptEnvironment,
  1425  				Location:    nextScriptLocation(),
  1426  			},
  1427  		)
  1428  		utils.RequireError(t, err)
  1429  		assert.ErrorContains(
  1430  			t,
  1431  			err,
  1432  			"failed to ABI encode value of type {Int: Bool}",
  1433  		)
  1434  	})
  1435  
  1436  	t.Run("encodeABI with unsupported array element type", func(t *testing.T) {
  1437  
  1438  		t.Parallel()
  1439  
  1440  		handler := &testContractHandler{}
  1441  
  1442  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1443  
  1444  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1445  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1446  
  1447  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1448  
  1449  		accountCodes := map[common.Location][]byte{}
  1450  		var events []cadence.Event
  1451  
  1452  		runtimeInterface := &TestRuntimeInterface{
  1453  			Storage: NewTestLedger(nil, nil),
  1454  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1455  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1456  			},
  1457  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1458  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1459  				accountCodes[location] = code
  1460  				return nil
  1461  			},
  1462  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1463  				code = accountCodes[location]
  1464  				return code, nil
  1465  			},
  1466  			OnEmitEvent: func(event cadence.Event) error {
  1467  				events = append(events, event)
  1468  				return nil
  1469  			},
  1470  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1471  				return json.Decode(nil, b)
  1472  			},
  1473  		}
  1474  
  1475  		nextTransactionLocation := NewTransactionLocationGenerator()
  1476  		nextScriptLocation := NewScriptLocationGenerator()
  1477  
  1478  		// Deploy contracts
  1479  
  1480  		deployContracts(
  1481  			t,
  1482  			rt,
  1483  			contractsAddress,
  1484  			runtimeInterface,
  1485  			transactionEnvironment,
  1486  			nextTransactionLocation,
  1487  			true,
  1488  		)
  1489  
  1490  		// Run script
  1491  
  1492  		script := []byte(`
  1493            import EVM from 0x1
  1494  
  1495            access(all)
  1496            fun main(): Bool {
  1497              let chars: [Character] = ["a", "b", "c"]
  1498              let data = EVM.encodeABI([chars])
  1499  
  1500              return true
  1501            }
  1502  		`)
  1503  
  1504  		_, err := rt.ExecuteScript(
  1505  			runtime.Script{
  1506  				Source:    script,
  1507  				Arguments: [][]byte{},
  1508  			},
  1509  			runtime.Context{
  1510  				Interface:   runtimeInterface,
  1511  				Environment: scriptEnvironment,
  1512  				Location:    nextScriptLocation(),
  1513  			},
  1514  		)
  1515  		utils.RequireError(t, err)
  1516  		assert.ErrorContains(
  1517  			t,
  1518  			err,
  1519  			"failed to ABI encode value of type Character",
  1520  		)
  1521  	})
  1522  
  1523  	t.Run("encodeABI with unsupported custom composite type", func(t *testing.T) {
  1524  
  1525  		t.Parallel()
  1526  
  1527  		handler := &testContractHandler{}
  1528  
  1529  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1530  
  1531  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1532  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1533  
  1534  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1535  
  1536  		accountCodes := map[common.Location][]byte{}
  1537  		var events []cadence.Event
  1538  
  1539  		runtimeInterface := &TestRuntimeInterface{
  1540  			Storage: NewTestLedger(nil, nil),
  1541  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1542  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1543  			},
  1544  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1545  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1546  				accountCodes[location] = code
  1547  				return nil
  1548  			},
  1549  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1550  				code = accountCodes[location]
  1551  				return code, nil
  1552  			},
  1553  			OnEmitEvent: func(event cadence.Event) error {
  1554  				events = append(events, event)
  1555  				return nil
  1556  			},
  1557  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1558  				return json.Decode(nil, b)
  1559  			},
  1560  		}
  1561  
  1562  		nextTransactionLocation := NewTransactionLocationGenerator()
  1563  		nextScriptLocation := NewScriptLocationGenerator()
  1564  
  1565  		// Deploy contracts
  1566  
  1567  		deployContracts(
  1568  			t,
  1569  			rt,
  1570  			contractsAddress,
  1571  			runtimeInterface,
  1572  			transactionEnvironment,
  1573  			nextTransactionLocation,
  1574  			true,
  1575  		)
  1576  
  1577  		// Run script
  1578  
  1579  		script := []byte(`
  1580            import EVM from 0x1
  1581  
  1582            access(all) struct Token {
  1583              access(all) let id: Int
  1584              access(all) var balance: Int
  1585  
  1586              init(id: Int, balance: Int) {
  1587                self.id = id
  1588                self.balance = balance
  1589              }
  1590            }
  1591  
  1592            access(all)
  1593            fun main(): Bool {
  1594              let token = Token(id: 9, balance: 150)
  1595              let data = EVM.encodeABI([token])
  1596  
  1597              return true
  1598            }
  1599  		`)
  1600  
  1601  		_, err := rt.ExecuteScript(
  1602  			runtime.Script{
  1603  				Source:    script,
  1604  				Arguments: [][]byte{},
  1605  			},
  1606  			runtime.Context{
  1607  				Interface:   runtimeInterface,
  1608  				Environment: scriptEnvironment,
  1609  				Location:    nextScriptLocation(),
  1610  			},
  1611  		)
  1612  		utils.RequireError(t, err)
  1613  		assert.ErrorContains(
  1614  			t,
  1615  			err,
  1616  			"failed to ABI encode value of type s.0100000000000000000000000000000000000000000000000000000000000000.Token",
  1617  		)
  1618  	})
  1619  
  1620  	t.Run("decodeABI with mismatched type", func(t *testing.T) {
  1621  
  1622  		t.Parallel()
  1623  
  1624  		handler := &testContractHandler{}
  1625  
  1626  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1627  
  1628  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1629  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1630  
  1631  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1632  
  1633  		accountCodes := map[common.Location][]byte{}
  1634  		var events []cadence.Event
  1635  
  1636  		runtimeInterface := &TestRuntimeInterface{
  1637  			Storage: NewTestLedger(nil, nil),
  1638  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1639  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1640  			},
  1641  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1642  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1643  				accountCodes[location] = code
  1644  				return nil
  1645  			},
  1646  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1647  				code = accountCodes[location]
  1648  				return code, nil
  1649  			},
  1650  			OnEmitEvent: func(event cadence.Event) error {
  1651  				events = append(events, event)
  1652  				return nil
  1653  			},
  1654  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1655  				return json.Decode(nil, b)
  1656  			},
  1657  		}
  1658  
  1659  		nextTransactionLocation := NewTransactionLocationGenerator()
  1660  		nextScriptLocation := NewScriptLocationGenerator()
  1661  
  1662  		// Deploy contracts
  1663  
  1664  		deployContracts(
  1665  			t,
  1666  			rt,
  1667  			contractsAddress,
  1668  			runtimeInterface,
  1669  			transactionEnvironment,
  1670  			nextTransactionLocation,
  1671  			true,
  1672  		)
  1673  
  1674  		// Run script
  1675  
  1676  		script := []byte(`
  1677            import EVM from 0x1
  1678  
  1679            access(all)
  1680            fun main(): Bool {
  1681              let data = EVM.encodeABI(["Peter"])
  1682              let values = EVM.decodeABI(types: [Type<Bool>()], data: data)
  1683  
  1684              return true
  1685            }
  1686  		`)
  1687  
  1688  		_, err := rt.ExecuteScript(
  1689  			runtime.Script{
  1690  				Source:    script,
  1691  				Arguments: [][]byte{},
  1692  			},
  1693  			runtime.Context{
  1694  				Interface:   runtimeInterface,
  1695  				Environment: scriptEnvironment,
  1696  				Location:    nextScriptLocation(),
  1697  			},
  1698  		)
  1699  		utils.RequireError(t, err)
  1700  		assert.ErrorContains(
  1701  			t,
  1702  			err,
  1703  			"failed to ABI decode data",
  1704  		)
  1705  	})
  1706  
  1707  	t.Run("decodeABI with surplus of types", func(t *testing.T) {
  1708  
  1709  		t.Parallel()
  1710  
  1711  		handler := &testContractHandler{}
  1712  
  1713  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1714  
  1715  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1716  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1717  
  1718  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1719  
  1720  		accountCodes := map[common.Location][]byte{}
  1721  		var events []cadence.Event
  1722  
  1723  		runtimeInterface := &TestRuntimeInterface{
  1724  			Storage: NewTestLedger(nil, nil),
  1725  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1726  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1727  			},
  1728  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1729  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1730  				accountCodes[location] = code
  1731  				return nil
  1732  			},
  1733  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1734  				code = accountCodes[location]
  1735  				return code, nil
  1736  			},
  1737  			OnEmitEvent: func(event cadence.Event) error {
  1738  				events = append(events, event)
  1739  				return nil
  1740  			},
  1741  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1742  				return json.Decode(nil, b)
  1743  			},
  1744  		}
  1745  
  1746  		nextTransactionLocation := NewTransactionLocationGenerator()
  1747  		nextScriptLocation := NewScriptLocationGenerator()
  1748  
  1749  		// Deploy contracts
  1750  
  1751  		deployContracts(
  1752  			t,
  1753  			rt,
  1754  			contractsAddress,
  1755  			runtimeInterface,
  1756  			transactionEnvironment,
  1757  			nextTransactionLocation,
  1758  			true,
  1759  		)
  1760  
  1761  		// Run script
  1762  
  1763  		script := []byte(`
  1764            import EVM from 0x1
  1765  
  1766            access(all)
  1767            fun main(): Bool {
  1768              let data = EVM.encodeABI(["Peter"])
  1769              let values = EVM.decodeABI(types: [Type<String>(), Type<Bool>()], data: data)
  1770  
  1771              return true
  1772            }
  1773  		`)
  1774  
  1775  		_, err := rt.ExecuteScript(
  1776  			runtime.Script{
  1777  				Source:    script,
  1778  				Arguments: [][]byte{},
  1779  			},
  1780  			runtime.Context{
  1781  				Interface:   runtimeInterface,
  1782  				Environment: scriptEnvironment,
  1783  				Location:    nextScriptLocation(),
  1784  			},
  1785  		)
  1786  		utils.RequireError(t, err)
  1787  		assert.ErrorContains(
  1788  			t,
  1789  			err,
  1790  			"failed to ABI decode data",
  1791  		)
  1792  	})
  1793  
  1794  	t.Run("decodeABI with unsupported fixed-point number type", func(t *testing.T) {
  1795  
  1796  		t.Parallel()
  1797  
  1798  		handler := &testContractHandler{}
  1799  
  1800  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1801  
  1802  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1803  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1804  
  1805  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1806  
  1807  		accountCodes := map[common.Location][]byte{}
  1808  		var events []cadence.Event
  1809  
  1810  		runtimeInterface := &TestRuntimeInterface{
  1811  			Storage: NewTestLedger(nil, nil),
  1812  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1813  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1814  			},
  1815  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1816  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1817  				accountCodes[location] = code
  1818  				return nil
  1819  			},
  1820  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1821  				code = accountCodes[location]
  1822  				return code, nil
  1823  			},
  1824  			OnEmitEvent: func(event cadence.Event) error {
  1825  				events = append(events, event)
  1826  				return nil
  1827  			},
  1828  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1829  				return json.Decode(nil, b)
  1830  			},
  1831  		}
  1832  
  1833  		nextTransactionLocation := NewTransactionLocationGenerator()
  1834  		nextScriptLocation := NewScriptLocationGenerator()
  1835  
  1836  		// Deploy contracts
  1837  
  1838  		deployContracts(
  1839  			t,
  1840  			rt,
  1841  			contractsAddress,
  1842  			runtimeInterface,
  1843  			transactionEnvironment,
  1844  			nextTransactionLocation,
  1845  			true,
  1846  		)
  1847  
  1848  		// Run script
  1849  
  1850  		script := []byte(`
  1851            import EVM from 0x1
  1852  
  1853            access(all)
  1854            fun main(): Bool {
  1855              let data = EVM.encodeABI(["Peter"])
  1856              let values = EVM.decodeABI(types: [Type<UFix64>()], data: data)
  1857  
  1858              return true
  1859            }
  1860  		`)
  1861  
  1862  		_, err := rt.ExecuteScript(
  1863  			runtime.Script{
  1864  				Source:    script,
  1865  				Arguments: [][]byte{},
  1866  			},
  1867  			runtime.Context{
  1868  				Interface:   runtimeInterface,
  1869  				Environment: scriptEnvironment,
  1870  				Location:    nextScriptLocation(),
  1871  			},
  1872  		)
  1873  		utils.RequireError(t, err)
  1874  		assert.ErrorContains(
  1875  			t,
  1876  			err,
  1877  			"failed to ABI decode data with type UFix64",
  1878  		)
  1879  	})
  1880  
  1881  	t.Run("decodeABI with unsupported dictionary type", func(t *testing.T) {
  1882  
  1883  		t.Parallel()
  1884  
  1885  		handler := &testContractHandler{}
  1886  
  1887  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1888  
  1889  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1890  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1891  
  1892  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1893  
  1894  		accountCodes := map[common.Location][]byte{}
  1895  		var events []cadence.Event
  1896  
  1897  		runtimeInterface := &TestRuntimeInterface{
  1898  			Storage: NewTestLedger(nil, nil),
  1899  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1900  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1901  			},
  1902  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1903  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1904  				accountCodes[location] = code
  1905  				return nil
  1906  			},
  1907  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1908  				code = accountCodes[location]
  1909  				return code, nil
  1910  			},
  1911  			OnEmitEvent: func(event cadence.Event) error {
  1912  				events = append(events, event)
  1913  				return nil
  1914  			},
  1915  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  1916  				return json.Decode(nil, b)
  1917  			},
  1918  		}
  1919  
  1920  		nextTransactionLocation := NewTransactionLocationGenerator()
  1921  		nextScriptLocation := NewScriptLocationGenerator()
  1922  
  1923  		// Deploy contracts
  1924  
  1925  		deployContracts(
  1926  			t,
  1927  			rt,
  1928  			contractsAddress,
  1929  			runtimeInterface,
  1930  			transactionEnvironment,
  1931  			nextTransactionLocation,
  1932  			true,
  1933  		)
  1934  
  1935  		// Run script
  1936  
  1937  		script := []byte(`
  1938            import EVM from 0x1
  1939  
  1940            access(all)
  1941            fun main(): Bool {
  1942              let data = EVM.encodeABI(["Peter"])
  1943              let values = EVM.decodeABI(types: [Type<{Int: Bool}>()], data: data)
  1944  
  1945              return true
  1946            }
  1947  		`)
  1948  
  1949  		_, err := rt.ExecuteScript(
  1950  			runtime.Script{
  1951  				Source:    script,
  1952  				Arguments: [][]byte{},
  1953  			},
  1954  			runtime.Context{
  1955  				Interface:   runtimeInterface,
  1956  				Environment: scriptEnvironment,
  1957  				Location:    nextScriptLocation(),
  1958  			},
  1959  		)
  1960  		utils.RequireError(t, err)
  1961  		assert.ErrorContains(
  1962  			t,
  1963  			err,
  1964  			"failed to ABI decode data with type {Int: Bool}",
  1965  		)
  1966  	})
  1967  
  1968  	t.Run("decodeABI with unsupported array element type", func(t *testing.T) {
  1969  
  1970  		t.Parallel()
  1971  
  1972  		handler := &testContractHandler{}
  1973  
  1974  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  1975  
  1976  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  1977  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  1978  
  1979  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  1980  
  1981  		accountCodes := map[common.Location][]byte{}
  1982  		var events []cadence.Event
  1983  
  1984  		runtimeInterface := &TestRuntimeInterface{
  1985  			Storage: NewTestLedger(nil, nil),
  1986  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  1987  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  1988  			},
  1989  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  1990  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  1991  				accountCodes[location] = code
  1992  				return nil
  1993  			},
  1994  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  1995  				code = accountCodes[location]
  1996  				return code, nil
  1997  			},
  1998  			OnEmitEvent: func(event cadence.Event) error {
  1999  				events = append(events, event)
  2000  				return nil
  2001  			},
  2002  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2003  				return json.Decode(nil, b)
  2004  			},
  2005  		}
  2006  
  2007  		nextTransactionLocation := NewTransactionLocationGenerator()
  2008  		nextScriptLocation := NewScriptLocationGenerator()
  2009  
  2010  		// Deploy contracts
  2011  
  2012  		deployContracts(
  2013  			t,
  2014  			rt,
  2015  			contractsAddress,
  2016  			runtimeInterface,
  2017  			transactionEnvironment,
  2018  			nextTransactionLocation,
  2019  			true,
  2020  		)
  2021  
  2022  		// Run script
  2023  
  2024  		script := []byte(`
  2025            import EVM from 0x1
  2026  
  2027            access(all)
  2028            fun main(): Bool {
  2029              let data = EVM.encodeABI(["Peter"])
  2030              let values = EVM.decodeABI(types: [Type<[Character]>()], data: data)
  2031  
  2032              return true
  2033            }
  2034  		`)
  2035  
  2036  		_, err := rt.ExecuteScript(
  2037  			runtime.Script{
  2038  				Source:    script,
  2039  				Arguments: [][]byte{},
  2040  			},
  2041  			runtime.Context{
  2042  				Interface:   runtimeInterface,
  2043  				Environment: scriptEnvironment,
  2044  				Location:    nextScriptLocation(),
  2045  			},
  2046  		)
  2047  		utils.RequireError(t, err)
  2048  		assert.ErrorContains(
  2049  			t,
  2050  			err,
  2051  			"failed to ABI decode data with type [Character]",
  2052  		)
  2053  	})
  2054  
  2055  	t.Run("decodeABI with unsupported custom composite type", func(t *testing.T) {
  2056  
  2057  		t.Parallel()
  2058  
  2059  		handler := &testContractHandler{}
  2060  
  2061  		contractsAddress := flow.BytesToAddress([]byte{0x1})
  2062  
  2063  		transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2064  		scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2065  
  2066  		rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2067  
  2068  		accountCodes := map[common.Location][]byte{}
  2069  		var events []cadence.Event
  2070  
  2071  		runtimeInterface := &TestRuntimeInterface{
  2072  			Storage: NewTestLedger(nil, nil),
  2073  			OnGetSigningAccounts: func() ([]runtime.Address, error) {
  2074  				return []runtime.Address{runtime.Address(contractsAddress)}, nil
  2075  			},
  2076  			OnResolveLocation: SingleIdentifierLocationResolver(t),
  2077  			OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  2078  				accountCodes[location] = code
  2079  				return nil
  2080  			},
  2081  			OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  2082  				code = accountCodes[location]
  2083  				return code, nil
  2084  			},
  2085  			OnEmitEvent: func(event cadence.Event) error {
  2086  				events = append(events, event)
  2087  				return nil
  2088  			},
  2089  			OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2090  				return json.Decode(nil, b)
  2091  			},
  2092  		}
  2093  
  2094  		nextTransactionLocation := NewTransactionLocationGenerator()
  2095  		nextScriptLocation := NewScriptLocationGenerator()
  2096  
  2097  		// Deploy contracts
  2098  
  2099  		deployContracts(
  2100  			t,
  2101  			rt,
  2102  			contractsAddress,
  2103  			runtimeInterface,
  2104  			transactionEnvironment,
  2105  			nextTransactionLocation,
  2106  			true,
  2107  		)
  2108  
  2109  		// Run script
  2110  
  2111  		script := []byte(`
  2112            import EVM from 0x1
  2113  
  2114            access(all) struct Token {
  2115              access(all) let id: Int
  2116              access(all) var balance: Int
  2117  
  2118              init(id: Int, balance: Int) {
  2119                self.id = id
  2120                self.balance = balance
  2121              }
  2122            }
  2123  
  2124            access(all)
  2125            fun main(): Bool {
  2126              let data = EVM.encodeABI(["Peter"])
  2127              let values = EVM.decodeABI(types: [Type<Token>()], data: data)
  2128  
  2129              return true
  2130            }
  2131  		`)
  2132  
  2133  		_, err := rt.ExecuteScript(
  2134  			runtime.Script{
  2135  				Source:    script,
  2136  				Arguments: [][]byte{},
  2137  			},
  2138  			runtime.Context{
  2139  				Interface:   runtimeInterface,
  2140  				Environment: scriptEnvironment,
  2141  				Location:    nextScriptLocation(),
  2142  			},
  2143  		)
  2144  		utils.RequireError(t, err)
  2145  		assert.ErrorContains(
  2146  			t,
  2147  			err,
  2148  			"failed to ABI decode data with type s.0100000000000000000000000000000000000000000000000000000000000000.Token",
  2149  		)
  2150  	})
  2151  }
  2152  
  2153  func TestEVMEncodeABIWithSignature(t *testing.T) {
  2154  
  2155  	t.Parallel()
  2156  
  2157  	handler := &testContractHandler{}
  2158  
  2159  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  2160  
  2161  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2162  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2163  
  2164  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2165  
  2166  	script := []byte(`
  2167        import EVM from 0x1
  2168  
  2169        access(all)
  2170        fun main(): [UInt8] {
  2171          // bytes for address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71
  2172          let address = EVM.EVMAddress(
  2173            bytes: [
  2174              122, 88, 192, 190, 114, 190, 33, 139, 65, 198,
  2175              8, 183, 254, 124, 91, 182, 48, 115, 108, 113
  2176            ]
  2177          )
  2178  
  2179          return EVM.encodeABIWithSignature(
  2180            "withdraw(address,uint256)",
  2181            [address, UInt256(250)]
  2182          )
  2183        }
  2184  	`)
  2185  
  2186  	accountCodes := map[common.Location][]byte{}
  2187  	var events []cadence.Event
  2188  
  2189  	computation := uint(0)
  2190  	runtimeInterface := &TestRuntimeInterface{
  2191  		Storage: NewTestLedger(nil, nil),
  2192  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  2193  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  2194  		},
  2195  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  2196  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  2197  			accountCodes[location] = code
  2198  			return nil
  2199  		},
  2200  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  2201  			code = accountCodes[location]
  2202  			return code, nil
  2203  		},
  2204  		OnEmitEvent: func(event cadence.Event) error {
  2205  			events = append(events, event)
  2206  			return nil
  2207  		},
  2208  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2209  			return json.Decode(nil, b)
  2210  		},
  2211  		OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error {
  2212  			if compKind == environment.ComputationKindEVMEncodeABI {
  2213  				computation += intensity
  2214  			}
  2215  			return nil
  2216  		},
  2217  		OnHash: func(
  2218  			data []byte,
  2219  			tag string,
  2220  			hashAlgorithm runtime.HashAlgorithm,
  2221  		) ([]byte, error) {
  2222  			return crypto.Keccak256(data), nil
  2223  		},
  2224  	}
  2225  
  2226  	nextTransactionLocation := NewTransactionLocationGenerator()
  2227  	nextScriptLocation := NewScriptLocationGenerator()
  2228  
  2229  	// Deploy contracts
  2230  
  2231  	deployContracts(
  2232  		t,
  2233  		rt,
  2234  		contractsAddress,
  2235  		runtimeInterface,
  2236  		transactionEnvironment,
  2237  		nextTransactionLocation,
  2238  		true,
  2239  	)
  2240  
  2241  	// Run script
  2242  
  2243  	result, err := rt.ExecuteScript(
  2244  		runtime.Script{
  2245  			Source:    script,
  2246  			Arguments: [][]byte{},
  2247  		},
  2248  		runtime.Context{
  2249  			Interface:   runtimeInterface,
  2250  			Environment: scriptEnvironment,
  2251  			Location:    nextScriptLocation(),
  2252  		},
  2253  	)
  2254  	require.NoError(t, err)
  2255  
  2256  	abiBytes := []byte{
  2257  		0xf3, 0xfe, 0xf3, 0xa3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2258  		0x0, 0x0, 0x0, 0x7a, 0x58, 0xc0, 0xbe, 0x72, 0xbe, 0x21, 0x8b, 0x41,
  2259  		0xc6, 0x8, 0xb7, 0xfe, 0x7c, 0x5b, 0xb6, 0x30, 0x73, 0x6c, 0x71, 0x0,
  2260  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2261  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2262  		0x0, 0x0, 0xfa,
  2263  	}
  2264  	cdcBytes := make([]cadence.Value, 0)
  2265  	for _, bt := range abiBytes {
  2266  		cdcBytes = append(cdcBytes, cadence.UInt8(bt))
  2267  	}
  2268  	encodedABI := cadence.NewArray(
  2269  		cdcBytes,
  2270  	).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type))
  2271  
  2272  	assert.Equal(t,
  2273  		encodedABI,
  2274  		result,
  2275  	)
  2276  	// The method ID is a byte array of length 4
  2277  	assert.Equal(t, computation+4, uint(len(cdcBytes)))
  2278  }
  2279  
  2280  func TestEVMDecodeABIWithSignature(t *testing.T) {
  2281  
  2282  	t.Parallel()
  2283  
  2284  	handler := &testContractHandler{}
  2285  
  2286  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  2287  
  2288  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2289  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2290  
  2291  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2292  
  2293  	script := []byte(`
  2294        import EVM from 0x1
  2295  
  2296        access(all)
  2297        fun main(data: [UInt8]): Bool {
  2298          let values = EVM.decodeABIWithSignature(
  2299            "withdraw(address,uint256)",
  2300            types: [Type<EVM.EVMAddress>(), Type<UInt256>()],
  2301            data: data
  2302          )
  2303  
  2304          // bytes for address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71
  2305          let address = EVM.EVMAddress(
  2306            bytes: [
  2307              122, 88, 192, 190, 114, 190, 33, 139, 65, 198,
  2308              8, 183, 254, 124, 91, 182, 48, 115, 108, 113
  2309            ]
  2310          )
  2311  
  2312          assert(values.length == 2)
  2313          assert((values[0] as! EVM.EVMAddress).bytes == address.bytes)
  2314          assert((values[1] as! UInt256) == UInt256(250))
  2315  
  2316          return true
  2317        }
  2318  	`)
  2319  
  2320  	accountCodes := map[common.Location][]byte{}
  2321  	var events []cadence.Event
  2322  
  2323  	computation := uint(0)
  2324  	runtimeInterface := &TestRuntimeInterface{
  2325  		Storage: NewTestLedger(nil, nil),
  2326  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  2327  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  2328  		},
  2329  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  2330  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  2331  			accountCodes[location] = code
  2332  			return nil
  2333  		},
  2334  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  2335  			code = accountCodes[location]
  2336  			return code, nil
  2337  		},
  2338  		OnEmitEvent: func(event cadence.Event) error {
  2339  			events = append(events, event)
  2340  			return nil
  2341  		},
  2342  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2343  			return json.Decode(nil, b)
  2344  		},
  2345  		OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error {
  2346  			if compKind == environment.ComputationKindEVMDecodeABI {
  2347  				computation += intensity
  2348  			}
  2349  			return nil
  2350  		},
  2351  		OnHash: func(
  2352  			data []byte,
  2353  			tag string,
  2354  			hashAlgorithm runtime.HashAlgorithm,
  2355  		) ([]byte, error) {
  2356  			return crypto.Keccak256(data), nil
  2357  		},
  2358  	}
  2359  
  2360  	nextTransactionLocation := NewTransactionLocationGenerator()
  2361  	nextScriptLocation := NewScriptLocationGenerator()
  2362  
  2363  	// Deploy contracts
  2364  
  2365  	deployContracts(
  2366  		t,
  2367  		rt,
  2368  		contractsAddress,
  2369  		runtimeInterface,
  2370  		transactionEnvironment,
  2371  		nextTransactionLocation,
  2372  		true,
  2373  	)
  2374  
  2375  	// Run script
  2376  	abiBytes := []byte{
  2377  		0xf3, 0xfe, 0xf3, 0xa3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2378  		0x0, 0x0, 0x0, 0x7a, 0x58, 0xc0, 0xbe, 0x72, 0xbe, 0x21, 0x8b, 0x41,
  2379  		0xc6, 0x8, 0xb7, 0xfe, 0x7c, 0x5b, 0xb6, 0x30, 0x73, 0x6c, 0x71, 0x0,
  2380  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2381  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2382  		0x0, 0x0, 0xfa,
  2383  	}
  2384  	cdcBytes := make([]cadence.Value, 0)
  2385  	for _, bt := range abiBytes {
  2386  		cdcBytes = append(cdcBytes, cadence.UInt8(bt))
  2387  	}
  2388  	encodedABI := cadence.NewArray(
  2389  		cdcBytes,
  2390  	).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type))
  2391  
  2392  	result, err := rt.ExecuteScript(
  2393  		runtime.Script{
  2394  			Source: script,
  2395  			Arguments: EncodeArgs([]cadence.Value{
  2396  				encodedABI,
  2397  			}),
  2398  		},
  2399  		runtime.Context{
  2400  			Interface:   runtimeInterface,
  2401  			Environment: scriptEnvironment,
  2402  			Location:    nextScriptLocation(),
  2403  		},
  2404  	)
  2405  	require.NoError(t, err)
  2406  
  2407  	assert.Equal(t, cadence.NewBool(true), result)
  2408  	// The method ID is a byte array of length 4
  2409  	assert.Equal(t, computation+4, uint(len(cdcBytes)))
  2410  }
  2411  
  2412  func TestEVMDecodeABIWithSignatureMismatch(t *testing.T) {
  2413  
  2414  	t.Parallel()
  2415  
  2416  	handler := &testContractHandler{}
  2417  
  2418  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  2419  
  2420  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2421  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2422  
  2423  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2424  
  2425  	script := []byte(`
  2426        import EVM from 0x1
  2427  
  2428        access(all)
  2429        fun main(data: [UInt8]): Bool {
  2430          // The data was encoded for the function "withdraw(address,uint256)",
  2431          // but we pass a different function signature
  2432          let values = EVM.decodeABIWithSignature(
  2433            "deposit(uint256, address)",
  2434            types: [Type<UInt256>(), Type<EVM.EVMAddress>()],
  2435            data: data
  2436          )
  2437  
  2438          return true
  2439        }
  2440  	`)
  2441  
  2442  	accountCodes := map[common.Location][]byte{}
  2443  	var events []cadence.Event
  2444  
  2445  	runtimeInterface := &TestRuntimeInterface{
  2446  		Storage: NewTestLedger(nil, nil),
  2447  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  2448  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  2449  		},
  2450  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  2451  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  2452  			accountCodes[location] = code
  2453  			return nil
  2454  		},
  2455  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  2456  			code = accountCodes[location]
  2457  			return code, nil
  2458  		},
  2459  		OnEmitEvent: func(event cadence.Event) error {
  2460  			events = append(events, event)
  2461  			return nil
  2462  		},
  2463  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2464  			return json.Decode(nil, b)
  2465  		},
  2466  		OnHash: func(
  2467  			data []byte,
  2468  			tag string,
  2469  			hashAlgorithm runtime.HashAlgorithm,
  2470  		) ([]byte, error) {
  2471  			return crypto.Keccak256(data), nil
  2472  		},
  2473  	}
  2474  
  2475  	nextTransactionLocation := NewTransactionLocationGenerator()
  2476  	nextScriptLocation := NewScriptLocationGenerator()
  2477  
  2478  	// Deploy contracts
  2479  
  2480  	deployContracts(
  2481  		t,
  2482  		rt,
  2483  		contractsAddress,
  2484  		runtimeInterface,
  2485  		transactionEnvironment,
  2486  		nextTransactionLocation,
  2487  		true,
  2488  	)
  2489  
  2490  	// Run script
  2491  	abiBytes := []byte{
  2492  		0xf3, 0xfe, 0xf3, 0xa3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2493  		0x0, 0x0, 0x0, 0x7a, 0x58, 0xc0, 0xbe, 0x72, 0xbe, 0x21, 0x8b, 0x41,
  2494  		0xc6, 0x8, 0xb7, 0xfe, 0x7c, 0x5b, 0xb6, 0x30, 0x73, 0x6c, 0x71, 0x0,
  2495  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2496  		0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  2497  		0x0, 0x0, 0xfa,
  2498  	}
  2499  	cdcBytes := make([]cadence.Value, 0)
  2500  	for _, bt := range abiBytes {
  2501  		cdcBytes = append(cdcBytes, cadence.UInt8(bt))
  2502  	}
  2503  	encodedABI := cadence.NewArray(
  2504  		cdcBytes,
  2505  	).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type))
  2506  
  2507  	_, err := rt.ExecuteScript(
  2508  		runtime.Script{
  2509  			Source: script,
  2510  			Arguments: EncodeArgs([]cadence.Value{
  2511  				encodedABI,
  2512  			}),
  2513  		},
  2514  		runtime.Context{
  2515  			Interface:   runtimeInterface,
  2516  			Environment: scriptEnvironment,
  2517  			Location:    nextScriptLocation(),
  2518  		},
  2519  	)
  2520  	require.Error(t, err)
  2521  	assert.ErrorContains(t, err, "panic: signature mismatch")
  2522  }
  2523  
  2524  func TestEVMAddressConstructionAndReturn(t *testing.T) {
  2525  
  2526  	t.Parallel()
  2527  
  2528  	handler := &testContractHandler{}
  2529  
  2530  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  2531  
  2532  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2533  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2534  
  2535  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2536  
  2537  	script := []byte(`
  2538        import EVM from 0x1
  2539  
  2540        access(all)
  2541        fun main(_ bytes: [UInt8; 20]): EVM.EVMAddress {
  2542            return EVM.EVMAddress(bytes: bytes)
  2543        }
  2544      `)
  2545  
  2546  	accountCodes := map[common.Location][]byte{}
  2547  	var events []cadence.Event
  2548  
  2549  	runtimeInterface := &TestRuntimeInterface{
  2550  		Storage: NewTestLedger(nil, nil),
  2551  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  2552  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  2553  		},
  2554  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  2555  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  2556  			accountCodes[location] = code
  2557  			return nil
  2558  		},
  2559  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  2560  			code = accountCodes[location]
  2561  			return code, nil
  2562  		},
  2563  		OnEmitEvent: func(event cadence.Event) error {
  2564  			events = append(events, event)
  2565  			return nil
  2566  		},
  2567  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2568  			return json.Decode(nil, b)
  2569  		},
  2570  	}
  2571  
  2572  	addressBytesArray := cadence.NewArray([]cadence.Value{
  2573  		cadence.UInt8(1), cadence.UInt8(1),
  2574  		cadence.UInt8(2), cadence.UInt8(2),
  2575  		cadence.UInt8(3), cadence.UInt8(3),
  2576  		cadence.UInt8(4), cadence.UInt8(4),
  2577  		cadence.UInt8(5), cadence.UInt8(5),
  2578  		cadence.UInt8(6), cadence.UInt8(6),
  2579  		cadence.UInt8(7), cadence.UInt8(7),
  2580  		cadence.UInt8(8), cadence.UInt8(8),
  2581  		cadence.UInt8(9), cadence.UInt8(9),
  2582  		cadence.UInt8(10), cadence.UInt8(10),
  2583  	}).WithType(stdlib.EVMAddressBytesCadenceType)
  2584  
  2585  	nextTransactionLocation := NewTransactionLocationGenerator()
  2586  	nextScriptLocation := NewScriptLocationGenerator()
  2587  
  2588  	// Deploy contracts
  2589  
  2590  	deployContracts(
  2591  		t,
  2592  		rt,
  2593  		contractsAddress,
  2594  		runtimeInterface,
  2595  		transactionEnvironment,
  2596  		nextTransactionLocation,
  2597  		true,
  2598  	)
  2599  
  2600  	// Run script
  2601  
  2602  	result, err := rt.ExecuteScript(
  2603  		runtime.Script{
  2604  			Source: script,
  2605  			Arguments: EncodeArgs([]cadence.Value{
  2606  				addressBytesArray,
  2607  			}),
  2608  		},
  2609  		runtime.Context{
  2610  			Interface:   runtimeInterface,
  2611  			Environment: scriptEnvironment,
  2612  			Location:    nextScriptLocation(),
  2613  		},
  2614  	)
  2615  	require.NoError(t, err)
  2616  
  2617  	evmAddressCadenceType := stdlib.NewEVMAddressCadenceType(common.Address(contractsAddress))
  2618  
  2619  	assert.Equal(t,
  2620  		cadence.Struct{
  2621  			StructType: evmAddressCadenceType,
  2622  			Fields: []cadence.Value{
  2623  				addressBytesArray,
  2624  			},
  2625  		},
  2626  		result,
  2627  	)
  2628  }
  2629  
  2630  func TestBalanceConstructionAndReturn(t *testing.T) {
  2631  
  2632  	t.Parallel()
  2633  
  2634  	handler := &testContractHandler{}
  2635  
  2636  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  2637  
  2638  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2639  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2640  
  2641  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2642  
  2643  	script := []byte(`
  2644        import EVM from 0x1
  2645  
  2646        access(all)
  2647        fun main(_ flow: UFix64): EVM.Balance {
  2648            return EVM.Balance(flow: flow)
  2649        }
  2650      `)
  2651  
  2652  	accountCodes := map[common.Location][]byte{}
  2653  	var events []cadence.Event
  2654  
  2655  	runtimeInterface := &TestRuntimeInterface{
  2656  		Storage: NewTestLedger(nil, nil),
  2657  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  2658  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  2659  		},
  2660  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  2661  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  2662  			accountCodes[location] = code
  2663  			return nil
  2664  		},
  2665  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  2666  			code = accountCodes[location]
  2667  			return code, nil
  2668  		},
  2669  		OnEmitEvent: func(event cadence.Event) error {
  2670  			events = append(events, event)
  2671  			return nil
  2672  		},
  2673  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2674  			return json.Decode(nil, b)
  2675  		},
  2676  	}
  2677  
  2678  	nextTransactionLocation := NewTransactionLocationGenerator()
  2679  	nextScriptLocation := NewScriptLocationGenerator()
  2680  
  2681  	// Deploy contracts
  2682  
  2683  	deployContracts(
  2684  		t,
  2685  		rt,
  2686  		contractsAddress,
  2687  		runtimeInterface,
  2688  		transactionEnvironment,
  2689  		nextTransactionLocation,
  2690  		false,
  2691  	)
  2692  
  2693  	// Run script
  2694  
  2695  	flowValue, err := cadence.NewUFix64FromParts(1, 23000000)
  2696  	require.NoError(t, err)
  2697  
  2698  	result, err := rt.ExecuteScript(
  2699  		runtime.Script{
  2700  			Source: script,
  2701  			Arguments: EncodeArgs([]cadence.Value{
  2702  				flowValue,
  2703  			}),
  2704  		},
  2705  		runtime.Context{
  2706  			Interface:   runtimeInterface,
  2707  			Environment: scriptEnvironment,
  2708  			Location:    nextScriptLocation(),
  2709  		},
  2710  	)
  2711  	require.NoError(t, err)
  2712  
  2713  	evmBalanceCadenceType := stdlib.NewBalanceCadenceType(common.Address(contractsAddress))
  2714  
  2715  	assert.Equal(t,
  2716  		cadence.Struct{
  2717  			StructType: evmBalanceCadenceType,
  2718  			Fields: []cadence.Value{
  2719  				flowValue,
  2720  			},
  2721  		},
  2722  		result,
  2723  	)
  2724  }
  2725  
  2726  func TestEVMRun(t *testing.T) {
  2727  
  2728  	t.Parallel()
  2729  
  2730  	evmTx := cadence.NewArray([]cadence.Value{
  2731  		cadence.UInt8(1),
  2732  		cadence.UInt8(2),
  2733  		cadence.UInt8(3),
  2734  	}).WithType(stdlib.EVMTransactionBytesCadenceType)
  2735  
  2736  	coinbase := cadence.NewArray([]cadence.Value{
  2737  		cadence.UInt8(1), cadence.UInt8(1),
  2738  		cadence.UInt8(2), cadence.UInt8(2),
  2739  		cadence.UInt8(3), cadence.UInt8(3),
  2740  		cadence.UInt8(4), cadence.UInt8(4),
  2741  		cadence.UInt8(5), cadence.UInt8(5),
  2742  		cadence.UInt8(6), cadence.UInt8(6),
  2743  		cadence.UInt8(7), cadence.UInt8(7),
  2744  		cadence.UInt8(8), cadence.UInt8(8),
  2745  		cadence.UInt8(9), cadence.UInt8(9),
  2746  		cadence.UInt8(10), cadence.UInt8(10),
  2747  	}).WithType(stdlib.EVMAddressBytesCadenceType)
  2748  
  2749  	runCalled := false
  2750  
  2751  	handler := &testContractHandler{
  2752  		run: func(tx []byte, coinbase types.Address) {
  2753  			runCalled = true
  2754  
  2755  			assert.Equal(t, []byte{1, 2, 3}, tx)
  2756  			assert.Equal(t,
  2757  				types.Address{
  2758  					1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
  2759  				},
  2760  				coinbase,
  2761  			)
  2762  
  2763  		},
  2764  	}
  2765  
  2766  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  2767  
  2768  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2769  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2770  
  2771  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2772  
  2773  	script := []byte(`
  2774        import EVM from 0x1
  2775  
  2776        access(all)
  2777        fun main(tx: [UInt8], coinbaseBytes: [UInt8; 20]) {
  2778            let coinbase = EVM.EVMAddress(bytes: coinbaseBytes)
  2779            EVM.run(tx: tx, coinbase: coinbase)
  2780        }
  2781      `)
  2782  
  2783  	accountCodes := map[common.Location][]byte{}
  2784  	var events []cadence.Event
  2785  
  2786  	runtimeInterface := &TestRuntimeInterface{
  2787  		Storage: NewTestLedger(nil, nil),
  2788  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  2789  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  2790  		},
  2791  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  2792  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  2793  			accountCodes[location] = code
  2794  			return nil
  2795  		},
  2796  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  2797  			code = accountCodes[location]
  2798  			return code, nil
  2799  		},
  2800  		OnEmitEvent: func(event cadence.Event) error {
  2801  			events = append(events, event)
  2802  			return nil
  2803  		},
  2804  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2805  			return json.Decode(nil, b)
  2806  		},
  2807  	}
  2808  
  2809  	nextTransactionLocation := NewTransactionLocationGenerator()
  2810  	nextScriptLocation := NewScriptLocationGenerator()
  2811  
  2812  	// Deploy contracts
  2813  
  2814  	deployContracts(
  2815  		t,
  2816  		rt,
  2817  		contractsAddress,
  2818  		runtimeInterface,
  2819  		transactionEnvironment,
  2820  		nextTransactionLocation,
  2821  		false,
  2822  	)
  2823  
  2824  	// Run script
  2825  
  2826  	_, err := rt.ExecuteScript(
  2827  		runtime.Script{
  2828  			Source:    script,
  2829  			Arguments: EncodeArgs([]cadence.Value{evmTx, coinbase}),
  2830  		},
  2831  		runtime.Context{
  2832  			Interface:   runtimeInterface,
  2833  			Environment: scriptEnvironment,
  2834  			Location:    nextScriptLocation(),
  2835  		},
  2836  	)
  2837  	require.NoError(t, err)
  2838  
  2839  	assert.True(t, runCalled)
  2840  }
  2841  
  2842  func TestEVMCreateBridgedAccount(t *testing.T) {
  2843  
  2844  	t.Parallel()
  2845  
  2846  	handler := &testContractHandler{}
  2847  
  2848  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  2849  
  2850  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2851  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2852  
  2853  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2854  
  2855  	script := []byte(`
  2856        import EVM from 0x1
  2857  
  2858        access(all)
  2859        fun main(): [UInt8; 20] {
  2860            let bridgedAccount1 <- EVM.createBridgedAccount()
  2861            destroy bridgedAccount1
  2862  
  2863            let bridgedAccount2 <- EVM.createBridgedAccount()
  2864            let bytes = bridgedAccount2.address().bytes
  2865            destroy bridgedAccount2
  2866  
  2867            return bytes
  2868        }
  2869      `)
  2870  
  2871  	accountCodes := map[common.Location][]byte{}
  2872  	var events []cadence.Event
  2873  
  2874  	runtimeInterface := &TestRuntimeInterface{
  2875  		Storage: NewTestLedger(nil, nil),
  2876  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  2877  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  2878  		},
  2879  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  2880  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  2881  			accountCodes[location] = code
  2882  			return nil
  2883  		},
  2884  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  2885  			code = accountCodes[location]
  2886  			return code, nil
  2887  		},
  2888  		OnEmitEvent: func(event cadence.Event) error {
  2889  			events = append(events, event)
  2890  			return nil
  2891  		},
  2892  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  2893  			return json.Decode(nil, b)
  2894  		},
  2895  	}
  2896  
  2897  	nextTransactionLocation := NewTransactionLocationGenerator()
  2898  	nextScriptLocation := NewScriptLocationGenerator()
  2899  
  2900  	// Deploy contracts
  2901  
  2902  	deployContracts(
  2903  		t,
  2904  		rt,
  2905  		contractsAddress,
  2906  		runtimeInterface,
  2907  		transactionEnvironment,
  2908  		nextTransactionLocation,
  2909  		false,
  2910  	)
  2911  
  2912  	// Run script
  2913  
  2914  	actual, err := rt.ExecuteScript(
  2915  		runtime.Script{
  2916  			Source: script,
  2917  		},
  2918  		runtime.Context{
  2919  			Interface:   runtimeInterface,
  2920  			Environment: scriptEnvironment,
  2921  			Location:    nextScriptLocation(),
  2922  		},
  2923  	)
  2924  	require.NoError(t, err)
  2925  
  2926  	expected := cadence.NewArray([]cadence.Value{
  2927  		cadence.UInt8(2), cadence.UInt8(0),
  2928  		cadence.UInt8(0), cadence.UInt8(0),
  2929  		cadence.UInt8(0), cadence.UInt8(0),
  2930  		cadence.UInt8(0), cadence.UInt8(0),
  2931  		cadence.UInt8(0), cadence.UInt8(0),
  2932  		cadence.UInt8(0), cadence.UInt8(0),
  2933  		cadence.UInt8(0), cadence.UInt8(0),
  2934  		cadence.UInt8(0), cadence.UInt8(0),
  2935  		cadence.UInt8(0), cadence.UInt8(0),
  2936  		cadence.UInt8(0), cadence.UInt8(0),
  2937  	}).WithType(cadence.NewConstantSizedArrayType(
  2938  		types.AddressLength,
  2939  		cadence.UInt8Type{},
  2940  	))
  2941  
  2942  	require.Equal(t, expected, actual)
  2943  }
  2944  
  2945  func TestBridgedAccountCall(t *testing.T) {
  2946  
  2947  	t.Parallel()
  2948  
  2949  	expectedBalance, err := cadence.NewUFix64FromParts(1, 23000000)
  2950  	require.NoError(t, err)
  2951  
  2952  	handler := &testContractHandler{
  2953  		accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account {
  2954  			assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress)
  2955  			assert.True(t, isAuthorized)
  2956  
  2957  			return &testFlowAccount{
  2958  				address: fromAddress,
  2959  				call: func(
  2960  					toAddress types.Address,
  2961  					data types.Data,
  2962  					limit types.GasLimit,
  2963  					balance types.Balance,
  2964  				) types.Data {
  2965  					assert.Equal(t, types.Address{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, toAddress)
  2966  					assert.Equal(t, types.Data{4, 5, 6}, data)
  2967  					assert.Equal(t, types.GasLimit(9999), limit)
  2968  					assert.Equal(t, types.Balance(expectedBalance), balance)
  2969  
  2970  					return types.Data{3, 1, 4}
  2971  				},
  2972  			}
  2973  		},
  2974  	}
  2975  
  2976  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  2977  
  2978  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  2979  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  2980  
  2981  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  2982  
  2983  	script := []byte(`
  2984        import EVM from 0x1
  2985  
  2986        access(all)
  2987        fun main(): [UInt8] {
  2988            let bridgedAccount <- EVM.createBridgedAccount()
  2989            let response = bridgedAccount.call(
  2990                to: EVM.EVMAddress(
  2991                    bytes: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  2992                ),
  2993                data: [4, 5, 6],
  2994                gasLimit: 9999,
  2995                value: EVM.Balance(flow: 1.23)
  2996            )
  2997            destroy bridgedAccount
  2998            return response
  2999        }
  3000     `)
  3001  
  3002  	accountCodes := map[common.Location][]byte{}
  3003  	var events []cadence.Event
  3004  
  3005  	runtimeInterface := &TestRuntimeInterface{
  3006  		Storage: NewTestLedger(nil, nil),
  3007  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  3008  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  3009  		},
  3010  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  3011  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  3012  			accountCodes[location] = code
  3013  			return nil
  3014  		},
  3015  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  3016  			code = accountCodes[location]
  3017  			return code, nil
  3018  		},
  3019  		OnEmitEvent: func(event cadence.Event) error {
  3020  			events = append(events, event)
  3021  			return nil
  3022  		},
  3023  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  3024  			return json.Decode(nil, b)
  3025  		},
  3026  	}
  3027  
  3028  	nextTransactionLocation := NewTransactionLocationGenerator()
  3029  	nextScriptLocation := NewScriptLocationGenerator()
  3030  
  3031  	// Deploy contracts
  3032  
  3033  	deployContracts(
  3034  		t,
  3035  		rt,
  3036  		contractsAddress,
  3037  		runtimeInterface,
  3038  		transactionEnvironment,
  3039  		nextTransactionLocation,
  3040  		false,
  3041  	)
  3042  
  3043  	// Run script
  3044  
  3045  	actual, err := rt.ExecuteScript(
  3046  		runtime.Script{
  3047  			Source: script,
  3048  		},
  3049  		runtime.Context{
  3050  			Interface:   runtimeInterface,
  3051  			Environment: scriptEnvironment,
  3052  			Location:    nextScriptLocation(),
  3053  		},
  3054  	)
  3055  	require.NoError(t, err)
  3056  
  3057  	expected := cadence.NewArray([]cadence.Value{
  3058  		cadence.UInt8(3),
  3059  		cadence.UInt8(1),
  3060  		cadence.UInt8(4),
  3061  	}).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type{}))
  3062  
  3063  	require.Equal(t, expected, actual)
  3064  }
  3065  
  3066  func TestEVMAddressDeposit(t *testing.T) {
  3067  
  3068  	t.Parallel()
  3069  
  3070  	expectedBalance, err := cadence.NewUFix64FromParts(1, 23000000)
  3071  	require.NoError(t, err)
  3072  
  3073  	var deposited bool
  3074  
  3075  	handler := &testContractHandler{
  3076  
  3077  		accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account {
  3078  			assert.Equal(t, types.Address{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress)
  3079  			assert.False(t, isAuthorized)
  3080  
  3081  			return &testFlowAccount{
  3082  				address: fromAddress,
  3083  				deposit: func(vault *types.FLOWTokenVault) {
  3084  					deposited = true
  3085  					assert.Equal(
  3086  						t,
  3087  						types.Balance(expectedBalance),
  3088  						vault.Balance(),
  3089  					)
  3090  				},
  3091  			}
  3092  		},
  3093  	}
  3094  
  3095  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  3096  
  3097  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  3098  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  3099  
  3100  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  3101  
  3102  	script := []byte(`
  3103        import EVM from 0x1
  3104        import FlowToken from 0x1
  3105  
  3106        access(all)
  3107        fun main() {
  3108            let admin = getAuthAccount(0x1)
  3109                .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin)!
  3110            let minter <- admin.createNewMinter(allowedAmount: 1.23)
  3111            let vault <- minter.mintTokens(amount: 1.23)
  3112            destroy minter
  3113  
  3114            let address = EVM.EVMAddress(
  3115                bytes: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  3116            )
  3117            address.deposit(from: <-vault)
  3118        }
  3119     `)
  3120  
  3121  	accountCodes := map[common.Location][]byte{}
  3122  	var events []cadence.Event
  3123  
  3124  	runtimeInterface := &TestRuntimeInterface{
  3125  		Storage: NewTestLedger(nil, nil),
  3126  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  3127  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  3128  		},
  3129  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  3130  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  3131  			accountCodes[location] = code
  3132  			return nil
  3133  		},
  3134  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  3135  			code = accountCodes[location]
  3136  			return code, nil
  3137  		},
  3138  		OnEmitEvent: func(event cadence.Event) error {
  3139  			events = append(events, event)
  3140  			return nil
  3141  		},
  3142  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  3143  			return json.Decode(nil, b)
  3144  		},
  3145  	}
  3146  
  3147  	nextTransactionLocation := NewTransactionLocationGenerator()
  3148  	nextScriptLocation := NewScriptLocationGenerator()
  3149  
  3150  	// Deploy contracts
  3151  
  3152  	deployContracts(
  3153  		t,
  3154  		rt,
  3155  		contractsAddress,
  3156  		runtimeInterface,
  3157  		transactionEnvironment,
  3158  		nextTransactionLocation,
  3159  		false,
  3160  	)
  3161  
  3162  	// Run script
  3163  
  3164  	_, err = rt.ExecuteScript(
  3165  		runtime.Script{
  3166  			Source: script,
  3167  		},
  3168  		runtime.Context{
  3169  			Interface:   runtimeInterface,
  3170  			Environment: scriptEnvironment,
  3171  			Location:    nextScriptLocation(),
  3172  		},
  3173  	)
  3174  	require.NoError(t, err)
  3175  
  3176  	require.True(t, deposited)
  3177  }
  3178  
  3179  func TestBridgedAccountWithdraw(t *testing.T) {
  3180  
  3181  	t.Parallel()
  3182  
  3183  	expectedDepositBalance, err := cadence.NewUFix64FromParts(2, 34000000)
  3184  	require.NoError(t, err)
  3185  
  3186  	expectedWithdrawBalance, err := cadence.NewUFix64FromParts(1, 23000000)
  3187  	require.NoError(t, err)
  3188  
  3189  	var deposited bool
  3190  	var withdrew bool
  3191  
  3192  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  3193  
  3194  	handler := &testContractHandler{
  3195  		flowTokenAddress: common.Address(contractsAddress),
  3196  		accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account {
  3197  			assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress)
  3198  			assert.Equal(t, deposited, isAuthorized)
  3199  
  3200  			return &testFlowAccount{
  3201  				address: fromAddress,
  3202  				deposit: func(vault *types.FLOWTokenVault) {
  3203  					deposited = true
  3204  					assert.Equal(t,
  3205  						types.Balance(expectedDepositBalance),
  3206  						vault.Balance(),
  3207  					)
  3208  				},
  3209  				withdraw: func(balance types.Balance) *types.FLOWTokenVault {
  3210  					assert.Equal(t,
  3211  						types.Balance(expectedWithdrawBalance),
  3212  						balance,
  3213  					)
  3214  					withdrew = true
  3215  					return types.NewFlowTokenVault(balance)
  3216  				},
  3217  			}
  3218  		},
  3219  	}
  3220  
  3221  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  3222  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  3223  
  3224  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  3225  
  3226  	script := []byte(`
  3227        import EVM from 0x1
  3228        import FlowToken from 0x1
  3229  
  3230        access(all)
  3231        fun main(): UFix64 {
  3232            let admin = getAuthAccount(0x1)
  3233                .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin)!
  3234            let minter <- admin.createNewMinter(allowedAmount: 2.34)
  3235            let vault <- minter.mintTokens(amount: 2.34)
  3236            destroy minter
  3237  
  3238            let bridgedAccount <- EVM.createBridgedAccount()
  3239            bridgedAccount.address().deposit(from: <-vault)
  3240  
  3241            let vault2 <- bridgedAccount.withdraw(balance: EVM.Balance(flow: 1.23))
  3242            let balance = vault2.balance
  3243            destroy bridgedAccount
  3244            destroy vault2
  3245  
  3246            return balance
  3247        }
  3248     `)
  3249  
  3250  	accountCodes := map[common.Location][]byte{}
  3251  	var events []cadence.Event
  3252  
  3253  	runtimeInterface := &TestRuntimeInterface{
  3254  		Storage: NewTestLedger(nil, nil),
  3255  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  3256  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  3257  		},
  3258  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  3259  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  3260  			accountCodes[location] = code
  3261  			return nil
  3262  		},
  3263  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  3264  			code = accountCodes[location]
  3265  			return code, nil
  3266  		},
  3267  		OnEmitEvent: func(event cadence.Event) error {
  3268  			events = append(events, event)
  3269  			return nil
  3270  		},
  3271  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  3272  			return json.Decode(nil, b)
  3273  		},
  3274  	}
  3275  
  3276  	nextTransactionLocation := NewTransactionLocationGenerator()
  3277  	nextScriptLocation := NewScriptLocationGenerator()
  3278  
  3279  	// Deploy contracts
  3280  
  3281  	deployContracts(
  3282  		t,
  3283  		rt,
  3284  		contractsAddress,
  3285  		runtimeInterface,
  3286  		transactionEnvironment,
  3287  		nextTransactionLocation,
  3288  		false,
  3289  	)
  3290  
  3291  	// Run script
  3292  
  3293  	result, err := rt.ExecuteScript(
  3294  		runtime.Script{
  3295  			Source: script,
  3296  		},
  3297  		runtime.Context{
  3298  			Interface:   runtimeInterface,
  3299  			Environment: scriptEnvironment,
  3300  			Location:    nextScriptLocation(),
  3301  		},
  3302  	)
  3303  	require.NoError(t, err)
  3304  
  3305  	assert.True(t, deposited)
  3306  	assert.True(t, withdrew)
  3307  	assert.Equal(t, expectedWithdrawBalance, result)
  3308  }
  3309  
  3310  func TestBridgedAccountDeploy(t *testing.T) {
  3311  
  3312  	t.Parallel()
  3313  
  3314  	var deployed bool
  3315  
  3316  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  3317  
  3318  	expectedBalance, err := cadence.NewUFix64FromParts(1, 23000000)
  3319  	require.NoError(t, err)
  3320  
  3321  	var handler *testContractHandler
  3322  	handler = &testContractHandler{
  3323  		flowTokenAddress: common.Address(contractsAddress),
  3324  		accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account {
  3325  			assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress)
  3326  			assert.True(t, isAuthorized)
  3327  
  3328  			return &testFlowAccount{
  3329  				address: fromAddress,
  3330  				deploy: func(code types.Code, limit types.GasLimit, balance types.Balance) types.Address {
  3331  					deployed = true
  3332  					assert.Equal(t, types.Code{4, 5, 6}, code)
  3333  					assert.Equal(t, types.GasLimit(9999), limit)
  3334  					assert.Equal(t, types.Balance(expectedBalance), balance)
  3335  
  3336  					return handler.AllocateAddress()
  3337  				},
  3338  			}
  3339  		},
  3340  	}
  3341  
  3342  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  3343  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  3344  
  3345  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  3346  
  3347  	script := []byte(`
  3348        import EVM from 0x1
  3349        import FlowToken from 0x1
  3350  
  3351        access(all)
  3352        fun main(): [UInt8; 20] {
  3353            let bridgedAccount <- EVM.createBridgedAccount()
  3354            let address = bridgedAccount.deploy(
  3355                code: [4, 5, 6],
  3356                gasLimit: 9999,
  3357                value: EVM.Balance(flow: 1.23)
  3358            )
  3359            destroy bridgedAccount
  3360            return address.bytes
  3361        }
  3362     `)
  3363  
  3364  	accountCodes := map[common.Location][]byte{}
  3365  	var events []cadence.Event
  3366  
  3367  	runtimeInterface := &TestRuntimeInterface{
  3368  		Storage: NewTestLedger(nil, nil),
  3369  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  3370  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  3371  		},
  3372  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  3373  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  3374  			accountCodes[location] = code
  3375  			return nil
  3376  		},
  3377  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  3378  			code = accountCodes[location]
  3379  			return code, nil
  3380  		},
  3381  		OnEmitEvent: func(event cadence.Event) error {
  3382  			events = append(events, event)
  3383  			return nil
  3384  		},
  3385  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  3386  			return json.Decode(nil, b)
  3387  		},
  3388  	}
  3389  
  3390  	nextTransactionLocation := NewTransactionLocationGenerator()
  3391  	nextScriptLocation := NewScriptLocationGenerator()
  3392  
  3393  	// Deploy contracts
  3394  
  3395  	deployContracts(
  3396  		t,
  3397  		rt,
  3398  		contractsAddress,
  3399  		runtimeInterface,
  3400  		transactionEnvironment,
  3401  		nextTransactionLocation,
  3402  		false,
  3403  	)
  3404  
  3405  	// Run script
  3406  
  3407  	actual, err := rt.ExecuteScript(
  3408  		runtime.Script{
  3409  			Source: script,
  3410  		},
  3411  		runtime.Context{
  3412  			Interface:   runtimeInterface,
  3413  			Environment: scriptEnvironment,
  3414  			Location:    nextScriptLocation(),
  3415  		},
  3416  	)
  3417  	require.NoError(t, err)
  3418  
  3419  	expected := cadence.NewArray([]cadence.Value{
  3420  		cadence.UInt8(2), cadence.UInt8(0),
  3421  		cadence.UInt8(0), cadence.UInt8(0),
  3422  		cadence.UInt8(0), cadence.UInt8(0),
  3423  		cadence.UInt8(0), cadence.UInt8(0),
  3424  		cadence.UInt8(0), cadence.UInt8(0),
  3425  		cadence.UInt8(0), cadence.UInt8(0),
  3426  		cadence.UInt8(0), cadence.UInt8(0),
  3427  		cadence.UInt8(0), cadence.UInt8(0),
  3428  		cadence.UInt8(0), cadence.UInt8(0),
  3429  		cadence.UInt8(0), cadence.UInt8(0),
  3430  	}).WithType(cadence.NewConstantSizedArrayType(
  3431  		types.AddressLength,
  3432  		cadence.UInt8Type{},
  3433  	))
  3434  
  3435  	require.Equal(t, expected, actual)
  3436  
  3437  	require.True(t, deployed)
  3438  }
  3439  
  3440  func TestEVMAccountBalance(t *testing.T) {
  3441  
  3442  	t.Parallel()
  3443  
  3444  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  3445  
  3446  	expectedBalanceValue, err := cadence.NewUFix64FromParts(1, 1337000)
  3447  	expectedBalance := cadence.
  3448  		NewStruct([]cadence.Value{expectedBalanceValue}).
  3449  		WithType(stdlib.NewBalanceCadenceType(common.Address(contractsAddress)))
  3450  
  3451  	require.NoError(t, err)
  3452  
  3453  	handler := &testContractHandler{
  3454  		flowTokenAddress: common.Address(contractsAddress),
  3455  		accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account {
  3456  			assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress)
  3457  			assert.False(t, isAuthorized)
  3458  
  3459  			return &testFlowAccount{
  3460  				address: fromAddress,
  3461  				balance: func() types.Balance {
  3462  					return types.Balance(expectedBalanceValue)
  3463  				},
  3464  			}
  3465  		},
  3466  	}
  3467  
  3468  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  3469  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  3470  
  3471  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  3472  
  3473  	script := []byte(`
  3474        import EVM from 0x1
  3475  
  3476        access(all)
  3477        fun main(): EVM.Balance {
  3478            let bridgedAccount <- EVM.createBridgedAccount()
  3479            let balance = bridgedAccount.balance()
  3480            destroy bridgedAccount
  3481            return balance
  3482        }
  3483      `)
  3484  
  3485  	accountCodes := map[common.Location][]byte{}
  3486  	var events []cadence.Event
  3487  
  3488  	runtimeInterface := &TestRuntimeInterface{
  3489  		Storage: NewTestLedger(nil, nil),
  3490  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  3491  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  3492  		},
  3493  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  3494  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  3495  			accountCodes[location] = code
  3496  			return nil
  3497  		},
  3498  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  3499  			code = accountCodes[location]
  3500  			return code, nil
  3501  		},
  3502  		OnEmitEvent: func(event cadence.Event) error {
  3503  			events = append(events, event)
  3504  			return nil
  3505  		},
  3506  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  3507  			return json.Decode(nil, b)
  3508  		},
  3509  	}
  3510  
  3511  	nextTransactionLocation := NewTransactionLocationGenerator()
  3512  	nextScriptLocation := NewScriptLocationGenerator()
  3513  
  3514  	// Deploy contracts
  3515  
  3516  	deployContracts(
  3517  		t,
  3518  		rt,
  3519  		contractsAddress,
  3520  		runtimeInterface,
  3521  		transactionEnvironment,
  3522  		nextTransactionLocation,
  3523  		false,
  3524  	)
  3525  
  3526  	// Run script
  3527  
  3528  	actual, err := rt.ExecuteScript(
  3529  		runtime.Script{
  3530  			Source: script,
  3531  		},
  3532  		runtime.Context{
  3533  			Interface:   runtimeInterface,
  3534  			Environment: scriptEnvironment,
  3535  			Location:    nextScriptLocation(),
  3536  		},
  3537  	)
  3538  	require.NoError(t, err)
  3539  
  3540  	require.NoError(t, err)
  3541  	require.Equal(t, expectedBalance, actual)
  3542  }
  3543  
  3544  func TestEVMAccountBalanceForABIOnlyContract(t *testing.T) {
  3545  
  3546  	t.Parallel()
  3547  
  3548  	contractsAddress := flow.BytesToAddress([]byte{0x1})
  3549  
  3550  	expectedBalanceValue, err := cadence.NewUFix64FromParts(1, 1337000)
  3551  	require.NoError(t, err)
  3552  
  3553  	handler := &testContractHandler{
  3554  		flowTokenAddress: common.Address(contractsAddress),
  3555  		accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account {
  3556  			assert.Equal(t, types.Address{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress)
  3557  			assert.False(t, isAuthorized)
  3558  
  3559  			return &testFlowAccount{
  3560  				address: fromAddress,
  3561  				balance: func() types.Balance {
  3562  					return types.Balance(expectedBalanceValue)
  3563  				},
  3564  			}
  3565  		},
  3566  	}
  3567  
  3568  	transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress)
  3569  	scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress)
  3570  
  3571  	rt := runtime.NewInterpreterRuntime(runtime.Config{})
  3572  
  3573  	script := []byte(`
  3574        import EVM from 0x1
  3575  
  3576        access(all)
  3577        fun main(): EVM.Balance {
  3578            let bridgedAccount <- EVM.createBridgedAccount()
  3579            let balance = bridgedAccount.balance()
  3580            destroy bridgedAccount
  3581            return balance
  3582        }
  3583      `)
  3584  
  3585  	accountCodes := map[common.Location][]byte{}
  3586  	var events []cadence.Event
  3587  
  3588  	runtimeInterface := &TestRuntimeInterface{
  3589  		Storage: NewTestLedger(nil, nil),
  3590  		OnGetSigningAccounts: func() ([]runtime.Address, error) {
  3591  			return []runtime.Address{runtime.Address(contractsAddress)}, nil
  3592  		},
  3593  		OnResolveLocation: SingleIdentifierLocationResolver(t),
  3594  		OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
  3595  			accountCodes[location] = code
  3596  			return nil
  3597  		},
  3598  		OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
  3599  			code = accountCodes[location]
  3600  			return code, nil
  3601  		},
  3602  		OnEmitEvent: func(event cadence.Event) error {
  3603  			events = append(events, event)
  3604  			return nil
  3605  		},
  3606  		OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
  3607  			return json.Decode(nil, b)
  3608  		},
  3609  	}
  3610  
  3611  	nextTransactionLocation := NewTransactionLocationGenerator()
  3612  	nextScriptLocation := NewScriptLocationGenerator()
  3613  
  3614  	// Deploy contracts
  3615  
  3616  	deployContracts(
  3617  		t,
  3618  		rt,
  3619  		contractsAddress,
  3620  		runtimeInterface,
  3621  		transactionEnvironment,
  3622  		nextTransactionLocation,
  3623  		true,
  3624  	)
  3625  
  3626  	// Run script
  3627  
  3628  	_, err = rt.ExecuteScript(
  3629  		runtime.Script{
  3630  			Source: script,
  3631  		},
  3632  		runtime.Context{
  3633  			Interface:   runtimeInterface,
  3634  			Environment: scriptEnvironment,
  3635  			Location:    nextScriptLocation(),
  3636  		},
  3637  	)
  3638  	require.Error(t, err)
  3639  
  3640  	assert.ErrorContains(
  3641  		t,
  3642  		err,
  3643  		"error: cannot find type in this scope: `EVM.Balance`",
  3644  	)
  3645  	assert.ErrorContains(
  3646  		t,
  3647  		err,
  3648  		"error: value of type `EVM` has no member `createBridgedAccount`",
  3649  	)
  3650  }