1use std::fmt;
8
9use alloy_primitives::{Address, U256, keccak256};
10use cow_types::{
11 UnsignedOrder,
12 trade::{EncodedTrade, SettlementTokenRegistry, SignatureData, encode_trade},
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub enum InteractionStage {
23 Pre = 0,
25 Intra = 1,
27 Post = 2,
29}
30
31impl fmt::Display for InteractionStage {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 match self {
34 Self::Pre => write!(f, "Pre"),
35 Self::Intra => write!(f, "Intra"),
36 Self::Post => write!(f, "Post"),
37 }
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct EncodedInteraction {
47 pub target: Address,
49 pub value: U256,
51 pub calldata: Vec<u8>,
53}
54
55#[derive(Debug, Clone)]
83pub struct SettlementEncoder {
84 tokens: SettlementTokenRegistry,
86 clearing_prices: Vec<U256>,
88 trades: Vec<EncodedTrade>,
90 interactions: [Vec<EncodedInteraction>; 3],
92}
93
94impl Default for SettlementEncoder {
95 fn default() -> Self {
96 Self::new()
97 }
98}
99
100impl SettlementEncoder {
101 #[must_use]
107 pub fn new() -> Self {
108 Self {
109 tokens: SettlementTokenRegistry::new(),
110 clearing_prices: Vec::new(),
111 trades: Vec::new(),
112 interactions: [Vec::new(), Vec::new(), Vec::new()],
113 }
114 }
115
116 pub fn add_token(&mut self, token: Address) -> usize {
129 let idx = self.tokens.index(token) as usize;
130 if self.clearing_prices.len() <= idx {
132 self.clearing_prices.resize(idx + 1, U256::ZERO);
133 }
134 idx
135 }
136
137 pub fn set_clearing_price(&mut self, token_index: usize, price: U256) {
147 if self.clearing_prices.len() <= token_index {
148 self.clearing_prices.resize(token_index + 1, U256::ZERO);
149 }
150 self.clearing_prices[token_index] = price;
151 }
152
153 pub fn add_trade(
164 &mut self,
165 order: &UnsignedOrder,
166 signature: &SignatureData,
167 executed_amount: U256,
168 ) {
169 let trade = encode_trade(&mut self.tokens, order, signature, executed_amount);
170 let token_count = self.tokens.addresses().len();
172 if self.clearing_prices.len() < token_count {
173 self.clearing_prices.resize(token_count, U256::ZERO);
174 }
175 self.trades.push(trade);
176 }
177
178 pub fn add_interaction(
187 &mut self,
188 stage: InteractionStage,
189 target: Address,
190 value: U256,
191 calldata: Vec<u8>,
192 ) {
193 self.interactions[stage as usize].push(EncodedInteraction { target, value, calldata });
194 }
195
196 #[must_use]
206 pub fn encode_settlement(&self) -> Vec<u8> {
207 let selector = &keccak256(
208 b"settle(address[],uint256[],(uint256,uint256,address,uint256,uint256,uint32,bytes32,uint256,uint256,uint256,bytes)[],(address,uint256,bytes)[][3])",
209 )[..4];
210
211 let tokens = self.tokens.addresses();
212 let mut buf = Vec::with_capacity(4 + 256);
213 buf.extend_from_slice(selector);
214
215 let head_size: usize = 4 * 32;
218
219 let tokens_enc = abi_encode_address_array(tokens);
221 let prices_enc = abi_encode_u256_array(&self.clearing_prices);
222 let trades_enc = self.abi_encode_trades();
223 let interactions_enc = self.abi_encode_interactions();
224
225 let offset_tokens = head_size;
226 let offset_prices = offset_tokens + tokens_enc.len();
227 let offset_trades = offset_prices + prices_enc.len();
228 let offset_interactions = offset_trades + trades_enc.len();
229
230 buf.extend_from_slice(&abi_u256(U256::from(offset_tokens)));
232 buf.extend_from_slice(&abi_u256(U256::from(offset_prices)));
233 buf.extend_from_slice(&abi_u256(U256::from(offset_trades)));
234 buf.extend_from_slice(&abi_u256(U256::from(offset_interactions)));
235
236 buf.extend_from_slice(&tokens_enc);
238 buf.extend_from_slice(&prices_enc);
239 buf.extend_from_slice(&trades_enc);
240 buf.extend_from_slice(&interactions_enc);
241
242 buf
243 }
244
245 #[must_use]
251 pub fn token_count(&self) -> usize {
252 self.tokens.addresses().len()
253 }
254
255 #[must_use]
261 pub const fn trade_count(&self) -> usize {
262 self.trades.len()
263 }
264
265 #[must_use]
275 pub const fn interaction_count(&self, stage: InteractionStage) -> usize {
276 self.interactions[stage as usize].len()
277 }
278
279 #[must_use]
285 pub fn is_empty(&self) -> bool {
286 self.trades.is_empty() && self.interactions.iter().all(Vec::is_empty)
287 }
288
289 pub fn clear(&mut self) {
291 self.tokens = SettlementTokenRegistry::new();
292 self.clearing_prices.clear();
293 self.trades.clear();
294 for stage in &mut self.interactions {
295 stage.clear();
296 }
297 }
298
299 fn abi_encode_trades(&self) -> Vec<u8> {
301 let count = self.trades.len();
303 let mut buf = Vec::new();
304
305 buf.extend_from_slice(&abi_u256(U256::from(count)));
307
308 if count == 0 {
309 return buf;
310 }
311
312 let mut encoded_trades: Vec<Vec<u8>> = Vec::with_capacity(count);
315 for trade in &self.trades {
316 encoded_trades.push(abi_encode_trade(trade));
317 }
318
319 let offsets_size = count * 32;
321 let mut cumulative = offsets_size;
322 for enc in &encoded_trades {
323 buf.extend_from_slice(&abi_u256(U256::from(cumulative)));
324 cumulative += enc.len();
325 }
326
327 for enc in encoded_trades {
329 buf.extend_from_slice(&enc);
330 }
331
332 buf
333 }
334
335 fn abi_encode_interactions(&self) -> Vec<u8> {
337 let mut buf = Vec::new();
340
341 let enc0 = abi_encode_interaction_array(&self.interactions[0]);
342 let enc1 = abi_encode_interaction_array(&self.interactions[1]);
343 let enc2 = abi_encode_interaction_array(&self.interactions[2]);
344
345 let head_size = 3 * 32;
346 let offset0 = head_size;
347 let offset1 = offset0 + enc0.len();
348 let offset2 = offset1 + enc1.len();
349
350 buf.extend_from_slice(&abi_u256(U256::from(offset0)));
351 buf.extend_from_slice(&abi_u256(U256::from(offset1)));
352 buf.extend_from_slice(&abi_u256(U256::from(offset2)));
353
354 buf.extend_from_slice(&enc0);
355 buf.extend_from_slice(&enc1);
356 buf.extend_from_slice(&enc2);
357
358 buf
359 }
360}
361
362const fn abi_u256(v: U256) -> [u8; 32] {
366 v.to_be_bytes()
367}
368
369fn abi_address(a: Address) -> [u8; 32] {
371 let mut buf = [0u8; 32];
372 buf[12..].copy_from_slice(a.as_slice());
373 buf
374}
375
376fn abi_encode_address_array(addrs: &[Address]) -> Vec<u8> {
378 let mut buf = Vec::with_capacity(32 + addrs.len() * 32);
379 buf.extend_from_slice(&abi_u256(U256::from(addrs.len())));
380 for addr in addrs {
381 buf.extend_from_slice(&abi_address(*addr));
382 }
383 buf
384}
385
386fn abi_encode_u256_array(values: &[U256]) -> Vec<u8> {
388 let mut buf = Vec::with_capacity(32 + values.len() * 32);
389 buf.extend_from_slice(&abi_u256(U256::from(values.len())));
390 for v in values {
391 buf.extend_from_slice(&abi_u256(*v));
392 }
393 buf
394}
395
396fn abi_encode_trade(trade: &EncodedTrade) -> Vec<u8> {
398 let mut buf = Vec::with_capacity(11 * 32 + 32 + trade.signature.len());
401
402 buf.extend_from_slice(&abi_u256(U256::from(trade.sell_token_index)));
404 buf.extend_from_slice(&abi_u256(U256::from(trade.buy_token_index)));
406 buf.extend_from_slice(&abi_address(trade.receiver));
408 buf.extend_from_slice(&abi_u256(trade.sell_amount));
410 buf.extend_from_slice(&abi_u256(trade.buy_amount));
412 buf.extend_from_slice(&abi_u256(U256::from(trade.valid_to)));
414 buf.extend_from_slice(trade.app_data.as_slice());
416 buf.extend_from_slice(&abi_u256(trade.fee_amount));
418 buf.extend_from_slice(&abi_u256(U256::from(trade.flags)));
420 buf.extend_from_slice(&abi_u256(trade.executed_amount));
422 buf.extend_from_slice(&abi_u256(U256::from(11u64 * 32)));
424 buf.extend_from_slice(&abi_u256(U256::from(trade.signature.len())));
426 buf.extend_from_slice(&trade.signature);
427 let padding = (32 - (trade.signature.len() % 32)) % 32;
429 buf.extend_from_slice(&vec![0u8; padding]);
430
431 buf
432}
433
434fn abi_encode_interaction_array(interactions: &[EncodedInteraction]) -> Vec<u8> {
436 let count = interactions.len();
437 let mut buf = Vec::new();
438
439 buf.extend_from_slice(&abi_u256(U256::from(count)));
440
441 if count == 0 {
442 return buf;
443 }
444
445 let mut encoded: Vec<Vec<u8>> = Vec::with_capacity(count);
447 for ix in interactions {
448 let mut e = Vec::with_capacity(3 * 32 + 32 + ix.calldata.len());
449 e.extend_from_slice(&abi_address(ix.target));
450 e.extend_from_slice(&abi_u256(ix.value));
451 e.extend_from_slice(&abi_u256(U256::from(3u64 * 32)));
453 e.extend_from_slice(&abi_u256(U256::from(ix.calldata.len())));
455 e.extend_from_slice(&ix.calldata);
456 let padding = (32 - (ix.calldata.len() % 32)) % 32;
457 e.extend_from_slice(&vec![0u8; padding]);
458 encoded.push(e);
459 }
460
461 let offsets_size = count * 32;
463 let mut cumulative = offsets_size;
464 for enc in &encoded {
465 buf.extend_from_slice(&abi_u256(U256::from(cumulative)));
466 cumulative += enc.len();
467 }
468 for enc in encoded {
469 buf.extend_from_slice(&enc);
470 }
471
472 buf
473}
474
475#[cfg(test)]
476mod tests {
477 use alloy_primitives::{B256, Bytes, address};
478
479 use super::*;
480 use cow_types::{OrderKind, SigningScheme, TokenBalance};
481
482 fn sample_order() -> UnsignedOrder {
483 UnsignedOrder {
484 sell_token: address!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
485 buy_token: address!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
486 receiver: Address::ZERO,
487 sell_amount: U256::from(1000),
488 buy_amount: U256::from(900),
489 valid_to: 1_000_000,
490 app_data: B256::ZERO,
491 fee_amount: U256::ZERO,
492 kind: OrderKind::Sell,
493 partially_fillable: false,
494 sell_token_balance: TokenBalance::Erc20,
495 buy_token_balance: TokenBalance::Erc20,
496 }
497 }
498
499 fn sample_signature() -> SignatureData {
500 SignatureData { scheme: SigningScheme::Eip712, data: Bytes::from(vec![0u8; 65]) }
501 }
502
503 #[test]
504 fn new_encoder_is_empty() {
505 let enc = SettlementEncoder::new();
506 assert!(enc.is_empty());
507 assert_eq!(enc.token_count(), 0);
508 assert_eq!(enc.trade_count(), 0);
509 assert_eq!(enc.interaction_count(InteractionStage::Pre), 0);
510 assert_eq!(enc.interaction_count(InteractionStage::Intra), 0);
511 assert_eq!(enc.interaction_count(InteractionStage::Post), 0);
512 }
513
514 #[test]
515 fn default_encoder_is_empty() {
516 let enc = SettlementEncoder::default();
517 assert!(enc.is_empty());
518 }
519
520 #[test]
521 fn add_token_registers_and_returns_index() {
522 let mut enc = SettlementEncoder::new();
523 let a = address!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
524 let b = address!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
525
526 assert_eq!(enc.add_token(a), 0);
527 assert_eq!(enc.add_token(b), 1);
528 assert_eq!(enc.add_token(a), 0);
529 assert_eq!(enc.token_count(), 2);
530 }
531
532 #[test]
533 fn set_clearing_price_extends_vec() {
534 let mut enc = SettlementEncoder::new();
535 enc.set_clearing_price(3, U256::from(42));
536 assert_eq!(enc.clearing_prices.len(), 4);
537 assert_eq!(enc.clearing_prices[3], U256::from(42));
538 assert_eq!(enc.clearing_prices[0], U256::ZERO);
539 }
540
541 #[test]
542 fn add_trade_registers_tokens() {
543 let mut enc = SettlementEncoder::new();
544 enc.add_trade(&sample_order(), &sample_signature(), U256::ZERO);
545 assert_eq!(enc.token_count(), 2);
546 assert_eq!(enc.trade_count(), 1);
547 assert!(!enc.is_empty());
548 }
549
550 #[test]
551 fn add_interaction_counts() {
552 let mut enc = SettlementEncoder::new();
553 enc.add_interaction(InteractionStage::Pre, Address::ZERO, U256::ZERO, vec![0xab]);
554 enc.add_interaction(InteractionStage::Post, Address::ZERO, U256::ZERO, vec![]);
555 enc.add_interaction(InteractionStage::Post, Address::ZERO, U256::from(1), vec![0xcd]);
556
557 assert_eq!(enc.interaction_count(InteractionStage::Pre), 1);
558 assert_eq!(enc.interaction_count(InteractionStage::Intra), 0);
559 assert_eq!(enc.interaction_count(InteractionStage::Post), 2);
560 assert!(!enc.is_empty());
561 }
562
563 #[test]
564 fn clear_resets_everything() {
565 let mut enc = SettlementEncoder::new();
566 enc.add_trade(&sample_order(), &sample_signature(), U256::ZERO);
567 enc.add_interaction(InteractionStage::Pre, Address::ZERO, U256::ZERO, vec![]);
568 enc.set_clearing_price(0, U256::from(1000));
569
570 enc.clear();
571 assert!(enc.is_empty());
572 assert_eq!(enc.token_count(), 0);
573 assert_eq!(enc.trade_count(), 0);
574 assert_eq!(enc.interaction_count(InteractionStage::Pre), 0);
575 }
576
577 #[test]
578 fn encode_settlement_starts_with_selector() {
579 let enc = SettlementEncoder::new();
580 let calldata = enc.encode_settlement();
581
582 let expected_selector = &keccak256(
583 b"settle(address[],uint256[],(uint256,uint256,address,uint256,uint256,uint32,bytes32,uint256,uint256,uint256,bytes)[],(address,uint256,bytes)[][3])",
584 )[..4];
585
586 assert_eq!(&calldata[..4], expected_selector);
587 }
588
589 #[test]
590 fn encode_settlement_empty_is_valid() {
591 let enc = SettlementEncoder::new();
592 let calldata = enc.encode_settlement();
593 assert!(calldata.len() >= 4 + 4 * 32);
595 }
596
597 #[test]
598 fn encode_settlement_with_trade() {
599 let mut enc = SettlementEncoder::new();
600 let order = sample_order();
601 let sig = sample_signature();
602
603 let sell_idx = enc.add_token(order.sell_token);
604 let buy_idx = enc.add_token(order.buy_token);
605 enc.set_clearing_price(sell_idx, U256::from(1000));
606 enc.set_clearing_price(buy_idx, U256::from(900));
607 enc.add_trade(&order, &sig, U256::ZERO);
608
609 let calldata = enc.encode_settlement();
610 assert!(calldata.len() > 4 + 4 * 32 + 2 * 32);
612 }
613
614 #[test]
615 fn encode_settlement_with_interactions() {
616 let mut enc = SettlementEncoder::new();
617 enc.add_interaction(
618 InteractionStage::Pre,
619 address!("cccccccccccccccccccccccccccccccccccccccc"),
620 U256::ZERO,
621 vec![0xde, 0xad, 0xbe, 0xef],
622 );
623 enc.add_interaction(InteractionStage::Post, Address::ZERO, U256::from(1), vec![]);
624
625 let calldata = enc.encode_settlement();
626 assert!(calldata.len() > 4 + 4 * 32);
627 }
628
629 #[test]
630 fn interaction_stage_display() {
631 assert_eq!(format!("{}", InteractionStage::Pre), "Pre");
632 assert_eq!(format!("{}", InteractionStage::Intra), "Intra");
633 assert_eq!(format!("{}", InteractionStage::Post), "Post");
634 }
635
636 #[test]
637 fn interaction_stage_clone_eq() {
638 let a = InteractionStage::Intra;
639 let b = a;
640 assert_eq!(a, b);
641 assert_ne!(InteractionStage::Pre, InteractionStage::Post);
642 }
643
644 #[test]
645 fn encoded_interaction_clone_eq() {
646 let ix = EncodedInteraction {
647 target: Address::ZERO,
648 value: U256::from(42),
649 calldata: vec![0xab, 0xcd],
650 };
651 let ix2 = ix.clone();
652 assert_eq!(ix, ix2);
653 }
654
655 #[test]
656 fn is_empty_with_only_interactions() {
657 let mut enc = SettlementEncoder::new();
658 assert!(enc.is_empty());
659 enc.add_interaction(InteractionStage::Intra, Address::ZERO, U256::ZERO, vec![]);
660 assert!(!enc.is_empty());
661 }
662
663 #[test]
664 fn multiple_trades_encode() {
665 let mut enc = SettlementEncoder::new();
666 let order = sample_order();
667 let sig = sample_signature();
668
669 enc.add_trade(&order, &sig, U256::ZERO);
670 enc.add_trade(&order, &sig, U256::from(100));
671 assert_eq!(enc.trade_count(), 2);
672
673 let calldata = enc.encode_settlement();
674 assert!(calldata.len() > 4 + 4 * 32);
675 }
676
677 #[test]
678 fn add_token_initializes_clearing_price() {
679 let mut enc = SettlementEncoder::new();
680 let idx = enc.add_token(address!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
681 assert_eq!(enc.clearing_prices[idx], U256::ZERO);
682 }
683}