@@ -29,6 +29,7 @@ import (
2929 "github.com/ethereum/go-ethereum"
3030 "github.com/ethereum/go-ethereum/accounts/abi"
3131 "github.com/ethereum/go-ethereum/common"
32+ "github.com/ethereum/go-ethereum/common/hexutil"
3233 "github.com/ethereum/go-ethereum/consensus/beacon"
3334 "github.com/ethereum/go-ethereum/consensus/ethash"
3435 "github.com/ethereum/go-ethereum/core"
@@ -754,3 +755,248 @@ func ExampleRevertErrorData() {
754755 // revert: 08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a75736572206572726f72
755756 // message: user error
756757}
758+
759+ func TestSimulateV1 (t * testing.T ) {
760+ backend , _ , err := newTestBackend (nil )
761+ if err != nil {
762+ t .Fatalf ("Failed to create test backend: %v" , err )
763+ }
764+ defer backend .Close ()
765+
766+ client := ethclient .NewClient (backend .Attach ())
767+ defer client .Close ()
768+
769+ ctx := context .Background ()
770+
771+ // Get current base fee
772+ header , err := client .HeaderByNumber (ctx , nil )
773+ if err != nil {
774+ t .Fatalf ("Failed to get header: %v" , err )
775+ }
776+
777+ // Simple test: transfer ETH from one account to another
778+ from := testAddr
779+ to := common .HexToAddress ("0x0000000000000000000000000000000000000001" )
780+ value := hexutil .Big (* big .NewInt (100 ))
781+ gas := hexutil .Uint64 (100000 )
782+ maxFeePerGas := hexutil .Big (* new (big.Int ).Mul (header .BaseFee , big .NewInt (2 )))
783+
784+ opts := ethclient.SimulateOptions {
785+ BlockStateCalls : []ethclient.SimulateBlock {
786+ {
787+ Calls : []ethclient.CallArgs {
788+ {
789+ From : & from ,
790+ To : & to ,
791+ Value : & value ,
792+ Gas : & gas ,
793+ MaxFeePerGas : & maxFeePerGas ,
794+ },
795+ },
796+ },
797+ },
798+ Validation : true ,
799+ }
800+
801+ results , err := client .SimulateV1 (ctx , opts , nil )
802+ if err != nil {
803+ t .Fatalf ("SimulateV1 failed: %v" , err )
804+ }
805+
806+ if len (results ) != 1 {
807+ t .Fatalf ("expected 1 block result, got %d" , len (results ))
808+ }
809+
810+ if len (results [0 ].Calls ) != 1 {
811+ t .Fatalf ("expected 1 call result, got %d" , len (results [0 ].Calls ))
812+ }
813+
814+ // Check that the transaction succeeded
815+ if results [0 ].Calls [0 ].Status != 1 {
816+ t .Errorf ("expected status 1 (success), got %d" , results [0 ].Calls [0 ].Status )
817+ }
818+
819+ if results [0 ].Calls [0 ].Error != nil {
820+ t .Errorf ("expected no error, got %v" , results [0 ].Calls [0 ].Error )
821+ }
822+ }
823+
824+ func TestSimulateV1WithBlockOverrides (t * testing.T ) {
825+ backend , _ , err := newTestBackend (nil )
826+ if err != nil {
827+ t .Fatalf ("Failed to create test backend: %v" , err )
828+ }
829+ defer backend .Close ()
830+
831+ client := ethclient .NewClient (backend .Attach ())
832+ defer client .Close ()
833+
834+ ctx := context .Background ()
835+
836+ // Get current base fee
837+ header , err := client .HeaderByNumber (ctx , nil )
838+ if err != nil {
839+ t .Fatalf ("Failed to get header: %v" , err )
840+ }
841+
842+ from := testAddr
843+ to := common .HexToAddress ("0x0000000000000000000000000000000000000001" )
844+ value := hexutil .Big (* big .NewInt (100 ))
845+ gas := hexutil .Uint64 (100000 )
846+ maxFeePerGas := hexutil .Big (* new (big.Int ).Mul (header .BaseFee , big .NewInt (2 )))
847+
848+ // Override timestamp only
849+ timestamp := hexutil .Uint64 (1234567890 )
850+
851+ opts := ethclient.SimulateOptions {
852+ BlockStateCalls : []ethclient.SimulateBlock {
853+ {
854+ BlockOverrides : & ethclient.BlockOverrides {
855+ Time : & timestamp ,
856+ },
857+ Calls : []ethclient.CallArgs {
858+ {
859+ From : & from ,
860+ To : & to ,
861+ Value : & value ,
862+ Gas : & gas ,
863+ MaxFeePerGas : & maxFeePerGas ,
864+ },
865+ },
866+ },
867+ },
868+ Validation : true ,
869+ }
870+
871+ results , err := client .SimulateV1 (ctx , opts , nil )
872+ if err != nil {
873+ t .Fatalf ("SimulateV1 with block overrides failed: %v" , err )
874+ }
875+
876+ if len (results ) != 1 {
877+ t .Fatalf ("expected 1 block result, got %d" , len (results ))
878+ }
879+
880+ // Verify the timestamp was overridden
881+ if results [0 ].Timestamp != timestamp {
882+ t .Errorf ("expected timestamp %d, got %d" , timestamp , results [0 ].Timestamp )
883+ }
884+ }
885+
886+ func TestSimulateV1WithStateOverrides (t * testing.T ) {
887+ backend , _ , err := newTestBackend (nil )
888+ if err != nil {
889+ t .Fatalf ("Failed to create test backend: %v" , err )
890+ }
891+ defer backend .Close ()
892+
893+ client := ethclient .NewClient (backend .Attach ())
894+ defer client .Close ()
895+
896+ ctx := context .Background ()
897+
898+ // Get current base fee
899+ header , err := client .HeaderByNumber (ctx , nil )
900+ if err != nil {
901+ t .Fatalf ("Failed to get header: %v" , err )
902+ }
903+
904+ from := testAddr
905+ to := common .HexToAddress ("0x0000000000000000000000000000000000000001" )
906+ value := hexutil .Big (* big .NewInt (1000000000000000000 )) // 1 ETH
907+ gas := hexutil .Uint64 (100000 )
908+ maxFeePerGas := hexutil .Big (* new (big.Int ).Mul (header .BaseFee , big .NewInt (2 )))
909+
910+ // Override the balance of the 'from' address
911+ balanceStr := "1000000000000000000000"
912+ balance := new (big.Int )
913+ balance .SetString (balanceStr , 10 )
914+
915+ opts := ethclient.SimulateOptions {
916+ BlockStateCalls : []ethclient.SimulateBlock {
917+ {
918+ StateOverrides : & ethclient.StateOverride {
919+ from : ethclient.OverrideAccount {
920+ Balance : (* hexutil .Big )(balance ),
921+ },
922+ },
923+ Calls : []ethclient.CallArgs {
924+ {
925+ From : & from ,
926+ To : & to ,
927+ Value : & value ,
928+ Gas : & gas ,
929+ MaxFeePerGas : & maxFeePerGas ,
930+ },
931+ },
932+ },
933+ },
934+ Validation : true ,
935+ }
936+
937+ results , err := client .SimulateV1 (ctx , opts , nil )
938+ if err != nil {
939+ t .Fatalf ("SimulateV1 with state overrides failed: %v" , err )
940+ }
941+
942+ if len (results ) != 1 {
943+ t .Fatalf ("expected 1 block result, got %d" , len (results ))
944+ }
945+
946+ if results [0 ].Calls [0 ].Status != 1 {
947+ t .Errorf ("expected status 1 (success), got %d" , results [0 ].Calls [0 ].Status )
948+ }
949+ }
950+
951+ func TestSimulateV1WithBlockNumberOrHash (t * testing.T ) {
952+ backend , _ , err := newTestBackend (nil )
953+ if err != nil {
954+ t .Fatalf ("Failed to create test backend: %v" , err )
955+ }
956+ defer backend .Close ()
957+
958+ client := ethclient .NewClient (backend .Attach ())
959+ defer client .Close ()
960+
961+ ctx := context .Background ()
962+
963+ // Get current base fee
964+ header , err := client .HeaderByNumber (ctx , nil )
965+ if err != nil {
966+ t .Fatalf ("Failed to get header: %v" , err )
967+ }
968+
969+ from := testAddr
970+ to := common .HexToAddress ("0x0000000000000000000000000000000000000001" )
971+ value := hexutil .Big (* big .NewInt (100 ))
972+ gas := hexutil .Uint64 (100000 )
973+ maxFeePerGas := hexutil .Big (* new (big.Int ).Mul (header .BaseFee , big .NewInt (2 )))
974+
975+ opts := ethclient.SimulateOptions {
976+ BlockStateCalls : []ethclient.SimulateBlock {
977+ {
978+ Calls : []ethclient.CallArgs {
979+ {
980+ From : & from ,
981+ To : & to ,
982+ Value : & value ,
983+ Gas : & gas ,
984+ MaxFeePerGas : & maxFeePerGas ,
985+ },
986+ },
987+ },
988+ },
989+ Validation : true ,
990+ }
991+
992+ // Simulate on the latest block
993+ latest := rpc .BlockNumberOrHashWithNumber (rpc .LatestBlockNumber )
994+ results , err := client .SimulateV1 (ctx , opts , & latest )
995+ if err != nil {
996+ t .Fatalf ("SimulateV1 with latest block failed: %v" , err )
997+ }
998+
999+ if len (results ) != 1 {
1000+ t .Fatalf ("expected 1 block result, got %d" , len (results ))
1001+ }
1002+ }
0 commit comments