Skip to content

Commit 51cd795

Browse files
authored
fix: vm.WithUNSAFECallerAddressProxying under DELEGATECALL (#50)
* fix: `vm.WithUNSAFECallerAddressProxying` under `DELEGATECALL` * test: `vm.WithUNSAFECallerAddressProxying()` effect on outgoing caller addr * chore: mark `eth/tracers/js` test flaky * feat: `vm.PrecompileEnvironment.IncomingCallType()` * chore: minor documentation edit * doc: `PrecompileEnvironment` example for determining actual caller * chore: placate the linter
1 parent 5ec080f commit 51cd795

File tree

5 files changed

+190
-72
lines changed

5 files changed

+190
-72
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ jobs:
1818
go-version: 1.21.4
1919
- name: Run tests
2020
run: | # Upstream flakes are race conditions exacerbated by concurrent tests
21-
FLAKY_REGEX='go-ethereum/(eth|eth/tracers/logger|accounts/keystore|eth/downloader|miner|ethclient|ethclient/gethclient|eth/catalyst)$';
21+
FLAKY_REGEX='go-ethereum/(eth|eth/tracers/js|eth/tracers/logger|accounts/keystore|eth/downloader|miner|ethclient|ethclient/gethclient|eth/catalyst)$';
2222
go list ./... | grep -P "${FLAKY_REGEX}" | xargs -n 1 go test -short;
2323
go test -short $(go list ./... | grep -Pv "${FLAKY_REGEX}");

core/vm/contracts.libevm.go

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import (
4242
// args := &evmCallArgs{evm, staticCall, caller, addr, input, gas, nil /*value*/}
4343
type evmCallArgs struct {
4444
evm *EVM
45-
callType callType
45+
callType CallType
4646

4747
// args:start
4848
caller ContractRef
@@ -53,15 +53,32 @@ type evmCallArgs struct {
5353
// args:end
5454
}
5555

56-
type callType uint8
56+
// A CallType refers to a *CALL* [OpCode] / respective method on [EVM].
57+
type CallType uint8
5758

5859
const (
59-
call callType = iota + 1
60-
callCode
61-
delegateCall
62-
staticCall
60+
UnknownCallType CallType = iota
61+
Call
62+
CallCode
63+
DelegateCall
64+
StaticCall
6365
)
6466

67+
// String returns a human-readable representation of the CallType.
68+
func (t CallType) String() string {
69+
switch t {
70+
case Call:
71+
return "Call"
72+
case CallCode:
73+
return "CallCode"
74+
case DelegateCall:
75+
return "DelegateCall"
76+
case StaticCall:
77+
return "StaticCall"
78+
}
79+
return fmt.Sprintf("Unknown %T(%d)", t, t)
80+
}
81+
6582
// run runs the [PrecompiledContract], differentiating between stateful and
6683
// regular types.
6784
func (args *evmCallArgs) run(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
@@ -115,6 +132,7 @@ type PrecompileEnvironment interface {
115132
// ReadOnlyState will always be non-nil.
116133
ReadOnlyState() libevm.StateReader
117134
Addresses() *libevm.AddressContext
135+
IncomingCallType() CallType
118136

119137
BlockHeader() (types.Header, error)
120138
BlockNumber() *big.Int
@@ -132,46 +150,30 @@ func (args *evmCallArgs) env() *environment {
132150
value = args.value
133151
)
134152
switch args.callType {
135-
case staticCall:
153+
case StaticCall:
136154
value = new(uint256.Int)
137155
fallthrough
138-
case call:
156+
case Call:
139157
self = args.addr
140158

141-
case delegateCall:
159+
case DelegateCall:
142160
value = nil
143161
fallthrough
144-
case callCode:
162+
case CallCode:
145163
self = args.caller.Address()
146164
}
147165

148166
// This is equivalent to the `contract` variables created by evm.*Call*()
149167
// methods, for non precompiles, to pass to [EVMInterpreter.Run].
150168
contract := NewContract(args.caller, AccountRef(self), value, args.gas)
151-
if args.callType == delegateCall {
169+
if args.callType == DelegateCall {
152170
contract = contract.AsDelegate()
153171
}
154172

155173
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
174+
evm: args.evm,
175+
self: contract,
176+
callType: args.callType,
175177
}
176178
}
177179

0 commit comments

Comments
 (0)