@@ -341,7 +341,16 @@ fn effective_gas_limit<RT: Runtime>(system: &System<RT>, gas: U256) -> u64 {
341
341
#[ cfg( test) ]
342
342
mod tests {
343
343
use crate :: evm_unit_test;
344
+ use cid:: Cid ;
344
345
use fil_actors_evm_shared:: uints:: U256 ;
346
+ use fil_actors_runtime:: test_utils:: EVM_ACTOR_CODE_ID ;
347
+ use fvm_ipld_blockstore:: Blockstore ;
348
+ use fvm_ipld_encoding:: ipld_block:: IpldBlock ;
349
+ use fvm_ipld_encoding:: IPLD_RAW ;
350
+ use fvm_shared:: address:: Address as FilAddress ;
351
+ use fvm_shared:: error:: { ErrorNumber , ExitCode } ;
352
+ use fvm_shared:: sys:: SendFlags ;
353
+ use num_traits:: Zero ;
345
354
346
355
#[ test]
347
356
fn test_calldataload ( ) {
@@ -540,4 +549,304 @@ mod tests {
540
549
assert_eq!( m. state. memory[ 0 ..3 ] , m. bytecode[ 1 ..4 ] ) ;
541
550
} ;
542
551
}
552
+
553
+ #[ test]
554
+ fn test_call ( ) {
555
+ let dest = EthAddress :: from_id ( 1001 ) ;
556
+ let fil_dest = FilAddress :: new_id ( 1001 ) ;
557
+ let input_data = vec ! [ 0x01 , 0x02 , 0x03 , 0x04 ] ;
558
+ let output_data = vec ! [ 0xCA , 0xFE , 0xBA , 0xBE ] ;
559
+ evm_unit_test ! {
560
+ ( rt) {
561
+ rt. in_call = true ;
562
+ rt. expect_send(
563
+ fil_dest,
564
+ crate :: Method :: InvokeContract as u64 ,
565
+ Some ( IpldBlock { codec: IPLD_RAW , data: input_data } ) ,
566
+ TokenAmount :: zero( ) ,
567
+ Some ( 1_000_000_000 ) ,
568
+ SendFlags :: empty( ) ,
569
+ Some ( IpldBlock { codec: IPLD_RAW , data: output_data. clone( ) } ) ,
570
+ ExitCode :: OK ,
571
+ None ,
572
+ ) ;
573
+ rt. expect_gas_available( 10_000_000_000 ) ;
574
+ }
575
+ ( m) {
576
+ // input data
577
+ PUSH4 ; 0x01 ; 0x02 ; 0x03 ; 0x04 ;
578
+ PUSH0 ;
579
+ MSTORE ;
580
+ // the call
581
+ CALL ;
582
+ }
583
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // output size
584
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // output offset
585
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // input size
586
+ m. state. stack. push( U256 :: from( 28 ) ) . unwrap( ) ; // input offset
587
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // value
588
+ m. state. stack. push( dest. as_evm_word( ) ) . unwrap( ) ; // dest
589
+ m. state. stack. push( U256 :: from( 1_000_000_000 ) ) . unwrap( ) ; // gas
590
+ for _ in 0 ..4 {
591
+ m. step( ) . expect( "execution step failed" ) ;
592
+ }
593
+ assert_eq!( m. state. stack. len( ) , 1 ) ;
594
+ assert_eq!( m. state. stack. pop( ) . unwrap( ) , U256 :: from( 1 ) ) ;
595
+ assert_eq!( & m. state. return_data, & output_data) ;
596
+ assert_eq!( & m. state. memory[ 0 ..4 ] , & output_data) ;
597
+ } ;
598
+ }
599
+
600
+ #[ test]
601
+ fn test_call_revert ( ) {
602
+ let dest = EthAddress :: from_id ( 1001 ) ;
603
+ let fil_dest = FilAddress :: new_id ( 1001 ) ;
604
+ let input_data = vec ! [ 0x01 , 0x02 , 0x03 , 0x04 ] ;
605
+ let output_data = vec ! [ 0xCA , 0xFE , 0xBA , 0xBE ] ;
606
+ evm_unit_test ! {
607
+ ( rt) {
608
+ rt. in_call = true ;
609
+ rt. expect_send(
610
+ fil_dest,
611
+ crate :: Method :: InvokeContract as u64 ,
612
+ Some ( IpldBlock { codec: IPLD_RAW , data: input_data } ) ,
613
+ TokenAmount :: zero( ) ,
614
+ Some ( 1_000_000_000 ) ,
615
+ SendFlags :: empty( ) ,
616
+ Some ( IpldBlock { codec: IPLD_RAW , data: output_data. clone( ) } ) ,
617
+ crate :: EVM_CONTRACT_REVERTED ,
618
+ None ,
619
+ ) ;
620
+ rt. expect_gas_available( 10_000_000_000 ) ;
621
+ }
622
+ ( m) {
623
+ // input data
624
+ PUSH4 ; 0x01 ; 0x02 ; 0x03 ; 0x04 ;
625
+ PUSH0 ;
626
+ MSTORE ;
627
+ // the call
628
+ CALL ;
629
+ }
630
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // output size
631
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // output offset
632
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // input size
633
+ m. state. stack. push( U256 :: from( 28 ) ) . unwrap( ) ; // input offset
634
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // value
635
+ m. state. stack. push( dest. as_evm_word( ) ) . unwrap( ) ; // dest
636
+ m. state. stack. push( U256 :: from( 1_000_000_000 ) ) . unwrap( ) ; // gas
637
+ for _ in 0 ..4 {
638
+ m. step( ) . expect( "execution step failed" ) ;
639
+ }
640
+ assert_eq!( m. state. stack. len( ) , 1 ) ;
641
+ assert_eq!( m. state. stack. pop( ) . unwrap( ) , U256 :: from( 0 ) ) ;
642
+ assert_eq!( & m. state. return_data, & output_data) ;
643
+ assert_eq!( & m. state. memory[ 0 ..4 ] , & output_data) ;
644
+ } ;
645
+ }
646
+
647
+ #[ test]
648
+ fn test_call_err ( ) {
649
+ let dest = EthAddress :: from_id ( 1001 ) ;
650
+ let fil_dest = FilAddress :: new_id ( 1001 ) ;
651
+ let input_data = vec ! [ 0x01 , 0x02 , 0x03 , 0x04 ] ;
652
+ evm_unit_test ! {
653
+ ( rt) {
654
+ rt. in_call = true ;
655
+ rt. expect_send(
656
+ fil_dest,
657
+ crate :: Method :: InvokeContract as u64 ,
658
+ Some ( IpldBlock { codec: IPLD_RAW , data: input_data } ) ,
659
+ TokenAmount :: zero( ) ,
660
+ Some ( 1_000_000_000 ) ,
661
+ SendFlags :: empty( ) ,
662
+ None ,
663
+ ExitCode :: OK ,
664
+ Some ( ErrorNumber :: IllegalOperation ) ,
665
+ ) ;
666
+ rt. expect_gas_available( 10_000_000_000 ) ;
667
+ }
668
+ ( m) {
669
+ // input data
670
+ PUSH4 ; 0x01 ; 0x02 ; 0x03 ; 0x04 ;
671
+ PUSH0 ;
672
+ MSTORE ;
673
+ // the call
674
+ CALL ;
675
+ }
676
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // output size
677
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // output offset
678
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // input size
679
+ m. state. stack. push( U256 :: from( 28 ) ) . unwrap( ) ; // input offset
680
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // value
681
+ m. state. stack. push( dest. as_evm_word( ) ) . unwrap( ) ; // dest
682
+ m. state. stack. push( U256 :: from( 1_000_000_000 ) ) . unwrap( ) ; // gas
683
+ for _ in 0 ..4 {
684
+ m. step( ) . expect( "execution step failed" ) ;
685
+ }
686
+ assert_eq!( m. state. stack. len( ) , 1 ) ;
687
+ assert_eq!( m. state. stack. pop( ) . unwrap( ) , U256 :: from( 0 ) ) ;
688
+ assert_eq!( m. state. return_data. len( ) , 0 ) ;
689
+ } ;
690
+ }
691
+
692
+ #[ test]
693
+ fn test_call_precompile ( ) {
694
+ let mut id_bytes = [ 0u8 ; 20 ] ;
695
+ id_bytes[ 19 ] = 0x04 ;
696
+ let dest = EthAddress ( id_bytes) ;
697
+ let mut output_data = [ 0u8 ; 32 ] ;
698
+ output_data[ 28 ] = 0x01 ;
699
+ output_data[ 29 ] = 0x02 ;
700
+ output_data[ 30 ] = 0x03 ;
701
+ output_data[ 31 ] = 0x04 ;
702
+ evm_unit_test ! {
703
+ ( rt) {
704
+ rt. in_call = true ;
705
+ rt. expect_gas_available( 10_000_000_000 ) ;
706
+ }
707
+ ( m) {
708
+ // input data
709
+ PUSH4 ; 0x01 ; 0x02 ; 0x03 ; 0x04 ;
710
+ PUSH0 ;
711
+ MSTORE ;
712
+ // the call
713
+ CALL ;
714
+ }
715
+ m. state. stack. push( U256 :: from( 32 ) ) . unwrap( ) ; // output size
716
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // output offset
717
+ m. state. stack. push( U256 :: from( 32 ) ) . unwrap( ) ; // input size
718
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // input offset
719
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // value
720
+ m. state. stack. push( dest. as_evm_word( ) ) . unwrap( ) ; // dest
721
+ m. state. stack. push( U256 :: from( 1_000_000_000 ) ) . unwrap( ) ; // gas
722
+ for _ in 0 ..4 {
723
+ m. step( ) . expect( "execution step failed" ) ;
724
+ }
725
+ assert_eq!( m. state. stack. len( ) , 1 ) ;
726
+ assert_eq!( m. state. stack. pop( ) . unwrap( ) , U256 :: from( 1 ) ) ;
727
+ assert_eq!( & m. state. return_data, & output_data) ;
728
+ assert_eq!( & m. state. memory[ ..] , & output_data) ;
729
+ } ;
730
+ }
731
+
732
+ #[ test]
733
+ fn test_delegatecall ( ) {
734
+ let receiver = FilAddress :: new_id ( 1000 ) ;
735
+ let dest = EthAddress :: from_id ( 1001 ) ;
736
+ let caller = EthAddress :: from_id ( 1002 ) ;
737
+ let fil_dest = FilAddress :: new_id ( 1001 ) ;
738
+ let input_data = vec ! [ 0x01 , 0x02 , 0x03 , 0x04 ] ;
739
+ let output_data = vec ! [ 0xCA , 0xFE , 0xBA , 0xBE ] ;
740
+ evm_unit_test ! {
741
+ ( rt) {
742
+ rt. in_call = true ;
743
+ rt. receiver = receiver;
744
+ rt. set_address_actor_type( fil_dest, * EVM_ACTOR_CODE_ID ) ;
745
+
746
+ let bytecode = vec![ 0xFE , 0xED , 0x43 , 0x33 ] ;
747
+ let bytecode_cid = Cid :: try_from( "baeaikaia" ) . unwrap( ) ;
748
+ rt. store. put_keyed( & bytecode_cid, bytecode. as_slice( ) ) . unwrap( ) ;
749
+
750
+ rt. expect_send(
751
+ fil_dest,
752
+ crate :: Method :: GetBytecode as u64 ,
753
+ Default :: default ( ) ,
754
+ TokenAmount :: zero( ) ,
755
+ None ,
756
+ SendFlags :: READ_ONLY ,
757
+ IpldBlock :: serialize_cbor( & bytecode_cid) . unwrap( ) ,
758
+ ExitCode :: OK ,
759
+ None ,
760
+ ) ;
761
+
762
+ let params = crate :: DelegateCallParams {
763
+ code: bytecode_cid,
764
+ input: input_data,
765
+ caller,
766
+ value: TokenAmount :: zero( ) ,
767
+ } ;
768
+
769
+ rt. expect_send(
770
+ receiver,
771
+ crate :: Method :: InvokeContractDelegate as u64 ,
772
+ IpldBlock :: serialize_dag_cbor( & params) . unwrap( ) ,
773
+ TokenAmount :: zero( ) ,
774
+ Some ( 1_000_000_000 ) ,
775
+ SendFlags :: empty( ) ,
776
+ Some ( IpldBlock { codec: IPLD_RAW , data: output_data. clone( ) } ) ,
777
+ ExitCode :: OK ,
778
+ None ,
779
+ ) ;
780
+ rt. expect_gas_available( 10_000_000_000 ) ;
781
+ }
782
+ ( m) {
783
+ // input data
784
+ PUSH4 ; 0x01 ; 0x02 ; 0x03 ; 0x04 ;
785
+ PUSH0 ;
786
+ MSTORE ;
787
+ // the call
788
+ DELEGATECALL ;
789
+ }
790
+ m. state. caller = caller;
791
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // output size
792
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // output offset
793
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // input size
794
+ m. state. stack. push( U256 :: from( 28 ) ) . unwrap( ) ; // input offset
795
+ m. state. stack. push( dest. as_evm_word( ) ) . unwrap( ) ; // dest
796
+ m. state. stack. push( U256 :: from( 1_000_000_000 ) ) . unwrap( ) ; // gas
797
+ for _ in 0 ..4 {
798
+ m. step( ) . expect( "execution step failed" ) ;
799
+ }
800
+ assert_eq!( m. state. stack. len( ) , 1 ) ;
801
+ assert_eq!( m. state. stack. pop( ) . unwrap( ) , U256 :: from( 1 ) ) ;
802
+ assert_eq!( & m. state. return_data, & output_data) ;
803
+ assert_eq!( & m. state. memory[ 0 ..4 ] , & output_data) ;
804
+ } ;
805
+ }
806
+
807
+ #[ test]
808
+ fn test_staticcall ( ) {
809
+ let dest = EthAddress :: from_id ( 1001 ) ;
810
+ let fil_dest = FilAddress :: new_id ( 1001 ) ;
811
+ let input_data = vec ! [ 0x01 , 0x02 , 0x03 , 0x04 ] ;
812
+ let output_data = vec ! [ 0xCA , 0xFE , 0xBA , 0xBE ] ;
813
+ evm_unit_test ! {
814
+ ( rt) {
815
+ rt. in_call = true ;
816
+ rt. expect_send(
817
+ fil_dest,
818
+ crate :: Method :: InvokeContract as u64 ,
819
+ Some ( IpldBlock { codec: IPLD_RAW , data: input_data } ) ,
820
+ TokenAmount :: zero( ) ,
821
+ Some ( 1_000_000_000 ) ,
822
+ SendFlags :: READ_ONLY ,
823
+ Some ( IpldBlock { codec: IPLD_RAW , data: output_data. clone( ) } ) ,
824
+ ExitCode :: OK ,
825
+ None ,
826
+ ) ;
827
+ rt. expect_gas_available( 10_000_000_000 ) ;
828
+ }
829
+ ( m) {
830
+ // input data
831
+ PUSH4 ; 0x01 ; 0x02 ; 0x03 ; 0x04 ;
832
+ PUSH0 ;
833
+ MSTORE ;
834
+ // the call
835
+ STATICCALL ;
836
+ }
837
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // output size
838
+ m. state. stack. push( U256 :: from( 0 ) ) . unwrap( ) ; // output offset
839
+ m. state. stack. push( U256 :: from( 4 ) ) . unwrap( ) ; // input size
840
+ m. state. stack. push( U256 :: from( 28 ) ) . unwrap( ) ; // input offset
841
+ m. state. stack. push( dest. as_evm_word( ) ) . unwrap( ) ; // dest
842
+ m. state. stack. push( U256 :: from( 1_000_000_000 ) ) . unwrap( ) ; // gas
843
+ for _ in 0 ..4 {
844
+ m. step( ) . expect( "execution step failed" ) ;
845
+ }
846
+ assert_eq!( m. state. stack. len( ) , 1 ) ;
847
+ assert_eq!( m. state. stack. pop( ) . unwrap( ) , U256 :: from( 1 ) ) ;
848
+ assert_eq!( & m. state. return_data, & output_data) ;
849
+ assert_eq!( & m. state. memory[ 0 ..4 ] , & output_data) ;
850
+ } ;
851
+ }
543
852
}
0 commit comments