Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: vm.WithUNSAFECallerAddressProxying under DELEGATECALL #50

Merged
merged 7 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ jobs:
go-version: 1.21.4
- name: Run tests
run: | # Upstream flakes are race conditions exacerbated by concurrent tests
FLAKY_REGEX='go-ethereum/(eth|eth/tracers/logger|accounts/keystore|eth/downloader|miner|ethclient|ethclient/gethclient|eth/catalyst)$';
FLAKY_REGEX='go-ethereum/(eth|eth/tracers/js|eth/tracers/logger|accounts/keystore|eth/downloader|miner|ethclient|ethclient/gethclient|eth/catalyst)$';
go list ./... | grep -P "${FLAKY_REGEX}" | xargs -n 1 go test -short;
go test -short $(go list ./... | grep -Pv "${FLAKY_REGEX}");
62 changes: 32 additions & 30 deletions core/vm/contracts.libevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import (
// args := &evmCallArgs{evm, staticCall, caller, addr, input, gas, nil /*value*/}
type evmCallArgs struct {
evm *EVM
callType callType
callType CallType

// args:start
caller ContractRef
Expand All @@ -53,15 +53,32 @@ type evmCallArgs struct {
// args:end
}

type callType uint8
// A CallType refers to a *CALL* [OpCode] / respective method on [EVM].
type CallType uint8

const (
call callType = iota + 1
callCode
delegateCall
staticCall
UnknownCallType CallType = iota
Call
CallCode
DelegateCall
StaticCall
)

// String returns a human-readable representation of the CallType.
func (t CallType) String() string {
switch t {
case Call:
return "Call"
case CallCode:
return "CallCode"
case DelegateCall:
return "DelegateCall"
case StaticCall:
return "StaticCall"
}
return fmt.Sprintf("Unknown %T(%d)", t, t)
}

// run runs the [PrecompiledContract], differentiating between stateful and
// regular types.
func (args *evmCallArgs) run(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
Expand Down Expand Up @@ -115,6 +132,7 @@ type PrecompileEnvironment interface {
// ReadOnlyState will always be non-nil.
ReadOnlyState() libevm.StateReader
Addresses() *libevm.AddressContext
IncomingCallType() CallType

BlockHeader() (types.Header, error)
BlockNumber() *big.Int
Expand All @@ -132,46 +150,30 @@ func (args *evmCallArgs) env() *environment {
value = args.value
)
switch args.callType {
case staticCall:
case StaticCall:
value = new(uint256.Int)
fallthrough
case call:
case Call:
self = args.addr

case delegateCall:
case DelegateCall:
value = nil
fallthrough
case callCode:
case CallCode:
self = args.caller.Address()
}

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

return &environment{
evm: args.evm,
self: contract,
forceReadOnly: args.readOnly(),
}
}

func (args *evmCallArgs) readOnly() bool {
// A switch statement provides clearer code coverage for difficult-to-test
// cases.
switch {
case args.callType == staticCall:
// evm.interpreter.readOnly is only set to true via a call to
// EVMInterpreter.Run() so, if a precompile is called directly with
// StaticCall(), then readOnly might not be set yet.
return true
case args.evm.interpreter.readOnly:
return true
default:
return false
evm: args.evm,
self: contract,
callType: args.callType,
}
}

Expand Down
Loading