use crate::alias_address;
use alloy::primitives::{Address, Signature, B256};
use signet_zenith::MINTER_ADDRESS;
pub(crate) const MAGIC_SIG_SENTINEL: [u8; 4] = [0xff, 0xee, 0xdd, 0xcc];
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub(crate) enum Flags {
Enter = 0x01,
EnterToken = 0x02,
Transact = 0x03,
}
impl From<Flags> for u8 {
fn from(flag: Flags) -> u8 {
flag as u8
}
}
impl TryFrom<u8> for Flags {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x01 => Ok(Self::Enter),
0x02 => Ok(Self::EnterToken),
0x03 => Ok(Self::Transact),
_ => Err(()),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum MagicSigInfo {
Enter,
EnterToken,
Transact {
sender: Address,
aliased: bool,
},
}
impl MagicSigInfo {
const fn flag(&self) -> u8 {
match self {
Self::Enter => Flags::Enter as u8,
Self::EnterToken => Flags::EnterToken as u8,
Self::Transact { .. } => Flags::Transact as u8,
}
}
pub fn write_into_s(&self, buf: &mut [u8]) {
debug_assert_eq!(buf.len(), 32);
buf[8] = self.flag();
if let Self::Transact { sender, aliased } = self {
buf[11] = *aliased as u8;
buf[12..32].copy_from_slice(sender.as_slice());
}
}
pub fn read_from_s(s: impl AsRef<[u8]>) -> Option<Self> {
let s = s.as_ref();
if s.len() < 32 {
return None;
}
let flag = s[8].try_into().ok()?;
match flag {
Flags::Enter => Some(Self::Enter),
Flags::EnterToken => Some(Self::EnterToken),
Flags::Transact => {
Some(Self::Transact { aliased: s[11] != 0, sender: Address::from_slice(&s[12..]) })
}
}
}
pub const fn raw_sender(&self) -> Address {
match self {
Self::Transact { sender, .. } => *sender,
_ => MINTER_ADDRESS,
}
}
pub fn rollup_sender(&self) -> Address {
match self {
Self::Transact { sender, aliased } => {
if *aliased {
alias_address(*sender)
} else {
*sender
}
}
_ => MINTER_ADDRESS,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MagicSig {
pub ty: MagicSigInfo,
pub txid: B256,
pub event_idx: usize,
}
impl MagicSig {
pub fn try_from_signature(sig: &Signature) -> Option<Self> {
let s = sig.s();
let s_bytes: [u8; 32] = s.to_be_bytes();
if !s_bytes.starts_with(&MAGIC_SIG_SENTINEL) {
return None;
}
let ty = MagicSigInfo::read_from_s(s_bytes)?;
let txid = sig.r().to_le_bytes().into();
let mut buf = [0u8; 4];
buf.copy_from_slice(&s_bytes[4..8]);
let event_idx = u32::from_be_bytes(buf) as usize;
Some(Self { ty, txid, event_idx })
}
pub const fn enter(txid: B256, event_idx: usize) -> Self {
Self { ty: MagicSigInfo::Enter, txid, event_idx }
}
pub const fn enter_token(txid: B256, event_idx: usize) -> Self {
Self { ty: MagicSigInfo::EnterToken, txid, event_idx }
}
pub const fn transact(txid: B256, aliased: bool, event_idx: usize, sender: Address) -> Self {
Self { ty: MagicSigInfo::Transact { sender, aliased }, txid, event_idx }
}
pub fn rollup_sender(&self) -> Address {
self.ty.rollup_sender()
}
}
impl From<MagicSig> for Signature {
fn from(value: MagicSig) -> Self {
let mut buf = [0u8; 64];
buf[..32].copy_from_slice(value.txid.as_ref());
buf[32..36].copy_from_slice(&MAGIC_SIG_SENTINEL);
buf[36..40].copy_from_slice(&(value.event_idx as u32).to_be_bytes());
value.ty.write_into_s(&mut buf[32..]);
Signature::from_bytes_and_parity(&buf, false)
}
}
#[cfg(test)]
mod test {
use super::*;
use alloy::{primitives::address, uint};
const ENTER_TOKEN_TX: &str = include_str!("../../../tests/artifacts/enter_tx.json");
#[track_caller]
fn test_roundtrip(msig: MagicSig) {
let sig: Signature = msig.into();
assert_eq!(MagicSig::try_from_signature(&sig), Some(msig))
}
#[test]
fn test_enter_roundtrip() {
let txid = B256::repeat_byte(0xcc);
let msig = MagicSig::enter_token(txid, 333);
test_roundtrip(msig);
}
#[test]
fn test_enter_token_roundtrip() {
let txid = B256::repeat_byte(0xcc);
let msig = MagicSig::enter_token(txid, 3821);
test_roundtrip(msig);
}
#[test]
fn test_transact_roundtrip() {
let txid = B256::repeat_byte(0xcc);
let sender = Address::repeat_byte(0x12);
let msig = MagicSig::transact(txid, false, u32::MAX as usize, sender);
test_roundtrip(msig);
let msig = MagicSig::transact(txid, true, 0, sender);
test_roundtrip(msig);
}
#[test]
fn test_tx_decode_sig() {
let tx: alloy::consensus::TxEnvelope = serde_json::from_str(ENTER_TOKEN_TX).unwrap();
let sig = tx.signature();
let msig = MagicSig::try_from_signature(sig).unwrap();
assert_eq!(msig.rollup_sender(), MINTER_ADDRESS)
}
#[test]
fn test_2026_01_27() {
let r = uint!(0x78916445ee265c92ca42976d7150d426bc75a46d47daff441e545e423965772_U256);
let s = uint!(0xffeeddcc000000000300000086973f6c0ad9d1a1519254f2b89cb341865e8b4e_U256);
let sig = Signature::new(r, s, false);
let msig = MagicSig::try_from_signature(&sig).unwrap();
assert_eq!(
msig,
MagicSig {
txid: r.to_le_bytes().into(),
event_idx: 0,
ty: MagicSigInfo::Transact {
sender: address!("0x86973f6c0ad9d1a1519254f2b89cb341865e8b4e"),
aliased: false
}
}
);
}
}