@@ -3118,6 +3118,96 @@ func TestCadenceArch(t *testing.T) {
31183118 })
31193119}
31203120
3121+ func TestNativePrecompiles (t * testing.T ) {
3122+ t .Parallel ()
3123+
3124+ chain := flow .Emulator .Chain ()
3125+
3126+ t .Run ("testing out of gas precompile call" , func (t * testing.T ) {
3127+ t .Parallel ()
3128+
3129+ RunWithNewEnvironment (t ,
3130+ chain , func (
3131+ ctx fvm.Context ,
3132+ vm fvm.VM ,
3133+ snapshot snapshot.SnapshotTree ,
3134+ testContract * TestContract ,
3135+ testAccount * EOATestAccount ,
3136+ ) {
3137+ sc := systemcontracts .SystemContractsForChain (chain .ChainID ())
3138+ code := []byte (fmt .Sprintf (
3139+ `
3140+ import EVM from %s
3141+
3142+ transaction(tx: [UInt8], coinbaseBytes: [UInt8; 20]){
3143+ prepare(account: &Account) {
3144+ let coinbase = EVM.EVMAddress(bytes: coinbaseBytes)
3145+ let res = EVM.run(tx: tx, coinbase: coinbase)
3146+
3147+ assert(res.status == EVM.Status.failed, message: "unexpected status")
3148+ assert(res.errorCode == 301, message: "unexpected error code: \(res.errorCode)")
3149+ assert(res.errorMessage == "out of gas", message: "unexpected error message: \(res.errorMessage)")
3150+ }
3151+ }
3152+ ` ,
3153+ sc .EVMContract .Address .HexWithPrefix (),
3154+ ))
3155+
3156+ coinbaseAddr := types.Address {1 , 2 , 3 }
3157+ coinbaseBalance := getEVMAccountBalance (t , ctx , vm , snapshot , coinbaseAddr )
3158+ require .Zero (t , types .BalanceToBigInt (coinbaseBalance ).Uint64 ())
3159+
3160+ // The address below is the latest precompile on the Prague hard-fork:
3161+ // https://github.com/ethereum/go-ethereum/blob/v1.16.3/core/vm/contracts.go#L140 .
3162+ to := common .HexToAddress ("0x00000000000000000000000000000000000000011" )
3163+ innerTxBytes := testAccount .PrepareSignAndEncodeTx (t ,
3164+ to ,
3165+ nil ,
3166+ big .NewInt (1_000_000 ),
3167+ uint64 (21_000 ),
3168+ big .NewInt (1 ),
3169+ )
3170+
3171+ innerTx := cadence .NewArray (
3172+ unittest .BytesToCdcUInt8 (innerTxBytes ),
3173+ ).WithType (stdlib .EVMTransactionBytesCadenceType )
3174+
3175+ coinbase := cadence .NewArray (
3176+ unittest .BytesToCdcUInt8 (coinbaseAddr .Bytes ()),
3177+ ).WithType (stdlib .EVMAddressBytesCadenceType )
3178+
3179+ txBody , err := flow .NewTransactionBodyBuilder ().
3180+ SetScript (code ).
3181+ SetPayer (sc .FlowServiceAccount .Address ).
3182+ AddAuthorizer (sc .FlowServiceAccount .Address ).
3183+ AddArgument (json .MustEncode (innerTx )).
3184+ AddArgument (json .MustEncode (coinbase )).
3185+ Build ()
3186+ require .NoError (t , err )
3187+
3188+ tx := fvm .Transaction (txBody , 0 )
3189+
3190+ state , output , err := vm .Run (
3191+ ctx ,
3192+ tx ,
3193+ snapshot ,
3194+ )
3195+ require .NoError (t , err )
3196+ require .NoError (t , output .Err )
3197+ require .NotEmpty (t , state .WriteSet )
3198+
3199+ // assert event fields are correct
3200+ require .Len (t , output .Events , 2 )
3201+ txEvent := output .Events [0 ]
3202+ txEventPayload := TxEventToPayload (t , txEvent , sc .EVMContract .Address )
3203+ require .Equal (t , uint16 (types .ExecutionErrCodeOutOfGas ), txEventPayload .ErrorCode )
3204+ require .Equal (t , uint16 (0 ), txEventPayload .Index )
3205+ require .Equal (t , uint64 (21000 ), txEventPayload .GasConsumed )
3206+ require .NoError (t , err )
3207+ })
3208+ })
3209+ }
3210+
31213211func TestEVMFileSystemContract (t * testing.T ) {
31223212 chain := flow .Emulator .Chain ()
31233213 sc := systemcontracts .SystemContractsForChain (chain .ChainID ())
0 commit comments