Skip to content

Commit ab3afd9

Browse files
committed
refactor: abstract options package
1 parent 594abd9 commit ab3afd9

File tree

3 files changed

+61
-23
lines changed

3 files changed

+61
-23
lines changed

core/vm/environment.libevm.go

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/ava-labs/libevm/common"
2626
"github.com/ava-labs/libevm/core/types"
2727
"github.com/ava-labs/libevm/libevm"
28+
"github.com/ava-labs/libevm/libevm/options"
2829
"github.com/ava-labs/libevm/params"
2930
)
3031

@@ -105,20 +106,14 @@ func (e *environment) callContract(typ CallType, addr common.Address, input []by
105106
}
106107

107108
var caller ContractRef = e.self
108-
for _, o := range opts {
109-
switch o := o.(type) {
110-
case callOptUNSAFECallerAddressProxy:
111-
// Note that, in addition to being unsafe, this breaks an EVM
112-
// assumption that the caller ContractRef is always a *Contract.
113-
caller = AccountRef(e.self.CallerAddress)
114-
if e.callType == DelegateCall {
115-
// self was created with AsDelegate(), which means that
116-
// CallerAddress was inherited.
117-
caller = AccountRef(e.self.Address())
118-
}
119-
case nil:
120-
default:
121-
return nil, gas, fmt.Errorf("unsupported option %T", o)
109+
if options.As[callConfig](opts...).unsafeCallerAddressProxying {
110+
// Note that, in addition to being unsafe, this breaks an EVM
111+
// assumption that the caller ContractRef is always a *Contract.
112+
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())
122117
}
123118
}
124119

core/vm/options.libevm.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@
1616

1717
package vm
1818

19-
// A CallOption modifies the default behaviour of a contract call.
20-
type CallOption interface {
21-
libevmCallOption() // noop to only allow internally defined options
19+
import "github.com/ava-labs/libevm/libevm/options"
20+
21+
type callConfig struct {
22+
unsafeCallerAddressProxying bool
2223
}
2324

25+
// A CallOption modifies the default behaviour of a contract call.
26+
type CallOption = options.Option[callConfig]
27+
2428
// WithUNSAFECallerAddressProxying results in precompiles making contract calls
2529
// specifying their own caller's address as the caller. This is NOT SAFE for
2630
// regular use as callers of the precompile may not understand that they are
@@ -29,10 +33,7 @@ type CallOption interface {
2933
// Deprecated: this option MUST NOT be used other than to allow migration to
3034
// libevm when backwards compatibility is required.
3135
func WithUNSAFECallerAddressProxying() CallOption {
32-
return callOptUNSAFECallerAddressProxy{}
36+
return options.Func[callConfig](func(c *callConfig) {
37+
c.unsafeCallerAddressProxying = true
38+
})
3339
}
34-
35-
// Deprecated: see [WithUNSAFECallerAddressProxying].
36-
type callOptUNSAFECallerAddressProxy struct{}
37-
38-
func (callOptUNSAFECallerAddressProxy) libevmCallOption() {}

libevm/options/options.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2024 the libevm authors.
2+
//
3+
// The libevm additions to go-ethereum are free software: you can redistribute
4+
// them and/or modify them under the terms of the GNU Lesser General Public License
5+
// as published by the Free Software Foundation, either version 3 of the License,
6+
// or (at your option) any later version.
7+
//
8+
// The libevm additions are distributed in the hope that they will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
// General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License
14+
// along with the go-ethereum library. If not, see
15+
// <http://www.gnu.org/licenses/>.
16+
17+
// Package options provides a generic mechanism for defining configuration of
18+
// arbitrary types.
19+
package options
20+
21+
// An Option configures values of arbitrary type.
22+
type Option[T any] interface {
23+
Configure(*T)
24+
}
25+
26+
// As applies Options to a zero-value T, which it then returns.
27+
func As[T any](opts ...Option[T]) *T {
28+
var t T
29+
for _, o := range opts {
30+
o.Configure(&t)
31+
}
32+
return &t
33+
}
34+
35+
// A Func converts a function into an [Option], using itself as the Configure
36+
// method.
37+
type Func[T any] func(*T)
38+
39+
var _ Option[struct{}] = Func[struct{}](nil)
40+
41+
// Configure implements the [Option] interface.
42+
func (f Func[T]) Configure(t *T) { f(t) }

0 commit comments

Comments
 (0)