Skip to content

Commit 55ab72c

Browse files
committed
fix: vm.WithUNSAFECallerAddressProxying under DELEGATECALL
1 parent 5ec080f commit 55ab72c

File tree

2 files changed

+28
-24
lines changed

2 files changed

+28
-24
lines changed

core/vm/contracts.libevm.go

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -153,25 +153,9 @@ func (args *evmCallArgs) env() *environment {
153153
}
154154

155155
return &environment{
156-
evm: args.evm,
157-
self: contract,
158-
forceReadOnly: args.readOnly(),
159-
}
160-
}
161-
162-
func (args *evmCallArgs) readOnly() bool {
163-
// A switch statement provides clearer code coverage for difficult-to-test
164-
// cases.
165-
switch {
166-
case args.callType == staticCall:
167-
// evm.interpreter.readOnly is only set to true via a call to
168-
// EVMInterpreter.Run() so, if a precompile is called directly with
169-
// StaticCall(), then readOnly might not be set yet.
170-
return true
171-
case args.evm.interpreter.readOnly:
172-
return true
173-
default:
174-
return false
156+
evm: args.evm,
157+
self: contract,
158+
callType: args.callType,
175159
}
176160
}
177161

core/vm/environment.libevm.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,33 @@ import (
3131
var _ PrecompileEnvironment = (*environment)(nil)
3232

3333
type environment struct {
34-
evm *EVM
35-
self *Contract
36-
forceReadOnly bool
34+
evm *EVM
35+
self *Contract
36+
callType callType
3737
}
3838

3939
func (e *environment) ChainConfig() *params.ChainConfig { return e.evm.chainConfig }
4040
func (e *environment) Rules() params.Rules { return e.evm.chainRules }
41-
func (e *environment) ReadOnly() bool { return e.forceReadOnly || e.evm.interpreter.readOnly }
4241
func (e *environment) ReadOnlyState() libevm.StateReader { return e.evm.StateDB }
4342
func (e *environment) BlockNumber() *big.Int { return new(big.Int).Set(e.evm.Context.BlockNumber) }
4443
func (e *environment) BlockTime() uint64 { return e.evm.Context.Time }
4544

45+
func (e *environment) ReadOnly() bool {
46+
// A switch statement provides clearer code coverage for difficult-to-test
47+
// cases.
48+
switch {
49+
case e.callType == staticCall:
50+
// evm.interpreter.readOnly is only set to true via a call to
51+
// EVMInterpreter.Run() so, if a precompile is called directly with
52+
// StaticCall(), then readOnly might not be set yet.
53+
return true
54+
case e.evm.interpreter.readOnly:
55+
return true
56+
default:
57+
return false
58+
}
59+
}
60+
4661
func (e *environment) Addresses() *libevm.AddressContext {
4762
return &libevm.AddressContext{
4863
Origin: e.evm.Origin,
@@ -83,7 +98,7 @@ func (e *environment) callContract(typ callType, addr common.Address, input []by
8398
in.evm.depth++
8499
defer func() { in.evm.depth-- }()
85100

86-
if e.forceReadOnly && !in.readOnly { // i.e. the precompile was StaticCall()ed
101+
if e.ReadOnly() && !in.readOnly { // i.e. the precompile was StaticCall()ed
87102
in.readOnly = true
88103
defer func() { in.readOnly = false }()
89104
}
@@ -95,6 +110,11 @@ func (e *environment) callContract(typ callType, addr common.Address, input []by
95110
// Note that, in addition to being unsafe, this breaks an EVM
96111
// assumption that the caller ContractRef is always a *Contract.
97112
caller = AccountRef(e.self.CallerAddress)
113+
if e.callType == delegateCall {
114+
// self was created with AsDelegate(), which means that
115+
// CallerAddress was inherited.
116+
caller = AccountRef(e.self.Address())
117+
}
98118
case nil:
99119
default:
100120
return nil, gas, fmt.Errorf("unsupported option %T", o)

0 commit comments

Comments
 (0)