github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/evm/testutils/contract.go (about)

     1  package testutils
     2  
     3  import (
     4  	"math"
     5  	"math/big"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/onflow/atree"
    10  	gethABI "github.com/onflow/go-ethereum/accounts/abi"
    11  	"github.com/stretchr/testify/require"
    12  
    13  	"github.com/onflow/flow-go/fvm/evm/emulator"
    14  	"github.com/onflow/flow-go/fvm/evm/testutils/contracts"
    15  	"github.com/onflow/flow-go/fvm/evm/types"
    16  	"github.com/onflow/flow-go/model/flow"
    17  )
    18  
    19  type TestContract struct {
    20  	ABI        string
    21  	ByteCode   []byte
    22  	DeployedAt types.Address
    23  }
    24  
    25  func MakeCallData(t testing.TB, abiString string, name string, args ...interface{}) []byte {
    26  	abi, err := gethABI.JSON(strings.NewReader(abiString))
    27  	require.NoError(t, err)
    28  	call, err := abi.Pack(name, args...)
    29  	require.NoError(t, err)
    30  	return call
    31  }
    32  
    33  func (tc *TestContract) MakeCallData(t testing.TB, name string, args ...interface{}) []byte {
    34  	return MakeCallData(t, tc.ABI, name, args...)
    35  }
    36  
    37  func (tc *TestContract) SetDeployedAt(deployedAt types.Address) {
    38  	tc.DeployedAt = deployedAt
    39  }
    40  
    41  func GetStorageTestContract(tb testing.TB) *TestContract {
    42  	return &TestContract{
    43  		ABI:      contracts.TestContractABIJSON,
    44  		ByteCode: contracts.TestContractBytes,
    45  	}
    46  }
    47  
    48  func GetDummyKittyTestContract(t testing.TB) *TestContract {
    49  	return &TestContract{
    50  		ABI:      contracts.DummyKittyContractABIJSON,
    51  		ByteCode: contracts.DummyKittyContractBytes,
    52  	}
    53  }
    54  
    55  func RunWithDeployedContract(t testing.TB, tc *TestContract, led atree.Ledger, flowEVMRootAddress flow.Address, f func(*TestContract)) {
    56  	DeployContract(t, RandomAddress(t), tc, led, flowEVMRootAddress)
    57  	f(tc)
    58  }
    59  
    60  func DeployContract(t testing.TB, caller types.Address, tc *TestContract, led atree.Ledger, flowEVMRootAddress flow.Address) {
    61  	// deploy contract
    62  	e := emulator.NewEmulator(led, flowEVMRootAddress)
    63  
    64  	ctx := types.NewDefaultBlockContext(2)
    65  
    66  	bl, err := e.NewReadOnlyBlockView(ctx)
    67  	require.NoError(t, err)
    68  
    69  	nonce, err := bl.NonceOf(caller)
    70  	require.NoError(t, err)
    71  
    72  	blk, err := e.NewBlockView(ctx)
    73  	require.NoError(t, err)
    74  
    75  	_, err = blk.DirectCall(
    76  		types.NewDepositCall(
    77  			RandomAddress(t), // any random non-empty address works here
    78  			caller,
    79  			new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1000)),
    80  			nonce,
    81  		),
    82  	)
    83  	require.NoError(t, err)
    84  
    85  	blk2, err := e.NewBlockView(types.NewDefaultBlockContext(3))
    86  	require.NoError(t, err)
    87  
    88  	res, err := blk2.DirectCall(
    89  		types.NewDeployCall(
    90  			caller,
    91  			tc.ByteCode,
    92  			math.MaxUint64,
    93  			big.NewInt(0),
    94  			nonce+1,
    95  		),
    96  	)
    97  	require.NoError(t, err)
    98  	require.NotNil(t, res.DeployedContractAddress)
    99  	tc.SetDeployedAt(*res.DeployedContractAddress)
   100  }