@@ -122,19 +122,9 @@ type PrecompileEnvironment interface {
122
122
BlockHeader () (types.Header , error )
123
123
BlockNumber () * big.Int
124
124
BlockTime () uint64
125
- }
126
125
127
- //
128
- // ****** SECURITY ******
129
- //
130
- // If you are updating PrecompileEnvironment to provide the ability to call back
131
- // into another contract, you MUST revisit the evmCallArgs.forceReadOnly flag.
132
- //
133
- // It is possible that forceReadOnly is true but evm.interpreter.readOnly is
134
- // false. This is safe for now, but may not be if recursive calling *from* a
135
- // precompile is enabled.
136
- //
137
- // ****** SECURITY ******
126
+ Call (common.Address , []byte , uint64 , * uint256.Int ) ([]byte , uint64 , error )
127
+ }
138
128
139
129
var _ PrecompileEnvironment = (* evmCallArgs )(nil )
140
130
@@ -168,11 +158,13 @@ func (args *evmCallArgs) ReadOnlyState() libevm.StateReader {
168
158
return args .evm .StateDB
169
159
}
170
160
161
+ func (args * evmCallArgs ) self () common.Address { return args .addr }
162
+
171
163
func (args * evmCallArgs ) Addresses () * libevm.AddressContext {
172
164
return & libevm.AddressContext {
173
165
Origin : args .evm .TxContext .Origin ,
174
166
Caller : args .caller .Address (),
175
- Self : args .addr ,
167
+ Self : args .self () ,
176
168
}
177
169
}
178
170
@@ -194,6 +186,24 @@ func (args *evmCallArgs) BlockNumber() *big.Int {
194
186
195
187
func (args * evmCallArgs ) BlockTime () uint64 { return args .evm .Context .Time }
196
188
189
+ func (args * evmCallArgs ) Call (addr common.Address , input []byte , gas uint64 , value * uint256.Int ) ([]byte , uint64 , error ) {
190
+ in := args .evm .interpreter
191
+
192
+ // The precompile run didn't increment the depth so this is necessary even
193
+ // though Call() will eventually result in it being done again.
194
+ in .evm .depth ++
195
+ defer func () { in .evm .depth -- }()
196
+
197
+ // This will happen if the precompile was invoked via StaticCall() from a
198
+ // non read-only state.
199
+ if args .readWrite == forceReadOnly && ! in .readOnly {
200
+ in .readOnly = true
201
+ defer func () { in .readOnly = false }()
202
+ }
203
+
204
+ return args .evm .Call (AccountRef (args .self ()), addr , input , gas , value )
205
+ }
206
+
197
207
var (
198
208
// These lock in the assumptions made when implementing [evmCallArgs]. If
199
209
// these break then the struct fields SHOULD be changed to match these
0 commit comments