Skip to content

Commit b5a6fcb

Browse files
authored
feat(hubble): support fao-v2 - solve metadata (#4989)
2 parents 3991e06 + 3e93879 commit b5a6fcb

File tree

3 files changed

+169
-4
lines changed

3 files changed

+169
-4
lines changed

hubble/src/indexer/enrich/ucs03_zkgm_0/packet.rs

Lines changed: 164 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const OP_TOKEN_ORDER: u8 = 0x03;
1515
const TOKEN_ORDER_KIND_INITIALIZE: u8 = 0x00;
1616
const TOKEN_ORDER_KIND_ESCROW: u8 = 0x01;
1717
const TOKEN_ORDER_KIND_UNESCROW: u8 = 0x02;
18+
const TOKEN_ORDER_KIND_SOLVE: u8 = 0x03;
1819

1920
sol! {
2021
#[derive(Serialize)]
@@ -96,6 +97,12 @@ sol! {
9697
bytes implementation;
9798
bytes initializer;
9899
}
100+
101+
#[derive(Serialize, Debug)]
102+
struct SolveMetadata {
103+
bytes solverAddress;
104+
bytes metadata;
105+
}
99106
}
100107

101108
impl Serialize for Instruction {
@@ -139,7 +146,7 @@ impl Serialize for TokenOrderV2 {
139146
// Add _metadata field based on metadata_type
140147
let metadata_value = match self.kind {
141148
TOKEN_ORDER_KIND_INITIALIZE => {
142-
// Decode metadata into TokenOrderMetadata
149+
// Decode metadata into TokenMetadata
143150
match <TokenMetadata>::abi_decode_sequence(&self.metadata) {
144151
Ok(decoded) => json!({
145152
"_type": "Initialize",
@@ -160,6 +167,20 @@ impl Serialize for TokenOrderV2 {
160167
"_type": "Unescrow",
161168
"data": self.metadata
162169
}),
170+
TOKEN_ORDER_KIND_SOLVE => {
171+
// Decode metadata into SolveMetadata
172+
match <SolveMetadata>::abi_decode_sequence(&self.metadata) {
173+
Ok(decoded) => json!({
174+
"_type": "Solve",
175+
"solverAddress": decoded.solverAddress,
176+
"metadata": decoded.metadata
177+
}),
178+
Err(_) => json!({
179+
"_type": "Solve",
180+
"error": "failed to decode solve metadata"
181+
}),
182+
}
183+
}
163184
_ => json!({
164185
"_type": "Unsupported",
165186
"data": self.metadata
@@ -457,6 +478,76 @@ mod tests {
457478
);
458479
}
459480

481+
#[test]
482+
fn test_parse_ucs03_zkgm_0_with_token_order_v2_packet_kind_solve() {
483+
// Create a V2 packet with metadata_type = 3 (Solve) using real hex encoding
484+
// replace with hex once packet is on chain
485+
let v2_order = TokenOrderV2 {
486+
sender: alloy_sol_types::private::Bytes::from(hex::decode("756e696f6e316a6b397073796876676b72743263756d7a386579746c6c323234346d326e6e7a347974326732").unwrap()),
487+
receiver: alloy_sol_types::private::Bytes::from(hex::decode("be68fc2d8249eb60bfcf0e71d5a0d2f2e292c4ed").unwrap()),
488+
baseToken: alloy_sol_types::private::Bytes::from(hex::decode("6d756e6f").unwrap()),
489+
baseAmount: alloy_sol_types::private::U256::from(100u64),
490+
quoteToken: alloy_sol_types::private::Bytes::from(hex::decode("ba53d2414765913e7b0b47c3ab3fc1e81006e7ba").unwrap()),
491+
quoteAmount: alloy_sol_types::private::U256::from(100u64),
492+
kind: 3, // solve
493+
metadata: SolveMetadata::abi_encode_params(&SolveMetadata { solverAddress: alloy_sol_types::private::Bytes::from(hex::decode("ba53d2414765913e7b0b47c3ab3fc1e81006e7ba").unwrap()), metadata: alloy_sol_types::private::Bytes::from(hex::decode("deadbeef").unwrap())}).into(),
494+
};
495+
496+
let instruction = Instruction {
497+
version: 2,
498+
opcode: OP_TOKEN_ORDER,
499+
operand: <TokenOrderV2>::abi_encode_sequence(&v2_order).into(),
500+
};
501+
502+
let salt_bytes =
503+
hex::decode("b515a7377bc2f8914aa44085a2d9f9800dec88985123ea2e1a9be5fa4775ae78")
504+
.unwrap();
505+
let mut salt_array = [0u8; 32];
506+
salt_array.copy_from_slice(&salt_bytes);
507+
508+
let zkgm_packet = ZkgmPacket {
509+
salt: alloy_sol_types::private::FixedBytes::from(salt_array),
510+
path: alloy_sol_types::private::U256::from(0u64),
511+
instruction,
512+
};
513+
514+
let encoded = <ZkgmPacket>::abi_encode_sequence(&zkgm_packet);
515+
let hex_string = hex::encode(encoded);
516+
517+
// Use the generated hex for the test
518+
let json = decode(&hex::decode(hex_string).unwrap()).unwrap();
519+
520+
dbg!(serde_json::to_string(&json).unwrap());
521+
522+
assert_eq!(
523+
json,
524+
json!({
525+
"instruction": {
526+
"opcode": 3,
527+
"operand": {
528+
"_type": "TokenOrder",
529+
"sender": "0x756e696f6e316a6b397073796876676b72743263756d7a386579746c6c323234346d326e6e7a347974326732",
530+
"receiver": "0xbe68fc2d8249eb60bfcf0e71d5a0d2f2e292c4ed",
531+
"baseToken": "0x6d756e6f",
532+
"baseAmount": "0x64",
533+
"quoteToken": "0xba53d2414765913e7b0b47c3ab3fc1e81006e7ba",
534+
"quoteAmount": "0x64",
535+
"kind": 3,
536+
"metadata": "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000014ba53d2414765913e7b0b47c3ab3fc1e81006e7ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000",
537+
"_metadata": {
538+
"_type": "Solve",
539+
"solverAddress": "0xba53d2414765913e7b0b47c3ab3fc1e81006e7ba",
540+
"metadata": "0xdeadbeef"
541+
}
542+
},
543+
"version": 2
544+
},
545+
"path": "0x0",
546+
"salt": "0xb515a7377bc2f8914aa44085a2d9f9800dec88985123ea2e1a9be5fa4775ae78"
547+
})
548+
);
549+
}
550+
460551
#[test]
461552
fn test_parse_ucs03_zkgm_0_with_token_order_v2_packet_unsupported_kind() {
462553
// Create a V2 packet with metadata_type = 99 (unsupported) using real hex encoding
@@ -528,8 +619,8 @@ mod tests {
528619
}
529620

530621
#[test]
531-
fn test_parse_ucs03_zkgm_0_with_token_order_v2_packet_unparsable_metadata() {
532-
// Create a V2 packet with metadata_type = 1 but invalid metadata that cannot be parsed
622+
fn test_parse_ucs03_zkgm_0_with_token_order_v2_packet_initialize_unparsable_metadata() {
623+
// Create a V2 packet with metadata_type = 0 (initialize) but invalid metadata that cannot be parsed
533624
use alloy_sol_types::SolType;
534625

535626
let v2_order = TokenOrderV2 {
@@ -597,6 +688,76 @@ mod tests {
597688
);
598689
}
599690

691+
#[test]
692+
fn test_parse_ucs03_zkgm_0_with_token_order_v2_packet_solve_unparsable_metadata() {
693+
// Create a V2 packet with metadata_type = 3 (solve) but invalid metadata that cannot be parsed
694+
use alloy_sol_types::SolType;
695+
696+
let v2_order = TokenOrderV2 {
697+
sender: alloy_sol_types::private::Bytes::from(hex::decode("756e696f6e316a6b397073796876676b72743263756d7a386579746c6c323234346d326e6e7a347974326732").unwrap()),
698+
receiver: alloy_sol_types::private::Bytes::from(hex::decode("be68fc2d8249eb60bfcf0e71d5a0d2f2e292c4ed").unwrap()),
699+
baseToken: alloy_sol_types::private::Bytes::from(hex::decode("6d756e6f").unwrap()),
700+
baseAmount: alloy_sol_types::private::U256::from(100u64),
701+
quoteToken: alloy_sol_types::private::Bytes::from(hex::decode("ba53d2414765913e7b0b47c3ab3fc1e81006e7ba").unwrap()),
702+
quoteAmount: alloy_sol_types::private::U256::from(100u64),
703+
kind: 3, // Solve
704+
metadata: alloy_sol_types::private::Bytes::from(hex::decode("deadbeef").unwrap()), // Invalid/too short for TokenOrderMetadata
705+
};
706+
707+
let instruction = Instruction {
708+
version: 2,
709+
opcode: OP_TOKEN_ORDER,
710+
operand: <TokenOrderV2>::abi_encode_sequence(&v2_order).into(),
711+
};
712+
713+
let salt_bytes =
714+
hex::decode("b515a7377bc2f8914aa44085a2d9f9800dec88985123ea2e1a9be5fa4775ae78")
715+
.unwrap();
716+
let mut salt_array = [0u8; 32];
717+
salt_array.copy_from_slice(&salt_bytes);
718+
719+
let zkgm_packet = ZkgmPacket {
720+
salt: alloy_sol_types::private::FixedBytes::from(salt_array),
721+
path: alloy_sol_types::private::U256::from(0u64),
722+
instruction,
723+
};
724+
725+
let encoded = <ZkgmPacket>::abi_encode_sequence(&zkgm_packet);
726+
let hex_string = hex::encode(encoded);
727+
728+
// Use the generated hex for the test
729+
let json = decode(&hex::decode(hex_string).unwrap()).unwrap();
730+
731+
dbg!(serde_json::to_string(&json).unwrap());
732+
733+
assert_eq!(
734+
json,
735+
json!({
736+
"instruction": {
737+
"opcode": 3,
738+
"operand": {
739+
"_type": "TokenOrder",
740+
"sender": "0x756e696f6e316a6b397073796876676b72743263756d7a386579746c6c323234346d326e6e7a347974326732",
741+
"receiver": "0xbe68fc2d8249eb60bfcf0e71d5a0d2f2e292c4ed",
742+
"baseToken": "0x6d756e6f",
743+
"baseAmount": "0x64",
744+
"quoteToken": "0xba53d2414765913e7b0b47c3ab3fc1e81006e7ba",
745+
"quoteAmount": "0x64",
746+
"kind": 3,
747+
"metadata": "0xdeadbeef",
748+
"_metadata": {
749+
"_type": "Solve",
750+
"error": "failed to decode solve metadata"
751+
}
752+
},
753+
"version": 2
754+
},
755+
"path": "0x0",
756+
"salt": "0xb515a7377bc2f8914aa44085a2d9f9800dec88985123ea2e1a9be5fa4775ae78"
757+
})
758+
);
759+
}
760+
600761
#[test]
601762
fn test_parse_ucs03_zkgm_0_with_xyz() {
602763
let result = decode(&hex::decode("00").unwrap());

hubble/src/indexer/enrich/ucs03_zkgm_0/packet_ack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ mod tests {
960960
}
961961

962962
#[test]
963-
fn test_token_order_v2_initialize_with_ack() {
963+
fn test_token_order_v2_escrow_with_ack() {
964964
let packet = hex::decode("b4536add4924363adf36c5525508616d702ea6c1e60b6544cd1b542f761a02ab0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000002c756e696f6e316a6b397073796876676b72743263756d7a386579746c6c323234346d326e6e7a34797432673200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014be68fc2d8249eb60bfcf0e71d5a0d2f2e292c4ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000046d756e6f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014ba53d2414765913e7b0b47c3ab3fc1e81006e7ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000020457af738e378cb8e744d0dfef10649e127afd4b54efea50c07782464db619280").unwrap();
965965

966966
let ack: &[u8] = &hex::decode("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000b0cad000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000").unwrap();

hubble/src/indexer/handler/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,13 +509,15 @@ pub enum TokenOrderKind {
509509
Initialize,
510510
Escrow,
511511
Unescrow,
512+
Solve,
512513
Unsupported(u8),
513514
}
514515

515516
impl TokenOrderKind {
516517
pub const INITIALIZE: u8 = 0;
517518
pub const ESCROW: u8 = 1;
518519
pub const UNESCROW: u8 = 2;
520+
pub const SOLVE: u8 = 3;
519521
}
520522

521523
impl From<u8> for TokenOrderKind {
@@ -524,6 +526,7 @@ impl From<u8> for TokenOrderKind {
524526
TokenOrderKind::INITIALIZE => TokenOrderKind::Initialize,
525527
TokenOrderKind::ESCROW => TokenOrderKind::Escrow,
526528
TokenOrderKind::UNESCROW => TokenOrderKind::Unescrow,
529+
TokenOrderKind::SOLVE => TokenOrderKind::Solve,
527530
kind => TokenOrderKind::Unsupported(kind),
528531
}
529532
}
@@ -535,6 +538,7 @@ impl From<TokenOrderKind> for u8 {
535538
TokenOrderKind::Initialize => TokenOrderKind::INITIALIZE,
536539
TokenOrderKind::Escrow => TokenOrderKind::ESCROW,
537540
TokenOrderKind::Unescrow => TokenOrderKind::UNESCROW,
541+
TokenOrderKind::Solve => TokenOrderKind::SOLVE,
538542
TokenOrderKind::Unsupported(value) => value,
539543
}
540544
}

0 commit comments

Comments
 (0)