Skip to content

Commit f7cb652

Browse files
authored
Merge pull request #8148 from onflow/mpeter/dry-call-apply-set-code-authorizations
Apply any given `SetCodeAuthorization` list to `DryCall`
2 parents 28d6425 + 3a1a776 commit f7cb652

File tree

3 files changed

+65
-9
lines changed

3 files changed

+65
-9
lines changed

fvm/evm/offchain/query/view.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ func (v *View) DryCall(
110110
from gethCommon.Address,
111111
to gethCommon.Address,
112112
data []byte,
113+
authList []gethTypes.SetCodeAuthorization,
113114
value *big.Int,
114115
gasLimit uint64,
115116
opts ...DryCallOption,
@@ -160,6 +161,13 @@ func (v *View) DryCall(
160161
// not apply. These endpoints don't mutate the state, they
161162
// simply read the state.
162163
call.SkipTxGasLimitCheck()
164+
165+
// If we are given a non-empty list of SetCode authorizations,
166+
// we need to set them, so that gas estimation works properly.
167+
if len(authList) > 0 {
168+
call.SetCodeAuthorizations(authList)
169+
}
170+
163171
res, err := bv.DirectCall(call)
164172
if err != nil {
165173
return nil, err

fvm/evm/offchain/query/view_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import (
55
"math/big"
66
"testing"
77

8+
"github.com/holiman/uint256"
89
"github.com/stretchr/testify/require"
910

1011
"github.com/ethereum/go-ethereum/common"
12+
gethTypes "github.com/ethereum/go-ethereum/core/types"
1113
"github.com/ethereum/go-ethereum/params"
1214

1315
"github.com/onflow/flow-go/fvm/evm/handler"
@@ -91,6 +93,7 @@ func TestView(t *testing.T) {
9193
testAccount.Address().ToCommon(),
9294
testContract.DeployedAt.ToCommon(),
9395
testContract.MakeCallData(t, "verifyArchCallToFlowBlockHeight", expectedFlowHeight),
96+
[]gethTypes.SetCodeAuthorization{},
9497
big.NewInt(0),
9598
uint64(1_000_000),
9699
query.WithExtraPrecompiledContracts(
@@ -110,6 +113,7 @@ func TestView(t *testing.T) {
110113
testAccount.Address().ToCommon(),
111114
newBalance,
112115
),
116+
[]gethTypes.SetCodeAuthorization{},
113117
big.NewInt(0),
114118
uint64(1_000_000),
115119
query.WithStateOverrideBalance(
@@ -129,6 +133,7 @@ func TestView(t *testing.T) {
129133
"store",
130134
big.NewInt(2),
131135
),
136+
[]gethTypes.SetCodeAuthorization{},
132137
big.NewInt(0),
133138
params.MaxTxGas+1_000,
134139
)
@@ -142,6 +147,7 @@ func TestView(t *testing.T) {
142147
"store",
143148
big.NewInt(2),
144149
),
150+
[]gethTypes.SetCodeAuthorization{},
145151
big.NewInt(0),
146152
maxCallGasLimit+1,
147153
)
@@ -151,6 +157,29 @@ func TestView(t *testing.T) {
151157
err,
152158
"gas limit is bigger than max gas limit allowed 26777217 > 26777216",
153159
)
160+
161+
// test non-empty SetCode authorization list
162+
_, err = view.DryCall(
163+
testAccount.Address().ToCommon(),
164+
testContract.DeployedAt.ToCommon(),
165+
testContract.MakeCallData(t,
166+
"store",
167+
big.NewInt(2),
168+
),
169+
[]gethTypes.SetCodeAuthorization{
170+
gethTypes.SetCodeAuthorization{
171+
ChainID: *uint256.NewInt(747),
172+
Address: common.HexToAddress("0xD370975A6257fE8CeF93101799D602D30838BAad"),
173+
Nonce: 1,
174+
V: 28,
175+
R: *RandomUint256Int(15_000_000),
176+
S: *RandomUint256Int(15_000_000),
177+
},
178+
},
179+
big.NewInt(0),
180+
maxCallGasLimit,
181+
)
182+
require.NoError(t, err)
154183
})
155184
})
156185
})
@@ -186,6 +215,7 @@ func TestViewStateOverrides(t *testing.T) {
186215
testAccount.Address().ToCommon(),
187216
testContract.DeployedAt.ToCommon(),
188217
testContract.MakeCallData(t, "retrieve"),
218+
nil,
189219
big.NewInt(0),
190220
uint64(1_000_000),
191221
query.WithStateOverrideState(
@@ -225,6 +255,7 @@ func TestViewStateOverrides(t *testing.T) {
225255
testAccount.Address().ToCommon(),
226256
testContract.DeployedAt.ToCommon(),
227257
testContract.MakeCallData(t, "retrieve"),
258+
nil,
228259
big.NewInt(0),
229260
uint64(1_000_000),
230261
query.WithStateOverrideStateDiff(
@@ -264,6 +295,7 @@ func TestViewStateOverrides(t *testing.T) {
264295
testAccount.Address().ToCommon(),
265296
testContract.DeployedAt.ToCommon(),
266297
testContract.MakeCallData(t, "retrieve"),
298+
nil,
267299
big.NewInt(0),
268300
uint64(1_000_000),
269301
query.WithStateOverrideState(
@@ -304,6 +336,7 @@ func TestViewStateOverrides(t *testing.T) {
304336
testAccount.Address().ToCommon(),
305337
testContract.DeployedAt.ToCommon(),
306338
testContract.MakeCallData(t, "retrieve"),
339+
nil,
307340
big.NewInt(0),
308341
uint64(1_000_000),
309342
query.WithStateOverrideStateDiff(
@@ -346,6 +379,7 @@ func TestViewStateOverrides(t *testing.T) {
346379
testAccount.Address().ToCommon(),
347380
newContractAddress,
348381
testContract.MakeCallData(t, "retrieve"),
382+
nil,
349383
big.NewInt(0),
350384
uint64(1_000_000),
351385
query.WithStateOverrideCode(
@@ -391,6 +425,7 @@ func TestViewStateOverrides(t *testing.T) {
391425
testAccount.Address().ToCommon(),
392426
newContractAddress,
393427
testContract.MakeCallData(t, "retrieve"),
428+
nil,
394429
big.NewInt(0),
395430
uint64(1_000_000),
396431
query.WithStateOverrideCode(

fvm/evm/types/call.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ type DirectCall struct {
5858
// Sets whether we skip or apply the EIP-7825 tx gas limit cap,
5959
// introduced in `Osaka` hard-fork
6060
skipTxGasLimitCheck bool
61+
62+
// setCodeAuthorizations is an authorization list from an account
63+
// to deploy code at its address. Useful for EIP-7702 transactions.
64+
setCodeAuthorizations []gethTypes.SetCodeAuthorization
6165
}
6266

6367
// DirectCallFromEncoded constructs a DirectCall from encoded data
@@ -88,15 +92,16 @@ func (dc *DirectCall) Hash() gethCommon.Hash {
8892
// Message constructs a core.Message from the direct call
8993
func (dc *DirectCall) Message() *gethCore.Message {
9094
return &gethCore.Message{
91-
From: dc.From.ToCommon(),
92-
To: dc.to(),
93-
Value: dc.Value,
94-
Data: dc.Data,
95-
Nonce: dc.Nonce,
96-
GasLimit: dc.GasLimit,
97-
GasPrice: big.NewInt(0), // price is set to zero fo direct calls
98-
GasTipCap: big.NewInt(0), // also known as maxPriorityFeePerGas (in GWei)
99-
GasFeeCap: big.NewInt(0), // also known as maxFeePerGas (in GWei)
95+
From: dc.From.ToCommon(),
96+
To: dc.to(),
97+
Value: dc.Value,
98+
Data: dc.Data,
99+
Nonce: dc.Nonce,
100+
GasLimit: dc.GasLimit,
101+
GasPrice: big.NewInt(0), // price is set to zero fo direct calls
102+
GasTipCap: big.NewInt(0), // also known as maxPriorityFeePerGas (in GWei)
103+
GasFeeCap: big.NewInt(0), // also known as maxFeePerGas (in GWei)
104+
SetCodeAuthorizations: dc.setCodeAuthorizations, // introduced in EIP-7702 tx type
100105
// TODO: maybe revisit setting the access list
101106
// AccessList: tx.AccessList(),
102107
// When SkipNonceChecks is true, the message nonce is
@@ -143,6 +148,14 @@ func (dc *DirectCall) SkipTxGasLimitCheck() {
143148
dc.skipTxGasLimitCheck = true
144149
}
145150

151+
// SetCodeAuthorizations sets the given code authorizaions for EIP-7702
152+
// transaction types
153+
func (dc *DirectCall) SetCodeAuthorizations(
154+
authList []gethTypes.SetCodeAuthorization,
155+
) {
156+
dc.setCodeAuthorizations = authList
157+
}
158+
146159
// ValidEIP7825GasLimit checks whether the `GasLimit` of the direct call
147160
// is valid according to the given chain rules.
148161
func (dc *DirectCall) ValidEIP7825GasLimit(rules gethParams.Rules) bool {

0 commit comments

Comments
 (0)