1use std::fmt;
8
9use alloy_primitives::{Address, U256, keccak256};
10
11use crate::order_signing::{
12 trade::{EncodedTrade, SettlementTokenRegistry, SignatureData, encode_trade},
13 types::UnsignedOrder,
14};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub enum InteractionStage {
24 Pre = 0,
26 Intra = 1,
28 Post = 2,
30}
31
32impl fmt::Display for InteractionStage {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 Self::Pre => write!(f, "Pre"),
36 Self::Intra => write!(f, "Intra"),
37 Self::Post => write!(f, "Post"),
38 }
39 }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
47pub struct EncodedInteraction {
48 pub target: Address,
50 pub value: U256,
52 pub calldata: Vec<u8>,
54}
55
56#[derive(Debug, Clone)]
88pub struct SettlementEncoder {
89 tokens: SettlementTokenRegistry,
91 clearing_prices: Vec<U256>,
93 trades: Vec<EncodedTrade>,
95 interactions: [Vec<EncodedInteraction>; 3],
97}
98
99impl Default for SettlementEncoder {
100 fn default() -> Self {
101 Self::new()
102 }
103}
104
105impl SettlementEncoder {
106 #[must_use]
112 pub fn new() -> Self {
113 Self {
114 tokens: SettlementTokenRegistry::new(),
115 clearing_prices: Vec::new(),
116 trades: Vec::new(),
117 interactions: [Vec::new(), Vec::new(), Vec::new()],
118 }
119 }
120
121 pub fn add_token(&mut self, token: Address) -> usize {
134 let idx = self.tokens.index(token) as usize;
135 if self.clearing_prices.len() <= idx {
137 self.clearing_prices.resize(idx + 1, U256::ZERO);
138 }
139 idx
140 }
141
142 pub fn set_clearing_price(&mut self, token_index: usize, price: U256) {
152 if self.clearing_prices.len() <= token_index {
153 self.clearing_prices.resize(token_index + 1, U256::ZERO);
154 }
155 self.clearing_prices[token_index] = price;
156 }
157
158 pub fn add_trade(
169 &mut self,
170 order: &UnsignedOrder,
171 signature: &SignatureData,
172 executed_amount: U256,
173 ) {
174 let trade = encode_trade(&mut self.tokens, order, signature, executed_amount);
175 let token_count = self.tokens.addresses().len();
177 if self.clearing_prices.len() < token_count {
178 self.clearing_prices.resize(token_count, U256::ZERO);
179 }
180 self.trades.push(trade);
181 }
182
183 pub fn add_interaction(
192 &mut self,
193 stage: InteractionStage,
194 target: Address,
195 value: U256,
196 calldata: Vec<u8>,
197 ) {
198 self.interactions[stage as usize].push(EncodedInteraction { target, value, calldata });
199 }
200
201 #[must_use]
211 pub fn encode_settlement(&self) -> Vec<u8> {
212 let selector = &keccak256(
213 b"settle(address[],uint256[],(uint256,uint256,address,uint256,uint256,uint32,bytes32,uint256,uint256,uint256,bytes)[],(address,uint256,bytes)[][3])",
214 )[..4];
215
216 let tokens = self.tokens.addresses();
217 let mut buf = Vec::with_capacity(4 + 256);
218 buf.extend_from_slice(selector);
219
220 let head_size: usize = 4 * 32;
223
224 let tokens_enc = abi_encode_address_array(tokens);
226 let prices_enc = abi_encode_u256_array(&self.clearing_prices);
227 let trades_enc = self.abi_encode_trades();
228 let interactions_enc = self.abi_encode_interactions();
229
230 let offset_tokens = head_size;
231 let offset_prices = offset_tokens + tokens_enc.len();
232 let offset_trades = offset_prices + prices_enc.len();
233 let offset_interactions = offset_trades + trades_enc.len();
234
235 buf.extend_from_slice(&abi_u256(U256::from(offset_tokens)));
237 buf.extend_from_slice(&abi_u256(U256::from(offset_prices)));
238 buf.extend_from_slice(&abi_u256(U256::from(offset_trades)));
239 buf.extend_from_slice(&abi_u256(U256::from(offset_interactions)));
240
241 buf.extend_from_slice(&tokens_enc);
243 buf.extend_from_slice(&prices_enc);
244 buf.extend_from_slice(&trades_enc);
245 buf.extend_from_slice(&interactions_enc);
246
247 buf
248 }
249
250 #[must_use]
256 pub fn token_count(&self) -> usize {
257 self.tokens.addresses().len()
258 }
259
260 #[must_use]
266 pub const fn trade_count(&self) -> usize {
267 self.trades.len()
268 }
269
270 #[must_use]
280 pub const fn interaction_count(&self, stage: InteractionStage) -> usize {
281 self.interactions[stage as usize].len()
282 }
283
284 #[must_use]
290 pub fn is_empty(&self) -> bool {
291 self.trades.is_empty() && self.interactions.iter().all(Vec::is_empty)
292 }
293
294 pub fn clear(&mut self) {
296 self.tokens = SettlementTokenRegistry::new();
297 self.clearing_prices.clear();
298 self.trades.clear();
299 for stage in &mut self.interactions {
300 stage.clear();
301 }
302 }
303
304 fn abi_encode_trades(&self) -> Vec<u8> {
306 let count = self.trades.len();
308 let mut buf = Vec::new();
309
310 buf.extend_from_slice(&abi_u256(U256::from(count)));
312
313 if count == 0 {
314 return buf;
315 }
316
317 let mut encoded_trades: Vec<Vec<u8>> = Vec::with_capacity(count);
320 for trade in &self.trades {
321 encoded_trades.push(abi_encode_trade(trade));
322 }
323
324 let offsets_size = count * 32;
326 let mut cumulative = offsets_size;
327 for enc in &encoded_trades {
328 buf.extend_from_slice(&abi_u256(U256::from(cumulative)));
329 cumulative += enc.len();
330 }
331
332 for enc in encoded_trades {
334 buf.extend_from_slice(&enc);
335 }
336
337 buf
338 }
339
340 fn abi_encode_interactions(&self) -> Vec<u8> {
342 let mut buf = Vec::new();
345
346 let enc0 = abi_encode_interaction_array(&self.interactions[0]);
347 let enc1 = abi_encode_interaction_array(&self.interactions[1]);
348 let enc2 = abi_encode_interaction_array(&self.interactions[2]);
349
350 let head_size = 3 * 32;
351 let offset0 = head_size;
352 let offset1 = offset0 + enc0.len();
353 let offset2 = offset1 + enc1.len();
354
355 buf.extend_from_slice(&abi_u256(U256::from(offset0)));
356 buf.extend_from_slice(&abi_u256(U256::from(offset1)));
357 buf.extend_from_slice(&abi_u256(U256::from(offset2)));
358
359 buf.extend_from_slice(&enc0);
360 buf.extend_from_slice(&enc1);
361 buf.extend_from_slice(&enc2);
362
363 buf
364 }
365}
366
367const fn abi_u256(v: U256) -> [u8; 32] {
371 v.to_be_bytes()
372}
373
374fn abi_address(a: Address) -> [u8; 32] {
376 let mut buf = [0u8; 32];
377 buf[12..].copy_from_slice(a.as_slice());
378 buf
379}
380
381fn abi_encode_address_array(addrs: &[Address]) -> Vec<u8> {
383 let mut buf = Vec::with_capacity(32 + addrs.len() * 32);
384 buf.extend_from_slice(&abi_u256(U256::from(addrs.len())));
385 for addr in addrs {
386 buf.extend_from_slice(&abi_address(*addr));
387 }
388 buf
389}
390
391fn abi_encode_u256_array(values: &[U256]) -> Vec<u8> {
393 let mut buf = Vec::with_capacity(32 + values.len() * 32);
394 buf.extend_from_slice(&abi_u256(U256::from(values.len())));
395 for v in values {
396 buf.extend_from_slice(&abi_u256(*v));
397 }
398 buf
399}
400
401fn abi_encode_trade(trade: &EncodedTrade) -> Vec<u8> {
403 let mut buf = Vec::with_capacity(11 * 32 + 32 + trade.signature.len());
406
407 buf.extend_from_slice(&abi_u256(U256::from(trade.sell_token_index)));
409 buf.extend_from_slice(&abi_u256(U256::from(trade.buy_token_index)));
411 buf.extend_from_slice(&abi_address(trade.receiver));
413 buf.extend_from_slice(&abi_u256(trade.sell_amount));
415 buf.extend_from_slice(&abi_u256(trade.buy_amount));
417 buf.extend_from_slice(&abi_u256(U256::from(trade.valid_to)));
419 buf.extend_from_slice(trade.app_data.as_slice());
421 buf.extend_from_slice(&abi_u256(trade.fee_amount));
423 buf.extend_from_slice(&abi_u256(U256::from(trade.flags)));
425 buf.extend_from_slice(&abi_u256(trade.executed_amount));
427 buf.extend_from_slice(&abi_u256(U256::from(11u64 * 32)));
429 buf.extend_from_slice(&abi_u256(U256::from(trade.signature.len())));
431 buf.extend_from_slice(&trade.signature);
432 let padding = (32 - (trade.signature.len() % 32)) % 32;
434 buf.extend_from_slice(&vec![0u8; padding]);
435
436 buf
437}
438
439fn abi_encode_interaction_array(interactions: &[EncodedInteraction]) -> Vec<u8> {
441 let count = interactions.len();
442 let mut buf = Vec::new();
443
444 buf.extend_from_slice(&abi_u256(U256::from(count)));
445
446 if count == 0 {
447 return buf;
448 }
449
450 let mut encoded: Vec<Vec<u8>> = Vec::with_capacity(count);
452 for ix in interactions {
453 let mut e = Vec::with_capacity(3 * 32 + 32 + ix.calldata.len());
454 e.extend_from_slice(&abi_address(ix.target));
455 e.extend_from_slice(&abi_u256(ix.value));
456 e.extend_from_slice(&abi_u256(U256::from(3u64 * 32)));
458 e.extend_from_slice(&abi_u256(U256::from(ix.calldata.len())));
460 e.extend_from_slice(&ix.calldata);
461 let padding = (32 - (ix.calldata.len() % 32)) % 32;
462 e.extend_from_slice(&vec![0u8; padding]);
463 encoded.push(e);
464 }
465
466 let offsets_size = count * 32;
468 let mut cumulative = offsets_size;
469 for enc in &encoded {
470 buf.extend_from_slice(&abi_u256(U256::from(cumulative)));
471 cumulative += enc.len();
472 }
473 for enc in encoded {
474 buf.extend_from_slice(&enc);
475 }
476
477 buf
478}
479
480#[cfg(test)]
481mod tests {
482 use alloy_primitives::{B256, Bytes, address};
483
484 use super::*;
485 use crate::{OrderKind, SigningScheme, TokenBalance};
486
487 fn sample_order() -> UnsignedOrder {
488 UnsignedOrder {
489 sell_token: address!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
490 buy_token: address!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
491 receiver: Address::ZERO,
492 sell_amount: U256::from(1000),
493 buy_amount: U256::from(900),
494 valid_to: 1_000_000,
495 app_data: B256::ZERO,
496 fee_amount: U256::ZERO,
497 kind: OrderKind::Sell,
498 partially_fillable: false,
499 sell_token_balance: TokenBalance::Erc20,
500 buy_token_balance: TokenBalance::Erc20,
501 }
502 }
503
504 fn sample_signature() -> SignatureData {
505 SignatureData { scheme: SigningScheme::Eip712, data: Bytes::from(vec![0u8; 65]) }
506 }
507
508 #[test]
509 fn new_encoder_is_empty() {
510 let enc = SettlementEncoder::new();
511 assert!(enc.is_empty());
512 assert_eq!(enc.token_count(), 0);
513 assert_eq!(enc.trade_count(), 0);
514 assert_eq!(enc.interaction_count(InteractionStage::Pre), 0);
515 assert_eq!(enc.interaction_count(InteractionStage::Intra), 0);
516 assert_eq!(enc.interaction_count(InteractionStage::Post), 0);
517 }
518
519 #[test]
520 fn default_encoder_is_empty() {
521 let enc = SettlementEncoder::default();
522 assert!(enc.is_empty());
523 }
524
525 #[test]
526 fn add_token_registers_and_returns_index() {
527 let mut enc = SettlementEncoder::new();
528 let a = address!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
529 let b = address!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
530
531 assert_eq!(enc.add_token(a), 0);
532 assert_eq!(enc.add_token(b), 1);
533 assert_eq!(enc.add_token(a), 0);
534 assert_eq!(enc.token_count(), 2);
535 }
536
537 #[test]
538 fn set_clearing_price_extends_vec() {
539 let mut enc = SettlementEncoder::new();
540 enc.set_clearing_price(3, U256::from(42));
541 assert_eq!(enc.clearing_prices.len(), 4);
542 assert_eq!(enc.clearing_prices[3], U256::from(42));
543 assert_eq!(enc.clearing_prices[0], U256::ZERO);
544 }
545
546 #[test]
547 fn add_trade_registers_tokens() {
548 let mut enc = SettlementEncoder::new();
549 enc.add_trade(&sample_order(), &sample_signature(), U256::ZERO);
550 assert_eq!(enc.token_count(), 2);
551 assert_eq!(enc.trade_count(), 1);
552 assert!(!enc.is_empty());
553 }
554
555 #[test]
556 fn add_interaction_counts() {
557 let mut enc = SettlementEncoder::new();
558 enc.add_interaction(InteractionStage::Pre, Address::ZERO, U256::ZERO, vec![0xab]);
559 enc.add_interaction(InteractionStage::Post, Address::ZERO, U256::ZERO, vec![]);
560 enc.add_interaction(InteractionStage::Post, Address::ZERO, U256::from(1), vec![0xcd]);
561
562 assert_eq!(enc.interaction_count(InteractionStage::Pre), 1);
563 assert_eq!(enc.interaction_count(InteractionStage::Intra), 0);
564 assert_eq!(enc.interaction_count(InteractionStage::Post), 2);
565 assert!(!enc.is_empty());
566 }
567
568 #[test]
569 fn clear_resets_everything() {
570 let mut enc = SettlementEncoder::new();
571 enc.add_trade(&sample_order(), &sample_signature(), U256::ZERO);
572 enc.add_interaction(InteractionStage::Pre, Address::ZERO, U256::ZERO, vec![]);
573 enc.set_clearing_price(0, U256::from(1000));
574
575 enc.clear();
576 assert!(enc.is_empty());
577 assert_eq!(enc.token_count(), 0);
578 assert_eq!(enc.trade_count(), 0);
579 assert_eq!(enc.interaction_count(InteractionStage::Pre), 0);
580 }
581
582 #[test]
583 fn encode_settlement_starts_with_selector() {
584 let enc = SettlementEncoder::new();
585 let calldata = enc.encode_settlement();
586
587 let expected_selector = &keccak256(
588 b"settle(address[],uint256[],(uint256,uint256,address,uint256,uint256,uint32,bytes32,uint256,uint256,uint256,bytes)[],(address,uint256,bytes)[][3])",
589 )[..4];
590
591 assert_eq!(&calldata[..4], expected_selector);
592 }
593
594 #[test]
595 fn encode_settlement_empty_is_valid() {
596 let enc = SettlementEncoder::new();
597 let calldata = enc.encode_settlement();
598 assert!(calldata.len() >= 4 + 4 * 32);
600 }
601
602 #[test]
603 fn encode_settlement_with_trade() {
604 let mut enc = SettlementEncoder::new();
605 let order = sample_order();
606 let sig = sample_signature();
607
608 let sell_idx = enc.add_token(order.sell_token);
609 let buy_idx = enc.add_token(order.buy_token);
610 enc.set_clearing_price(sell_idx, U256::from(1000));
611 enc.set_clearing_price(buy_idx, U256::from(900));
612 enc.add_trade(&order, &sig, U256::ZERO);
613
614 let calldata = enc.encode_settlement();
615 assert!(calldata.len() > 4 + 4 * 32 + 2 * 32);
617 }
618
619 #[test]
620 fn encode_settlement_with_interactions() {
621 let mut enc = SettlementEncoder::new();
622 enc.add_interaction(
623 InteractionStage::Pre,
624 address!("cccccccccccccccccccccccccccccccccccccccc"),
625 U256::ZERO,
626 vec![0xde, 0xad, 0xbe, 0xef],
627 );
628 enc.add_interaction(InteractionStage::Post, Address::ZERO, U256::from(1), vec![]);
629
630 let calldata = enc.encode_settlement();
631 assert!(calldata.len() > 4 + 4 * 32);
632 }
633
634 #[test]
635 fn interaction_stage_display() {
636 assert_eq!(format!("{}", InteractionStage::Pre), "Pre");
637 assert_eq!(format!("{}", InteractionStage::Intra), "Intra");
638 assert_eq!(format!("{}", InteractionStage::Post), "Post");
639 }
640
641 #[test]
642 fn interaction_stage_clone_eq() {
643 let a = InteractionStage::Intra;
644 let b = a;
645 assert_eq!(a, b);
646 assert_ne!(InteractionStage::Pre, InteractionStage::Post);
647 }
648
649 #[test]
650 fn encoded_interaction_clone_eq() {
651 let ix = EncodedInteraction {
652 target: Address::ZERO,
653 value: U256::from(42),
654 calldata: vec![0xab, 0xcd],
655 };
656 let ix2 = ix.clone();
657 assert_eq!(ix, ix2);
658 }
659
660 #[test]
661 fn is_empty_with_only_interactions() {
662 let mut enc = SettlementEncoder::new();
663 assert!(enc.is_empty());
664 enc.add_interaction(InteractionStage::Intra, Address::ZERO, U256::ZERO, vec![]);
665 assert!(!enc.is_empty());
666 }
667
668 #[test]
669 fn multiple_trades_encode() {
670 let mut enc = SettlementEncoder::new();
671 let order = sample_order();
672 let sig = sample_signature();
673
674 enc.add_trade(&order, &sig, U256::ZERO);
675 enc.add_trade(&order, &sig, U256::from(100));
676 assert_eq!(enc.trade_count(), 2);
677
678 let calldata = enc.encode_settlement();
679 assert!(calldata.len() > 4 + 4 * 32);
680 }
681
682 #[test]
683 fn add_token_initializes_clearing_price() {
684 let mut enc = SettlementEncoder::new();
685 let idx = enc.add_token(address!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
686 assert_eq!(enc.clearing_prices[idx], U256::ZERO);
687 }
688}