Skip to content

Commit

Permalink
chore(eip7702): remove OptionalNonce
Browse files Browse the repository at this point in the history
  • Loading branch information
onbjerg committed Jul 15, 2024
1 parent ecea267 commit 060bd9d
Showing 1 changed file with 5 additions and 95 deletions.
100 changes: 5 additions & 95 deletions crates/eips/src/eip7702/auth_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct Authorization {
/// The address of the authorization.
pub address: Address,
/// The nonce for the authorization.
pub nonce: OptionalNonce,
pub nonce: u64,
}

impl Authorization {
Expand All @@ -39,13 +39,8 @@ impl Authorization {
}

/// Get the `nonce` for the authorization.
///
/// # Note
///
/// If this is `Some`, implementers should check that the nonce of the authority is equal to
/// this nonce.
pub fn nonce(&self) -> Option<u64> {
*self.nonce
pub fn nonce(&self) -> u64 {
self.nonce
}

/// Computes the signature hash used to sign the authorization, or recover the authority from a
Expand Down Expand Up @@ -237,77 +232,10 @@ impl Deref for RecoveredAuthorization {
}
}

/// An internal wrapper around an `Option<u64>` for optional nonces.
///
/// In EIP-7702 the nonce is encoded as a list of either 0 or 1 items, where 0 items means that no
/// nonce was specified (i.e. `None`). If there is 1 item, this is the same as `Some`.
///
/// The wrapper type is used for RLP encoding and decoding.
#[derive(Default, Debug, Copy, Clone, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
pub struct OptionalNonce(Option<u64>);

impl OptionalNonce {
/// Create a new [`OptionalNonce`]
pub const fn new(nonce: Option<u64>) -> Self {
Self(nonce)
}
}

impl From<Option<u64>> for OptionalNonce {
fn from(value: Option<u64>) -> Self {
Self::new(value)
}
}

impl Encodable for OptionalNonce {
fn encode(&self, out: &mut dyn BufMut) {
match self.0 {
Some(nonce) => {
Header { list: true, payload_length: nonce.length() }.encode(out);
nonce.encode(out);
}
None => Header { list: true, payload_length: 0 }.encode(out),
}
}

fn length(&self) -> usize {
self.map(|nonce| nonce.length() + length_of_length(nonce.length())).unwrap_or(1)
}
}

impl Decodable for OptionalNonce {
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
let mut bytes = Header::decode_bytes(buf, true)?;
if bytes.is_empty() {
return Ok(Self(None));
}

let payload_view = &mut bytes;
let nonce = u64::decode(payload_view)?;
if !payload_view.is_empty() {
// if there's more than 1 item in the nonce list we error
Err(alloy_rlp::Error::UnexpectedLength)
} else {
Ok(Self(Some(nonce)))
}
}
}

impl Deref for OptionalNonce {
type Target = Option<u64>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{hex, Signature};
use arbitrary::Arbitrary;
use core::str::FromStr;

fn test_encode_decode_roundtrip(auth: Authorization) {
Expand All @@ -324,26 +252,8 @@ mod tests {
test_encode_decode_roundtrip(Authorization {
chain_id: 1u64,
address: Address::left_padding_from(&[6]),
nonce: Some(1u64).into(),
nonce: 1,
});

// no nonce
test_encode_decode_roundtrip(Authorization {
chain_id: 1u64,
address: Address::left_padding_from(&[6]),
nonce: None.into(),
});
}

#[test]
fn opt_nonce_too_many_elements() {
let mut buf = Vec::new();
vec![1u64, 2u64].encode(&mut buf);

assert_eq!(
OptionalNonce::decode(&mut buf.as_ref()),
Err(alloy_rlp::Error::UnexpectedLength)
)
}

#[test]
Expand All @@ -352,7 +262,7 @@ mod tests {
inner: Authorization {
chain_id: 1u64,
address: Address::left_padding_from(&[6]),
nonce: Some(1u64).into(),
nonce: 1,
},
signature: Signature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c8041b").unwrap(),
};
Expand Down

0 comments on commit 060bd9d

Please sign in to comment.