11package evm_test
22
33import (
4+ "bytes"
45 "encoding/binary"
56 "fmt"
67 "math"
78 "math/big"
89 "testing"
910
11+ "github.com/ethereum/go-ethereum/common"
1012 gethTypes "github.com/ethereum/go-ethereum/core/types"
1113 gethParams "github.com/ethereum/go-ethereum/params"
1214 "github.com/ethereum/go-ethereum/rlp"
1315 "github.com/onflow/cadence/encoding/ccf"
1416 "github.com/stretchr/testify/assert"
17+ "github.com/stretchr/testify/require"
1518
1619 "github.com/onflow/cadence"
1720 "github.com/onflow/cadence/encoding/json"
18- "github.com/stretchr/testify/require"
1921
2022 "github.com/onflow/flow-go/engine/execution/testutil"
2123 "github.com/onflow/flow-go/fvm"
@@ -3114,6 +3116,136 @@ func TestCadenceArch(t *testing.T) {
31143116 })
31153117}
31163118
3119+ func TestEVMDeployFileSystemContract (t * testing.T ) {
3120+ chain := flow .Emulator .Chain ()
3121+
3122+ RunContractWithNewEnvironment (
3123+ t ,
3124+ chain ,
3125+ GetFileSystemContract (t ),
3126+ func (
3127+ ctx fvm.Context ,
3128+ vm fvm.VM ,
3129+ snapshot snapshot.SnapshotTree ,
3130+ testContract * TestContract ,
3131+ testAccount * EOATestAccount ,
3132+ ) {
3133+ sc := systemcontracts .SystemContractsForChain (chain .ChainID ())
3134+
3135+ code := []byte (fmt .Sprintf (
3136+ `
3137+ import EVM from %s
3138+
3139+ transaction(tx: [UInt8], coinbaseBytes: [UInt8; 20]){
3140+ prepare(account: &Account) {
3141+ let coinbase = EVM.EVMAddress(bytes: coinbaseBytes)
3142+ let res = EVM.run(tx: tx, coinbase: coinbase)
3143+
3144+ assert(res.status == EVM.Status.successful, message: "unexpected status")
3145+ assert(res.errorCode == 0, message: "unexpected error code")
3146+ assert(res.deployedContract == nil, message: "unexpected deployed contract")
3147+ }
3148+ }
3149+ ` ,
3150+ sc .EVMContract .Address .HexWithPrefix (),
3151+ ))
3152+
3153+ coinbaseAddr := types.Address {1 , 2 , 3 }
3154+ coinbaseBalance := getEVMAccountBalance (t , ctx , vm , snapshot , coinbaseAddr )
3155+ require .Zero (t , types .BalanceToBigInt (coinbaseBalance ).Uint64 ())
3156+
3157+ var buffer bytes.Buffer
3158+ address := common .HexToAddress ("0xea02F564664A477286B93712829180be4764fAe2" )
3159+ chunkHash := "0x2521660d04da85198d1cc71c20a69b7e875ebbf1682f6a5c6a3fec69068ccc13"
3160+ index := int64 (0 )
3161+ chunk := "T1ARYBYsPOJPVYoU7wVp+PYuXmdS6bgkLf2egcxa+1hP64wAxfkLXtnllU6DmEuj+Id4oWl1ZV4ftQ+ofQ3DQhOoxNlPZGOYbhoMLuzE"
3162+ for i := 0 ; i <= 500 ; i ++ {
3163+ buffer .WriteString (chunk )
3164+ }
3165+ innerTxBytes := testAccount .PrepareSignAndEncodeTx (t ,
3166+ testContract .DeployedAt .ToCommon (),
3167+ testContract .MakeCallData (
3168+ t ,
3169+ "publishChunk" ,
3170+ address ,
3171+ chunkHash ,
3172+ big .NewInt (index ),
3173+ buffer .String (),
3174+ ),
3175+ big .NewInt (0 ),
3176+ uint64 (2_500_000 ),
3177+ big .NewInt (1 ),
3178+ )
3179+
3180+ innerTx := cadence .NewArray (
3181+ unittest .BytesToCdcUInt8 (innerTxBytes ),
3182+ ).WithType (stdlib .EVMTransactionBytesCadenceType )
3183+
3184+ coinbase := cadence .NewArray (
3185+ unittest .BytesToCdcUInt8 (coinbaseAddr .Bytes ()),
3186+ ).WithType (stdlib .EVMAddressBytesCadenceType )
3187+
3188+ txBody , err := flow .NewTransactionBodyBuilder ().
3189+ SetScript (code ).
3190+ AddAuthorizer (sc .FlowServiceAccount .Address ).
3191+ AddArgument (json .MustEncode (innerTx )).
3192+ AddArgument (json .MustEncode (coinbase )).
3193+ Build ()
3194+ require .NoError (t , err )
3195+
3196+ tx := fvm .Transaction (
3197+ txBody ,
3198+ 0 ,
3199+ )
3200+
3201+ state , output , err := vm .Run (ctx , tx , snapshot )
3202+ require .NoError (t , err )
3203+ require .NoError (t , output .Err )
3204+ require .NotEmpty (t , state .WriteSet )
3205+ snapshot = snapshot .Append (state )
3206+
3207+ // assert event fields are correct
3208+ require .Len (t , output .Events , 2 )
3209+ txEvent := output .Events [0 ]
3210+ txEventPayload := TxEventToPayload (t , txEvent , sc .EVMContract .Address )
3211+ require .NoError (t , err )
3212+
3213+ // fee transfer event
3214+ feeTransferEvent := output .Events [1 ]
3215+ feeTranferEventPayload := TxEventToPayload (t , feeTransferEvent , sc .EVMContract .Address )
3216+ require .NoError (t , err )
3217+ require .Equal (t , uint16 (types .ErrCodeNoError ), feeTranferEventPayload .ErrorCode )
3218+ require .Equal (t , uint16 (1 ), feeTranferEventPayload .Index )
3219+ require .Equal (t , uint64 (21000 ), feeTranferEventPayload .GasConsumed )
3220+
3221+ // commit block
3222+ blockEventPayload , _ := callEVMHeartBeat (t ,
3223+ ctx ,
3224+ vm ,
3225+ snapshot ,
3226+ )
3227+
3228+ require .NotEmpty (t , blockEventPayload .Hash )
3229+ require .Equal (t , uint64 (2132170 ), blockEventPayload .TotalGasUsed )
3230+ require .NotEmpty (t , blockEventPayload .Hash )
3231+
3232+ txHashes := types.TransactionHashes {txEventPayload .Hash , feeTranferEventPayload .Hash }
3233+ require .Equal (t ,
3234+ txHashes .RootHash (),
3235+ blockEventPayload .TransactionHashRoot ,
3236+ )
3237+ require .NotEmpty (t , blockEventPayload .ReceiptRoot )
3238+
3239+ require .Equal (t , innerTxBytes , txEventPayload .Payload )
3240+ require .Equal (t , uint16 (types .ErrCodeNoError ), txEventPayload .ErrorCode )
3241+ require .Equal (t , uint16 (0 ), txEventPayload .Index )
3242+ require .Equal (t , blockEventPayload .Height , txEventPayload .BlockHeight )
3243+ require .Equal (t , blockEventPayload .TotalGasUsed - feeTranferEventPayload .GasConsumed , txEventPayload .GasConsumed )
3244+ require .Empty (t , txEventPayload .ContractAddress )
3245+ },
3246+ )
3247+ }
3248+
31173249func createAndFundFlowAccount (
31183250 t * testing.T ,
31193251 ctx fvm.Context ,
@@ -3404,6 +3536,62 @@ func getEVMAccountNonce(
34043536func RunWithNewEnvironment (
34053537 t * testing.T ,
34063538 chain flow.Chain ,
3539+ f func (fvm.Context , fvm.VM , snapshot.SnapshotTree , * TestContract , * EOATestAccount ),
3540+ ) {
3541+ rootAddr := evm .StorageAccountAddress (chain .ChainID ())
3542+ RunWithTestBackend (t , func (backend * TestBackend ) {
3543+ RunWithDeployedContract (t , GetStorageTestContract (t ), backend , rootAddr , func (testContract * TestContract ) {
3544+ RunWithEOATestAccount (t , backend , rootAddr , func (testAccount * EOATestAccount ) {
3545+ blocks := new (envMock.Blocks )
3546+ block1 := unittest .BlockFixture ()
3547+ blocks .On ("ByHeightFrom" ,
3548+ block1 .Height ,
3549+ block1 .ToHeader (),
3550+ ).Return (block1 .ToHeader (), nil )
3551+
3552+ opts := []fvm.Option {
3553+ fvm .WithChain (chain ),
3554+ fvm .WithBlockHeader (block1 .ToHeader ()),
3555+ fvm .WithAuthorizationChecksEnabled (false ),
3556+ fvm .WithSequenceNumberCheckAndIncrementEnabled (false ),
3557+ fvm .WithEntropyProvider (testutil .EntropyProviderFixture (nil )),
3558+ fvm .WithRandomSourceHistoryCallAllowed (true ),
3559+ fvm .WithBlocks (blocks ),
3560+ fvm .WithCadenceLogging (true ),
3561+ }
3562+ ctx := fvm .NewContext (opts ... )
3563+
3564+ vm := fvm .NewVirtualMachine ()
3565+ snapshotTree := snapshot .NewSnapshotTree (backend )
3566+
3567+ baseBootstrapOpts := []fvm.BootstrapProcedureOption {
3568+ fvm .WithInitialTokenSupply (unittest .GenesisTokenSupply ),
3569+ }
3570+
3571+ executionSnapshot , _ , err := vm .Run (
3572+ ctx ,
3573+ fvm .Bootstrap (unittest .ServiceAccountPublicKey , baseBootstrapOpts ... ),
3574+ snapshotTree )
3575+ require .NoError (t , err )
3576+
3577+ snapshotTree = snapshotTree .Append (executionSnapshot )
3578+
3579+ f (
3580+ fvm .NewContextFromParent (ctx , fvm .WithEVMEnabled (true )),
3581+ vm ,
3582+ snapshotTree ,
3583+ testContract ,
3584+ testAccount ,
3585+ )
3586+ })
3587+ })
3588+ })
3589+ }
3590+
3591+ func RunContractWithNewEnvironment (
3592+ t * testing.T ,
3593+ chain flow.Chain ,
3594+ tc * TestContract ,
34073595 f func (
34083596 fvm.Context ,
34093597 fvm.VM ,
@@ -3415,19 +3603,20 @@ func RunWithNewEnvironment(
34153603 rootAddr := evm .StorageAccountAddress (chain .ChainID ())
34163604
34173605 RunWithTestBackend (t , func (backend * TestBackend ) {
3418- RunWithDeployedContract (t , GetStorageTestContract ( t ) , backend , rootAddr , func (testContract * TestContract ) {
3606+ RunWithDeployedContract (t , tc , backend , rootAddr , func (testContract * TestContract ) {
34193607 RunWithEOATestAccount (t , backend , rootAddr , func (testAccount * EOATestAccount ) {
34203608
34213609 blocks := new (envMock.Blocks )
34223610 block1 := unittest .BlockFixture ()
3611+ header1 := block1 .ToHeader ()
34233612 blocks .On ("ByHeightFrom" ,
3424- block1 .Height ,
3425- block1 . ToHeader () ,
3426- ).Return (block1 . ToHeader () , nil )
3613+ header1 .Height ,
3614+ header1 ,
3615+ ).Return (header1 , nil )
34273616
34283617 opts := []fvm.Option {
34293618 fvm .WithChain (chain ),
3430- fvm .WithBlockHeader (block1 . ToHeader () ),
3619+ fvm .WithBlockHeader (header1 ),
34313620 fvm .WithAuthorizationChecksEnabled (false ),
34323621 fvm .WithSequenceNumberCheckAndIncrementEnabled (false ),
34333622 fvm .WithEntropyProvider (testutil .EntropyProviderFixture (nil )),
0 commit comments