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
83 changes: 81 additions & 2 deletions crates/types/src/signing/order.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::signing::{permit_signing_info, SignedPermitError, SigningError};
use alloy::{
network::TransactionBuilder, primitives::Address, rpc::types::TransactionRequest,
signers::Signer, sol_types::SolCall,
network::TransactionBuilder,
primitives::{keccak256, Address, B256},
rpc::types::TransactionRequest,
signers::Signer,
sol_types::{SolCall, SolValue},
};
use chrono::Utc;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -68,6 +71,41 @@ impl SignedOrder {
// construct an initiate tx request
TransactionRequest::default().with_input(initiate_data).with_to(order_contract)
}

/// Get the hash of the order.
///
/// # Composition
///
/// The order hash is composed of the following:
/// - The permit2 batch permit inputs, ABI encoded and hashed.
/// - The permit2 batch owner, ABI encoded and hashed.
/// - The order outputs, ABI encoded and hashed.
/// - The permit2 batch signature, normalized and hashed.
///
/// The components are then hashed together.
pub fn order_hash(&self) -> B256 {
keccak256(self.order_hash_pre_image())
}

/// Get the pre-image for the order hash.
///
/// This is the raw bytes that are hashed to produce the order hash.
#[doc(hidden)]
pub fn order_hash_pre_image(&self) -> Vec<u8> {
// 4 * 32 bytes = 128 bytes
let mut buf = Vec::with_capacity(128);

buf.extend_from_slice(keccak256(self.permit.permit.abi_encode()).as_slice());
buf.extend_from_slice(keccak256(self.permit.owner.abi_encode()).as_slice());
buf.extend_from_slice(keccak256(self.outputs.abi_encode()).as_slice());

// Normalize the signature.
let signature =
alloy::primitives::Signature::from_raw(&self.permit.signature).unwrap().normalized_s();
buf.extend_from_slice(keccak256(signature.as_bytes()).as_slice());

buf
}
}

/// An UnsignedOrder is a helper type used to easily transform an Order into a SignedOrder with correct permit2 semantics.
Expand Down Expand Up @@ -147,3 +185,44 @@ impl<'a> UnsignedOrder<'a> {
})
}
}

#[cfg(test)]
mod tests {
use alloy::primitives::{b256, Signature, U256};
use signet_zenith::HostOrders::{PermitBatchTransferFrom, TokenPermissions};

use super::*;

fn basic_order() -> SignedOrder {
SignedOrder::new(
Permit2Batch {
permit: PermitBatchTransferFrom {
permitted: vec![TokenPermissions { token: Address::ZERO, amount: U256::ZERO }],
nonce: U256::ZERO,
deadline: U256::ZERO,
},
owner: Address::ZERO,
signature: Signature::test_signature().as_bytes().into(),
},
vec![Output {
token: Address::ZERO,
amount: U256::ZERO,
recipient: Address::ZERO,
chainId: 0,
}],
)
}

#[test]
fn test_order_hash() {
let order = basic_order();
let hash = order.order_hash();
let pre_image = order.order_hash_pre_image();

assert_eq!(hash, keccak256(pre_image));
assert_eq!(
hash,
b256!("0xba359dd4f891bed0a2cf87c306e59fb6ee099e02b5b0fa86584cdcc44bf6c272")
);
}
}
Loading