Skip to content
Merged
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
23 changes: 9 additions & 14 deletions crates/vm/levm/src/precompiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,18 +322,15 @@ pub fn ecrecover(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu
let (raw_v, raw_sig) = tail.split_at(WORD);

// EVM expects v ∈ {27, 28}. Anything else is invalid → empty return.
let v = match u8::try_from(u256_from_big_endian(raw_v)) {
Ok(v @ (27 | 28)) => v,
let mut recid_byte = match u8::try_from(u256_from_big_endian(raw_v)) {
Ok(27) => 0,
Ok(28) => 1,
_ => return Ok(Bytes::new()),
};

#[allow(clippy::arithmetic_side_effects, reason = "v ∈ {27, 28}")]
let mut recid_byte = v - 27;

// Parse signature (r||s). If malformed → empty return.
let mut sig = match Signature::from_slice(raw_sig) {
Ok(s) => s,
Err(_) => return Ok(Bytes::new()),
let Ok(mut sig) = Signature::from_slice(raw_sig) else {
return Ok(Bytes::new());
};

// k256 enforces canonical low-S for recovery.
Expand All @@ -344,15 +341,13 @@ pub fn ecrecover(calldata: &Bytes, gas_remaining: &mut u64, _fork: Fork) -> Resu
}

// Recovery id from the adjusted byte.
let recid = match RecoveryId::from_byte(recid_byte) {
Some(id) => id,
None => return Ok(Bytes::new()),
let Some(recid) = RecoveryId::from_byte(recid_byte) else {
return Ok(Bytes::new());
};

// Recover the verifying key from the prehash (32-byte digest).
let vk = match VerifyingKey::recover_from_prehash(raw_hash, &sig, recid) {
Ok(k) => k,
Err(_) => return Ok(Bytes::new()),
let Ok(vk) = VerifyingKey::recover_from_prehash(raw_hash, &sig, recid) else {
return Ok(Bytes::new());
};

// SEC1 uncompressed: 0x04 || X(32) || Y(32). We need X||Y (64 bytes).
Expand Down