Skip to content

Commit 386ca06

Browse files
authored
fix(eip7702): small fixes (#8791)
* fix(eip7702): doc and small fixes * clippy
1 parent c835d7e commit 386ca06

File tree

7 files changed

+48
-56
lines changed

7 files changed

+48
-56
lines changed

crates/anvil/src/eth/error.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,12 @@ pub enum InvalidTransactionError {
231231
/// Thrown when there are no `blob_hashes` in the transaction.
232232
#[error("There should be at least one blob in a Blob transaction.")]
233233
EmptyBlobs,
234+
/// Thrown when an access list is used before the berlin hard fork.
235+
#[error("EIP-7702 authorization lists are not supported before the Prague hardfork")]
236+
AuthorizationListNotSupported,
237+
/// Forwards error from the revm
238+
#[error(transparent)]
239+
Revm(revm::primitives::InvalidTransaction),
234240
}
235241

236242
impl From<revm::primitives::InvalidTransaction> for InvalidTransactionError {
@@ -263,7 +269,14 @@ impl From<revm::primitives::InvalidTransaction> for InvalidTransactionError {
263269
InvalidTransaction::BlobVersionNotSupported => Self::BlobVersionNotSupported,
264270
InvalidTransaction::EmptyBlobs => Self::EmptyBlobs,
265271
InvalidTransaction::TooManyBlobs { max, have } => Self::TooManyBlobs(max, have),
266-
_ => todo!(),
272+
InvalidTransaction::AuthorizationListNotSupported => {
273+
Self::AuthorizationListNotSupported
274+
}
275+
InvalidTransaction::AuthorizationListInvalidFields |
276+
InvalidTransaction::InvalidAuthorizationList |
277+
InvalidTransaction::OptimismError(_) |
278+
InvalidTransaction::EofCrateShouldHaveToAddress |
279+
InvalidTransaction::EmptyAuthorizationList => Self::Revm(err),
267280
}
268281
}
269282
}

