Skip to content

Commit 9328628

Browse files
committed
feat: vm.PrecompiledStatefulContract can make CALLs
1 parent 53ef071 commit 9328628

File tree

1 file changed

+23
-13
lines changed

1 file changed

+23
-13
lines changed

core/vm/contracts.libevm.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -122,19 +122,9 @@ type PrecompileEnvironment interface {
122122
BlockHeader() (types.Header, error)
123123
BlockNumber() *big.Int
124124
BlockTime() uint64
125-
}
126125

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+
}
138128

139129
var _ PrecompileEnvironment = (*evmCallArgs)(nil)
140130

@@ -168,11 +158,13 @@ func (args *evmCallArgs) ReadOnlyState() libevm.StateReader {
168158
return args.evm.StateDB
169159
}
170160

161+
func (args *evmCallArgs) self() common.Address { return args.addr }
162+
171163
func (args *evmCallArgs) Addresses() *libevm.AddressContext {
172164
return &libevm.AddressContext{
173165
Origin: args.evm.TxContext.Origin,
174166
Caller: args.caller.Address(),
175-
Self: args.addr,
167+
Self: args.self(),
176168
}
177169
}
178170

@@ -194,6 +186,24 @@ func (args *evmCallArgs) BlockNumber() *big.Int {
194186

195187
func (args *evmCallArgs) BlockTime() uint64 { return args.evm.Context.Time }
196188

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+
197207
var (
198208
// These lock in the assumptions made when implementing [evmCallArgs]. If
199209
// these break then the struct fields SHOULD be changed to match these

0 commit comments

Comments
 (0)