@@ -3,6 +3,8 @@ package vm_test
33import (
44 "fmt"
55 "math/big"
6+ "reflect"
7+ "strings"
68 "testing"
79
810 "github.com/holiman/uint256"
@@ -11,6 +13,8 @@ import (
1113 "golang.org/x/exp/rand"
1214
1315 "github.com/ethereum/go-ethereum/common"
16+ "github.com/ethereum/go-ethereum/core"
17+ "github.com/ethereum/go-ethereum/core/types"
1418 "github.com/ethereum/go-ethereum/core/vm"
1519 "github.com/ethereum/go-ethereum/crypto"
1620 "github.com/ethereum/go-ethereum/libevm"
@@ -79,6 +83,31 @@ func TestPrecompileOverride(t *testing.T) {
7983 }
8084}
8185
86+ type statefulPrecompileOutput struct {
87+ Caller , Self common.Address
88+ StateValue common.Hash
89+ ReadOnly bool
90+ BlockNumber , Difficulty * big.Int
91+ BlockTime uint64
92+ Input []byte
93+ }
94+
95+ func (o statefulPrecompileOutput ) String () string {
96+ var lines []string
97+ out := reflect .ValueOf (o )
98+ for i , n := 0 , out .NumField (); i < n ; i ++ {
99+ name := out .Type ().Field (i ).Name
100+ fld := out .Field (i ).Interface ()
101+
102+ verb := "%v"
103+ if _ , ok := fld .([]byte ); ok {
104+ verb = "%#x"
105+ }
106+ lines = append (lines , fmt .Sprintf ("%s: " + verb , name , fld ))
107+ }
108+ return strings .Join (lines , "\n " )
109+ }
110+
82111func TestNewStatefulPrecompile (t * testing.T ) {
83112 rng := ethtest .NewPseudoRand (314159 )
84113 precompile := rng .Address ()
@@ -87,20 +116,27 @@ func TestNewStatefulPrecompile(t *testing.T) {
87116 const gasLimit = 1e6
88117 gasCost := rng .Uint64n (gasLimit )
89118
90- makeOutput := func (caller , self common.Address , input []byte , stateVal common.Hash , readOnly bool ) []byte {
91- return []byte (fmt .Sprintf (
92- "Caller: %v Precompile: %v State: %v Read-only: %t, Input: %#x" ,
93- caller , self , stateVal , readOnly , input ,
94- ))
95- }
96119 run := func (env vm.PrecompileEnvironment , input []byte , suppliedGas uint64 ) ([]byte , uint64 , error ) {
97120 if got , want := env .StateDB () != nil , ! env .ReadOnly (); got != want {
98121 return nil , 0 , fmt .Errorf ("PrecompileEnvironment().StateDB() must be non-nil i.f.f. not read-only; got non-nil? %t; want %t" , got , want )
99122 }
123+ hdr , err := env .BlockHeader ()
124+ if err != nil {
125+ return nil , 0 , err
126+ }
100127
101128 addrs := env .Addresses ()
102- val := env .ReadOnlyState ().GetState (precompile , slot )
103- return makeOutput (addrs .Caller , addrs .Self , input , val , env .ReadOnly ()), suppliedGas - gasCost , nil
129+ out := & statefulPrecompileOutput {
130+ Caller : addrs .Caller ,
131+ Self : addrs .Self ,
132+ StateValue : env .ReadOnlyState ().GetState (precompile , slot ),
133+ ReadOnly : env .ReadOnly (),
134+ BlockNumber : env .BlockNumber (),
135+ BlockTime : env .BlockTime (),
136+ Difficulty : hdr .Difficulty ,
137+ Input : input ,
138+ }
139+ return []byte (out .String ()), suppliedGas - gasCost , nil
104140 }
105141 hooks := & hookstest.Stub {
106142 PrecompileOverrides : map [common.Address ]libevm.PrecompiledContract {
@@ -109,11 +145,18 @@ func TestNewStatefulPrecompile(t *testing.T) {
109145 }
110146 hooks .Register (t )
111147
148+ header := & types.Header {
149+ Number : rng .BigUint64 (),
150+ Time : rng .Uint64 (),
151+ Difficulty : rng .BigUint64 (),
152+ }
112153 caller := rng .Address ()
113154 input := rng .Bytes (8 )
114155 value := rng .Hash ()
115156
116- state , evm := ethtest .NewZeroEVM (t )
157+ state , evm := ethtest .NewZeroEVM (t , ethtest .WithBlockContext (
158+ core .NewEVMBlockContext (header , nil , rng .AddressPtr ()),
159+ ))
117160 state .SetState (precompile , slot , value )
118161
119162 tests := []struct {
@@ -155,12 +198,21 @@ func TestNewStatefulPrecompile(t *testing.T) {
155198
156199 for _ , tt := range tests {
157200 t .Run (tt .name , func (t * testing.T ) {
158- wantReturnData := makeOutput (caller , precompile , input , value , tt .wantReadOnly )
201+ wantReturnData := statefulPrecompileOutput {
202+ Caller : caller ,
203+ Self : precompile ,
204+ StateValue : value ,
205+ ReadOnly : tt .wantReadOnly ,
206+ BlockNumber : header .Number ,
207+ BlockTime : header .Time ,
208+ Difficulty : header .Difficulty ,
209+ Input : input ,
210+ }.String ()
159211 wantGasLeft := gasLimit - gasCost
160212
161213 gotReturnData , gotGasLeft , err := tt .call ()
162214 require .NoError (t , err )
163- assert .Equal (t , string ( wantReturnData ) , string (gotReturnData ))
215+ assert .Equal (t , wantReturnData , string (gotReturnData ))
164216 assert .Equal (t , wantGasLeft , gotGasLeft )
165217 })
166218 }
0 commit comments