@@ -100,49 +100,63 @@ func (e *environment) BlockHeader() (types.Header, error) {
100100 return * hdr , nil
101101}
102102
103- func (e * environment ) Call (addr common.Address , input []byte , gas uint64 , value * uint256.Int , opts ... CallOption ) ([]byte , error ) {
104- return e .callContract (Call , addr , input , gas , value , opts ... )
105- }
106-
107- func (e * environment ) callContract (typ CallType , addr common.Address , input []byte , gas uint64 , value * uint256.Int , opts ... CallOption ) (retData []byte , retErr error ) {
103+ func (e * environment ) beforeNewCallFrame (typ CallType , gas uint64 , value * uint256.Int , opts ... CallOption ) (ContractRef , func (), error ) {
108104 // Depth and read-only setting are handled by [EVMInterpreter.Run], which
109105 // isn't used for precompiles, so we need to do it ourselves to maintain the
110106 // expected invariants.
111107 in := e .evm .interpreter
108+ var deferred []func ()
112109
113110 in .evm .depth ++
114- defer func () { in .evm .depth -- }( )
111+ deferred = append ( deferred , func () { in .evm .depth -- })
115112
116113 if e .ReadOnly () && ! in .readOnly { // i.e. the precompile was StaticCall()ed
117114 in .readOnly = true
118- defer func () { in .readOnly = false }( )
115+ deferred = append ( deferred , func () { in .readOnly = false })
119116 }
120117
121- var caller ContractRef = e .self
122- for _ , o := range opts {
123- switch o := o .(type ) {
124- case callOptUNSAFECallerAddressProxy :
125- // Note that, in addition to being unsafe, this breaks an EVM
126- // assumption that the caller ContractRef is always a *Contract.
127- caller = AccountRef (e .self .CallerAddress )
128- if e .callType == DelegateCall {
129- // self was created with AsDelegate(), which means that
130- // CallerAddress was inherited.
131- caller = AccountRef (e .self .Address ())
132- }
133- case nil :
134- default :
135- return nil , fmt .Errorf ("unsupported option %T" , o )
118+ var (
119+ caller ContractRef = e .self
120+ config libevmCallConfig
121+ )
122+ config .apply (opts ... )
123+ if config .proxyCallerAddressUNSAFE {
124+ // Note that, in addition to being unsafe, this breaks an EVM
125+ // assumption that the caller ContractRef is always a *Contract.
126+ caller = AccountRef (e .self .CallerAddress )
127+ if e .callType == DelegateCall {
128+ // self was created with AsDelegate(), which means that
129+ // CallerAddress was inherited.
130+ caller = AccountRef (e .self .Address ())
136131 }
137132 }
138133
139- if in .readOnly && value != nil && ! value .IsZero () {
140- return nil , ErrWriteProtection
134+ writes := (value != nil && ! value .IsZero ()) || typ == create || typ == create2
135+ if in .readOnly && writes {
136+ return nil , nil , ErrWriteProtection
141137 }
142138 if ! e .UseGas (gas ) {
143- return nil , ErrOutOfGas
139+ return nil , nil , ErrOutOfGas
144140 }
145141
142+ return caller , func () {
143+ for _ , fn := range deferred {
144+ fn ()
145+ }
146+ }, nil
147+ }
148+
149+ func (e * environment ) Call (addr common.Address , input []byte , gas uint64 , value * uint256.Int , opts ... CallOption ) ([]byte , error ) {
150+ return e .callContract (Call , addr , input , gas , value , opts ... )
151+ }
152+
153+ func (e * environment ) callContract (typ CallType , addr common.Address , input []byte , gas uint64 , value * uint256.Int , opts ... CallOption ) (retData []byte , retErr error ) {
154+ caller , cleanup , err := e .beforeNewCallFrame (typ , gas , value , opts ... )
155+ if err != nil {
156+ return nil , err
157+ }
158+ defer cleanup ()
159+
146160 if t := e .evm .Config .Tracer ; t != nil {
147161 var bigVal * big.Int
148162 if value != nil {
@@ -174,3 +188,31 @@ func (e *environment) callContract(typ CallType, addr common.Address, input []by
174188 return nil , fmt .Errorf ("unimplemented precompile call type %v" , typ )
175189 }
176190}
191+
192+ func (e * environment ) Create (code []byte , gas uint64 , value * uint256.Int ) ([]byte , common.Address , error ) {
193+ return e .create (create , gas , value , func (caller ContractRef ) ([]byte , common.Address , uint64 , error ) {
194+ return e .evm .Create (caller , code , gas , value )
195+ })
196+ }
197+
198+ func (e * environment ) Create2 (code []byte , gas uint64 , value , salt * uint256.Int ) ([]byte , common.Address , error ) {
199+ return e .create (create2 , gas , value , func (caller ContractRef ) ([]byte , common.Address , uint64 , error ) {
200+ return e .evm .Create2 (caller , code , gas , value , salt )
201+ })
202+ }
203+
204+ type creator func (ContractRef ) ([]byte , common.Address , uint64 , error )
205+
206+ func (e * environment ) create (typ CallType , gas uint64 , value * uint256.Int , do creator ) ([]byte , common.Address , error ) {
207+ caller , cleanup , err := e .beforeNewCallFrame (typ , gas , value )
208+ if err != nil {
209+ return nil , common.Address {}, err
210+ }
211+ defer cleanup ()
212+
213+ ret , contract , returnGas , err := do (caller )
214+ if err := e .refundGas (returnGas ); err != nil {
215+ return nil , common.Address {}, err
216+ }
217+ return ret , contract , err
218+ }
0 commit comments