crates/cast/bin/cmd/access_list.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::tx::{CastTxBuilder, SenderKind};
2-
use alloy_primitives::TxKind;
32
use alloy_rpc_types::BlockId;
43
use cast::Cast;
54
use clap::Parser;
@@ -55,15 +54,10 @@ impl AccessListArgs {
5554
let provider = utils::get_provider(&config)?;
5655
let sender = SenderKind::from_wallet_opts(eth.wallet).await?;
5756

58-
let tx_kind = if let Some(to) = to {
59-
TxKind::Call(to.resolve(&provider).await?)
60-
} else {
61-
TxKind::Create
62-
};
63-
6457
let (tx, _) = CastTxBuilder::new(&provider, tx, &config)
6558
.await?
66-
.with_tx_kind(tx_kind)
59+
.with_to(to)
60+
.await?
6761
.with_code_sig_and_args(None, sig, args)
6862
.await?
6963
.build_raw(sender)

crates/cast/bin/cmd/call.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,6 @@ impl CallArgs {
143143
let sender = SenderKind::from_wallet_opts(eth.wallet).await?;
144144
let from = sender.address();
145145

146-
let tx_kind = if let Some(to) = to {
147-
TxKind::Call(to.resolve(&provider).await?)
148-
} else {
149-
TxKind::Create
150-
};
151-
152146
let code = if let Some(CallSubcommands::Create {
153147
code,
154148
sig: create_sig,
@@ -168,7 +162,8 @@ impl CallArgs {
168162

169163
let (tx, func) = CastTxBuilder::new(&provider, tx, &config)
170164
.await?
171-
.with_tx_kind(tx_kind)
165+
.with_to(to)
166+
.await?
172167
.with_code_sig_and_args(code, sig, args)
173168
.await?
174169
.build_raw(sender)
@@ -192,6 +187,7 @@ impl CallArgs {
192187

193188
let value = tx.value.unwrap_or_default();
194189
let input = tx.inner.input.into_input().unwrap_or_default();
190+
let tx_kind = tx.inner.to.expect("set by builder");
195191

196192
let trace = match tx_kind {
197193
TxKind::Create => {

crates/cast/bin/cmd/estimate.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::tx::{CastTxBuilder, SenderKind};
2-
use alloy_primitives::{TxKind, U256};
2+
use alloy_primitives::U256;
33
use alloy_provider::Provider;
44
use alloy_rpc_types::BlockId;
55
use clap::Parser;
@@ -73,12 +73,6 @@ impl EstimateArgs {
7373
let provider = utils::get_provider(&config)?;
7474
let sender = SenderKind::from_wallet_opts(eth.wallet).await?;
7575

76-
let tx_kind = if let Some(to) = to {
77-
TxKind::Call(to.resolve(&provider).await?)
78-
} else {
79-
TxKind::Create
80-
};
81-
8276
let code = if let Some(EstimateSubcommands::Create {
8377
code,
8478
sig: create_sig,
@@ -98,7 +92,8 @@ impl EstimateArgs {
9892

9993
let (tx, _) = CastTxBuilder::new(&provider, tx, &config)
10094
.await?
101-
.with_tx_kind(tx_kind)
95+
.with_to(to)
96+
.await?
10297
.with_code_sig_and_args(code, sig, args)
10398
.await?
10499
.build_raw(sender)

crates/cast/bin/cmd/mktx.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use clap::Parser;
66
use eyre::Result;
77
use foundry_cli::{
88
opts::{EthereumOpts, TransactionOpts},
9-
utils::{self, get_provider},
9+
utils::get_provider,
1010
};
1111
use foundry_common::ens::NameOrAddress;
1212
use foundry_config::Config;
@@ -83,9 +83,6 @@ impl MakeTxArgs {
8383
};
8484

8585
let config = Config::from(&eth);
86-
let provider = utils::get_provider(&config)?;
87-
88-
let tx_kind = tx::resolve_tx_kind(&provider, &code, &to).await?;
8986

9087
// Retrieve the signer, and bail if it can't be constructed.
9188
let signer = eth.wallet.signer().await?;
@@ -97,7 +94,8 @@ impl MakeTxArgs {
9794

9895
let (tx, _) = CastTxBuilder::new(provider, tx, &config)
9996
.await?
100-
.with_tx_kind(tx_kind)
97+
.with_to(to)
98+
.await?
10199
.with_code_sig_and_args(code, sig, args)
102100
.await?
103101
.with_blob_data(blob_data)?

crates/cast/bin/cmd/send.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ impl SendTxArgs {
122122

123123
let config = Config::from(&eth);
124124
let provider = utils::get_provider(&config)?;
125-
let tx_kind = tx::resolve_tx_kind(&provider, &code, &to).await?;
126125

127126
let builder = CastTxBuilder::new(&provider, tx, &config)
128127
.await?
129-
.with_tx_kind(tx_kind)
128+
.with_to(to)
129+
.await?
130130
.with_code_sig_and_args(code, sig, args)
131131
.await?
132132
.with_blob_data(blob_data)?;

crates/cast/bin/tx.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -103,29 +103,14 @@ corresponds to the sender, or let foundry automatically detect it by not specify
103103
Ok(())
104104
}
105105

106-
/// Ensures the transaction is either a contract deployment or a recipient address is specified
107-
pub async fn resolve_tx_kind<P: Provider<T, AnyNetwork>, T: Transport + Clone>(
108-
provider: &P,
109-
code: &Option<String>,
110-
to: &Option<NameOrAddress>,
111-
) -> Result<TxKind> {
112-
if code.is_some() {
113-
Ok(TxKind::Create)
114-
} else if let Some(to) = to {
115-
Ok(TxKind::Call(to.resolve(provider).await?))
116-
} else {
117-
eyre::bail!("Must specify a recipient address or contract code to deploy");
118-
}
119-
}
120-
121106
/// Initial state.
122107
#[derive(Debug)]
123108
pub struct InitState;
124109

125110
/// State with known [TxKind].
126111
#[derive(Debug)]
127-
pub struct TxKindState {
128-
kind: TxKind,
112+
pub struct ToState {
113+
to: Option<Address>,
129114
}
130115

131116
/// State with known input for the transaction.
@@ -211,22 +196,23 @@ where
211196
}
212197

213198
/// Sets [TxKind] for this builder and changes state to [TxKindState].
214-
pub fn with_tx_kind(self, kind: TxKind) -> CastTxBuilder<T, P, TxKindState> {
215-
CastTxBuilder {
199+
pub async fn with_to(self, to: Option<NameOrAddress>) -> Result<CastTxBuilder<T, P, ToState>> {
200+
let to = if let Some(to) = to { Some(to.resolve(&self.provider).await?) } else { None };
201+
Ok(CastTxBuilder {
216202
provider: self.provider,
217203
tx: self.tx,
218204
legacy: self.legacy,
219205
blob: self.blob,
220206
chain: self.chain,
221207
etherscan_api_key: self.etherscan_api_key,
222208
auth: self.auth,
223-
state: TxKindState { kind },
209+
state: ToState { to },
224210
_t: self._t,
225-
}
211+
})
226212
}
227213
}
228214

229-
impl<T, P> CastTxBuilder<T, P, TxKindState>
215+
impl<T, P> CastTxBuilder<T, P, ToState>
230216
where
231217
P: Provider<T, AnyNetwork>,
232218
T: Transport + Clone,
@@ -244,7 +230,7 @@ where
244230
parse_function_args(
245231
&sig,
246232
args,
247-
self.state.kind.to().cloned(),
233+
self.state.to,
248234
self.chain,
249235
&self.provider,
250236
self.etherscan_api_key.as_deref(),
@@ -254,14 +240,24 @@ where
254240
(Vec::new(), None)
255241
};
256242

257-
let input = if let Some(code) = code {
243+
let input = if let Some(code) = &code {
258244
let mut code = hex::decode(code)?;
259245
code.append(&mut args);
260246
code
261247
} else {
262248
args
263249
};
264250

251+
if self.state.to.is_none() && code.is_none() {
252+
let has_value = self.tx.value.map_or(false, |v| !v.is_zero());
253+
let has_auth = self.auth.is_some();
254+
// We only allow user to omit the recipient address if transaction is an EIP-7702 tx
255+
// without a value.
256+
if !has_auth || has_value {
257+
eyre::bail!("Must specify a recipient address or contract code to deploy");
258+
}
259+
}
260+
265261
Ok(CastTxBuilder {
266262
provider: self.provider,
267263
tx: self.tx,
@@ -270,7 +266,7 @@ where
270266
chain: self.chain,
271267
etherscan_api_key: self.etherscan_api_key,
272268
auth: self.auth,
273-
state: InputState { kind: self.state.kind, input, func },
269+
state: InputState { kind: self.state.to.into(), input, func },
274270
_t: self._t,
275271
})
276272
}

0 commit comments

Comments
 (0)