@@ -391,6 +391,174 @@ func TestEVMRun(t *testing.T) {
391
391
assert .Equal (t , num , last .Big ().Int64 ())
392
392
})
393
393
})
394
+
395
+ t .Run ("testing EVM.run execution reverted with assert error" , func (t * testing.T ) {
396
+
397
+ t .Parallel ()
398
+
399
+ RunWithNewEnvironment (t ,
400
+ chain , func (
401
+ ctx fvm.Context ,
402
+ vm fvm.VM ,
403
+ snapshot snapshot.SnapshotTree ,
404
+ testContract * TestContract ,
405
+ testAccount * EOATestAccount ,
406
+ ) {
407
+ sc := systemcontracts .SystemContractsForChain (chain .ChainID ())
408
+ code := []byte (fmt .Sprintf (
409
+ `
410
+ import EVM from %s
411
+
412
+ transaction(tx: [UInt8], coinbaseBytes: [UInt8; 20]){
413
+ prepare(account: &Account) {
414
+ let coinbase = EVM.EVMAddress(bytes: coinbaseBytes)
415
+ let res = EVM.run(tx: tx, coinbase: coinbase)
416
+
417
+ assert(res.status == EVM.Status.failed, message: "unexpected status")
418
+ assert(res.errorCode == 306, message: "unexpected error code")
419
+ assert(res.deployedContract == nil, message: "unexpected deployed contract")
420
+ }
421
+ }
422
+ ` ,
423
+ sc .EVMContract .Address .HexWithPrefix (),
424
+ ))
425
+
426
+ coinbaseAddr := types.Address {1 , 2 , 3 }
427
+ coinbaseBalance := getEVMAccountBalance (t , ctx , vm , snapshot , coinbaseAddr )
428
+ require .Zero (t , types .BalanceToBigInt (coinbaseBalance ).Uint64 ())
429
+
430
+ innerTxBytes := testAccount .PrepareSignAndEncodeTx (t ,
431
+ testContract .DeployedAt .ToCommon (),
432
+ testContract .MakeCallData (t , "assertError" ),
433
+ big .NewInt (0 ),
434
+ uint64 (100_000 ),
435
+ big .NewInt (1 ),
436
+ )
437
+
438
+ innerTx := cadence .NewArray (
439
+ ConvertToCadence (innerTxBytes ),
440
+ ).WithType (stdlib .EVMTransactionBytesCadenceType )
441
+
442
+ coinbase := cadence .NewArray (
443
+ ConvertToCadence (coinbaseAddr .Bytes ()),
444
+ ).WithType (stdlib .EVMAddressBytesCadenceType )
445
+
446
+ tx := fvm .Transaction (
447
+ flow .NewTransactionBody ().
448
+ SetScript (code ).
449
+ AddAuthorizer (sc .FlowServiceAccount .Address ).
450
+ AddArgument (json .MustEncode (innerTx )).
451
+ AddArgument (json .MustEncode (coinbase )),
452
+ 0 )
453
+
454
+ state , output , err := vm .Run (
455
+ ctx ,
456
+ tx ,
457
+ snapshot ,
458
+ )
459
+ require .NoError (t , err )
460
+ require .NoError (t , output .Err )
461
+ require .NotEmpty (t , state .WriteSet )
462
+
463
+ // assert event fields are correct
464
+ require .Len (t , output .Events , 2 )
465
+ txEvent := output .Events [0 ]
466
+ txEventPayload := TxEventToPayload (t , txEvent , sc .EVMContract .Address )
467
+ require .NoError (t , err )
468
+
469
+ assert .Equal (
470
+ t ,
471
+ "execution reverted: Assert Error Message" ,
472
+ txEventPayload .ErrorMessage ,
473
+ )
474
+ },
475
+ )
476
+ })
477
+
478
+ t .Run ("testing EVM.run execution reverted with custom error" , func (t * testing.T ) {
479
+
480
+ t .Parallel ()
481
+
482
+ RunWithNewEnvironment (t ,
483
+ chain , func (
484
+ ctx fvm.Context ,
485
+ vm fvm.VM ,
486
+ snapshot snapshot.SnapshotTree ,
487
+ testContract * TestContract ,
488
+ testAccount * EOATestAccount ,
489
+ ) {
490
+ sc := systemcontracts .SystemContractsForChain (chain .ChainID ())
491
+ code := []byte (fmt .Sprintf (
492
+ `
493
+ import EVM from %s
494
+
495
+ transaction(tx: [UInt8], coinbaseBytes: [UInt8; 20]){
496
+ prepare(account: &Account) {
497
+ let coinbase = EVM.EVMAddress(bytes: coinbaseBytes)
498
+ let res = EVM.run(tx: tx, coinbase: coinbase)
499
+
500
+ assert(res.status == EVM.Status.failed, message: "unexpected status")
501
+ assert(res.errorCode == 306, message: "unexpected error code")
502
+ assert(res.deployedContract == nil, message: "unexpected deployed contract")
503
+ }
504
+ }
505
+ ` ,
506
+ sc .EVMContract .Address .HexWithPrefix (),
507
+ ))
508
+
509
+ coinbaseAddr := types.Address {1 , 2 , 3 }
510
+ coinbaseBalance := getEVMAccountBalance (t , ctx , vm , snapshot , coinbaseAddr )
511
+ require .Zero (t , types .BalanceToBigInt (coinbaseBalance ).Uint64 ())
512
+
513
+ innerTxBytes := testAccount .PrepareSignAndEncodeTx (t ,
514
+ testContract .DeployedAt .ToCommon (),
515
+ testContract .MakeCallData (t , "customError" ),
516
+ big .NewInt (0 ),
517
+ uint64 (100_000 ),
518
+ big .NewInt (1 ),
519
+ )
520
+
521
+ innerTx := cadence .NewArray (
522
+ ConvertToCadence (innerTxBytes ),
523
+ ).WithType (stdlib .EVMTransactionBytesCadenceType )
524
+
525
+ coinbase := cadence .NewArray (
526
+ ConvertToCadence (coinbaseAddr .Bytes ()),
527
+ ).WithType (stdlib .EVMAddressBytesCadenceType )
528
+
529
+ tx := fvm .Transaction (
530
+ flow .NewTransactionBody ().
531
+ SetScript (code ).
532
+ AddAuthorizer (sc .FlowServiceAccount .Address ).
533
+ AddArgument (json .MustEncode (innerTx )).
534
+ AddArgument (json .MustEncode (coinbase )),
535
+ 0 )
536
+
537
+ state , output , err := vm .Run (
538
+ ctx ,
539
+ tx ,
540
+ snapshot ,
541
+ )
542
+ require .NoError (t , err )
543
+ require .NoError (t , output .Err )
544
+ require .NotEmpty (t , state .WriteSet )
545
+
546
+ // assert event fields are correct
547
+ require .Len (t , output .Events , 2 )
548
+ txEvent := output .Events [0 ]
549
+ txEventPayload := TxEventToPayload (t , txEvent , sc .EVMContract .Address )
550
+ require .NoError (t , err )
551
+
552
+ // Unlike assert errors, custom errors cannot be further examined
553
+ // or ABI decoded, as we do not have access to the contract's ABI.
554
+ assert .Equal (
555
+ t ,
556
+ "execution reverted" ,
557
+ txEventPayload .ErrorMessage ,
558
+ )
559
+ },
560
+ )
561
+ })
394
562
}
395
563
396
564
func TestEVMBatchRun (t * testing.T ) {
0 commit comments