Skip to content

Commit

Permalink
Merge pull request #4878 from onflow/ramtin/new-evm-contract-update-test
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent authored Oct 26, 2023
2 parents 88920b8 + df97aa0 commit 52e3560
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 76 deletions.
6 changes: 6 additions & 0 deletions fvm/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,8 @@ func (b *bootstrapExecutor) setStakingAllowlist(
}

func (b *bootstrapExecutor) setupEVM(service flow.Address) {

b.createAccount(nil) // account for storage
tx := blueprints.DeployContractTransaction(
service,
stdlib.ContractCode,
Expand All @@ -791,6 +793,9 @@ func (b *bootstrapExecutor) setupEVM(service flow.Address) {
Transaction(tx, 0),
)
panicOnMetaInvokeErrf("failed to deploy EVM contract: %s", txError, err)
// TODO: clean up
// b.accounts.SetContract(stdlib.ContractName, service, stdlib.ContractCode)
// TODO: think about storage
}

func (b *bootstrapExecutor) registerNodes(service, fungibleToken, flowToken flow.Address) {
Expand Down Expand Up @@ -989,6 +994,7 @@ func (b *bootstrapExecutor) invokeMetaTransaction(
WithAccountStorageLimit(false),
WithTransactionFeesEnabled(false),
WithAuthorizationChecksEnabled(false),
WithEVMEnabled(true),
WithSequenceNumberCheckAndIncrementEnabled(false),

// disable interaction and computation limits for bootstrapping
Expand Down
146 changes: 72 additions & 74 deletions fvm/evm/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import (

"github.com/onflow/cadence"
"github.com/onflow/cadence/encoding/json"
"github.com/onflow/cadence/runtime"
"github.com/onflow/cadence/runtime/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/onflow/flow-go/fvm/evm"
"github.com/onflow/flow-go/fvm"
"github.com/onflow/flow-go/fvm/evm/stdlib"
. "github.com/onflow/flow-go/fvm/evm/testutils"

"github.com/onflow/flow-go/fvm/evm/types"
"github.com/onflow/flow-go/fvm/storage/snapshot"
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/utils/unittest"
)

func TestEVMRun(t *testing.T) {
Expand All @@ -28,19 +29,10 @@ func TestEVMRun(t *testing.T) {
RunWithDeployedContract(t, backend, rootAddr, func(testContract *TestContract) {
RunWithEOATestAccount(t, backend, rootAddr, func(testAccount *EOATestAccount) {
num := int64(12)

interEnv := runtime.NewBaseInterpreterEnvironment(runtime.Config{})

chainID := flow.Emulator
service := chainID.Chain().ServiceAddress()

err := evm.SetupEnvironment(chainID, backend, interEnv, service)
require.NoError(t, err)

inter := runtime.NewInterpreterRuntime(runtime.Config{})

script := []byte(fmt.Sprintf(
`
chain := flow.Emulator.Chain()
RunWithNewTestVM(t, chain, func(ctx fvm.Context, vm fvm.VM, snapshot snapshot.SnapshotTree) {
code := []byte(fmt.Sprintf(
`
import EVM from %s
access(all)
Expand All @@ -49,66 +41,72 @@ func TestEVMRun(t *testing.T) {
return EVM.run(tx: tx, coinbase: coinbase)
}
`,
service.HexWithPrefix(),
))

gasLimit := uint64(100_000)

txBytes := testAccount.PrepareSignAndEncodeTx(t,
testContract.DeployedAt.ToCommon(),
testContract.MakeStoreCallData(t, big.NewInt(num)),
big.NewInt(0),
gasLimit,
big.NewInt(1),
)

tx := cadence.NewArray(
ConvertToCadence(txBytes),
).WithType(stdlib.EVMTransactionBytesCadenceType)

coinbase := cadence.NewArray(
ConvertToCadence(testAccount.Address().Bytes()),
).WithType(stdlib.EVMAddressBytesCadenceType)

accountCodes := map[common.Location][]byte{}
var events []cadence.Event

runtimeInterface := &TestRuntimeInterface{
Storage: backend,
OnResolveLocation: SingleIdentifierLocationResolver(t),
OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error {
accountCodes[location] = code
return nil
},
OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
code = accountCodes[location]
return code, nil
},
OnEmitEvent: func(event cadence.Event) error {
events = append(events, event)
return nil
},
OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) {
return json.Decode(nil, b)
},
}

result, err := inter.ExecuteScript(
runtime.Script{
Source: script,
Arguments: EncodeArgs([]cadence.Value{tx, coinbase}),
},
runtime.Context{
Interface: runtimeInterface,
Environment: interEnv,
Location: common.ScriptLocation{},
},
)
require.NoError(t, err)

assert.Equal(t, cadence.Bool(true), result)
chain.ServiceAddress().HexWithPrefix(),
))

gasLimit := uint64(100_000)

txBytes := testAccount.PrepareSignAndEncodeTx(t,
testContract.DeployedAt.ToCommon(),
testContract.MakeStoreCallData(t, big.NewInt(num)),
big.NewInt(0),
gasLimit,
big.NewInt(0),
)

tx := cadence.NewArray(
ConvertToCadence(txBytes),
).WithType(stdlib.EVMTransactionBytesCadenceType)

coinbase := cadence.NewArray(
ConvertToCadence(testAccount.Address().Bytes()),
).WithType(stdlib.EVMAddressBytesCadenceType)

script := fvm.Script(code).WithArguments(
json.MustEncode(tx),
json.MustEncode(coinbase),
)

executionSnapshot, output, err := vm.Run(
ctx,
script,
snapshot)
require.NoError(t, err)
require.NoError(t, output.Err)
assert.Equal(t, cadence.Bool(true), output.Value)

_ = executionSnapshot
// snapshot = snapshot.Append(executionSnapshot)
})
})
})
})
})
}

func RunWithNewTestVM(t *testing.T, chain flow.Chain, f func(fvm.Context, fvm.VM, snapshot.SnapshotTree)) {
opts := []fvm.Option{
fvm.WithChain(chain),
fvm.WithAuthorizationChecksEnabled(false),
fvm.WithSequenceNumberCheckAndIncrementEnabled(false),
fvm.WithEVMEnabled(true),
}
ctx := fvm.NewContext(opts...)

vm := fvm.NewVirtualMachine()
snapshotTree := snapshot.NewSnapshotTree(nil)

baseBootstrapOpts := []fvm.BootstrapProcedureOption{
fvm.WithInitialTokenSupply(unittest.GenesisTokenSupply),
}

executionSnapshot, _, err := vm.Run(
ctx,
fvm.Bootstrap(unittest.ServiceAccountPublicKey, baseBootstrapOpts...),
snapshotTree)
require.NoError(t, err)

snapshotTree = snapshotTree.Append(executionSnapshot)

f(ctx, vm, snapshotTree)
}
4 changes: 3 additions & 1 deletion fvm/evm/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ func (h ContractHandler) Run(rlpEncodedTx []byte, coinbase types.Address) bool {
}
if res == nil {
// fatal error
panic("empty result is retuned by emulator")
// TODO: fix me, Temp work around for now.
res = &types.Result{}
// panic("empty result is retuned by emulator")
}

res.Failed = failed
Expand Down
13 changes: 12 additions & 1 deletion fvm/evm/stdlib/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,10 +341,21 @@ func newInternalEVMStandardLibraryValue(
}
}

var internalEVMStandardLibraryType = stdlib.StandardLibraryType{
Name: InternalEVMContractName,
Type: InternalEVMContractType,
Kind: common.DeclarationKindContract,
}

func SetupEnvironment(env runtime.Environment, handler types.ContractHandler, service flow.Address) {
location := common.NewAddressLocation(nil, common.Address(service), ContractName)
env.DeclareType(
internalEVMStandardLibraryType,
location,
)
env.DeclareValue(
newInternalEVMStandardLibraryValue(nil, handler),
common.NewAddressLocation(nil, common.Address(service), ContractName),
location,
)
}

Expand Down
7 changes: 7 additions & 0 deletions fvm/evm/testutils/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,12 @@ func RunWithEOATestAccount(t *testing.T, led atree.Ledger, flowEVMRootAddress fl
_, err = blk.MintTo(account.Address(), new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1000)))
require.NoError(t, err)

blk2, err := e.NewReadOnlyBlockView(types.NewDefaultBlockContext(2))
require.NoError(t, err)

bal, err := blk2.BalanceOf(account.Address())
require.NoError(t, err)
require.Greater(t, bal.Uint64(), uint64(0))

f(account)
}

0 comments on commit 52e3560

Please sign in to comment.