1use crate::helpers::{hex_to_string, PortalMatcher, Portals, CARTESI_ADDRESSES};
2use ethers_core::abi::{encode, Token};
3use ethers_core::types::{Address, Bytes, U256};
4use ethers_core::utils::{id, to_checksum};
5
6use hex;
7use json::JsonValue;
8
9#[repr(u32)]
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum TxHexCodes {
12 WithdrawEther = 0x8cf70f0b,
14 WithdrawErc20 = 0x4f94d342,
16 WithdrawErc721 = 0x33acf293,
18 WithdrawErc1155Single = 0x8bb0a811,
20 WithdrawErc1155Batch = 0x50c80019,
22
23 TransferEther = 0x428c9c4d,
25 TransferErc20 = 0x03d61dcd,
27 TransferErc721 = 0xaf615a5a,
29 TransferErc1155Single = 0xe1c913ed,
31 TransferErc1155Batch = 0x638ac6f9,
33
34 Erc20TransferFunctionSelectorFunsel = 0xa9059cbb,
36 Erc721TransferFunctionSelectorFunsel = 0x42842e0e,
38 Erc1155SingleTransferFunctionSelectorFunsel = 0xf242432a,
40 Erc1155BatchTransferFunctionSelectorFunsel = 0x2eb2c2d6,
42}
43
44pub enum CmaVoucherFieldType {
45 EtherVoucherFields(CmaParserEtherVoucherFields),
46 Erc20VoucherFields(CmaParserErc20VoucherFields),
47 Erc721VoucherFields(CmaParserErc721VoucherFields),
48 Erc1155SingleVoucherFields(CmaParserErc1155SingleVoucherFields),
49 Erc1155BatchVoucherFields(CmaParserErc1155BatchVoucherFields),
50}
51
52enum TokenType {
53 Erc20,
54 Erc721,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum CmaParserInputType {
59 CmaParserInputTypeNone,
60 CmaParserInputTypeAuto,
61 CmaParserInputTypeEtherDeposit,
62 CmaParserInputTypeErc20Deposit,
63 CmaParserInputTypeErc721Deposit,
64 CmaParserInputTypeErc1155SingleDeposit,
65 CmaParserInputTypeErc1155BatchDeposit,
66 CmaParserInputTypeEtherWithdrawal,
67 CmaParserInputTypeErc20Withdrawal,
68 CmaParserInputTypeErc721Withdrawal,
69 CmaParserInputTypeErc1155SingleWithdrawal,
70 CmaParserInputTypeErc1155BatchWithdrawal,
71 CmaParserInputTypeEtherTransfer,
72 CmaParserInputTypeErc20Transfer,
73 CmaParserInputTypeErc721Transfer,
74 CmaParserInputTypeErc1155SingleTransfer,
75 CmaParserInputTypeErc1155BatchTransfer,
76 CmaParserInputTypeBalance,
77 CmaParserInputTypeSupply,
78}
79
80impl CmaParserInputType {
81 pub fn from_string(s: &str) -> Self {
82 match s {
83 "EtherDeposit" => CmaParserInputType::CmaParserInputTypeEtherDeposit,
84 "Erc20Deposit" => CmaParserInputType::CmaParserInputTypeErc20Deposit,
85 "Erc721Deposit" => CmaParserInputType::CmaParserInputTypeErc721Deposit,
86 "Erc1155SingleDeposit" => CmaParserInputType::CmaParserInputTypeErc1155SingleDeposit,
87 "Erc1155BatchDeposit" => CmaParserInputType::CmaParserInputTypeErc1155BatchDeposit,
88 "EtherWithdrawal" => CmaParserInputType::CmaParserInputTypeEtherWithdrawal,
89 "Erc20Withdrawal" => CmaParserInputType::CmaParserInputTypeErc20Withdrawal,
90 "Erc721Withdrawal" => CmaParserInputType::CmaParserInputTypeErc721Withdrawal,
91 "Erc1155SingleWithdrawal" => {
92 CmaParserInputType::CmaParserInputTypeErc1155SingleWithdrawal
93 }
94 "Erc1155BatchWithdrawal" => {
95 CmaParserInputType::CmaParserInputTypeErc1155BatchWithdrawal
96 }
97 "EtherTransfer" => CmaParserInputType::CmaParserInputTypeEtherTransfer,
98 "Erc20Transfer" => CmaParserInputType::CmaParserInputTypeErc20Transfer,
99 "Erc721Transfer" => CmaParserInputType::CmaParserInputTypeErc721Transfer,
100 "Erc1155SingleTransfer" => CmaParserInputType::CmaParserInputTypeErc1155SingleTransfer,
101 "Erc1155BatchTransfer" => CmaParserInputType::CmaParserInputTypeErc1155BatchTransfer,
102 "ledgerGetBalance" => CmaParserInputType::CmaParserInputTypeBalance,
103 "ledgerGetTotalSupply" => CmaParserInputType::CmaParserInputTypeSupply,
104 _ => CmaParserInputType::CmaParserInputTypeNone,
105 }
106 }
107}
108
109pub enum CmaParserVoucherType {
110 CmaParserVoucherTypeNone,
111 CmaParserVoucherTypeEther,
112 CmaParserVoucherTypeErc20,
113 CmaParserVoucherTypeErc721,
114 CmaParserVoucherTypeErc1155Single,
115 CmaParserVoucherTypeErc1155Batch,
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
119pub enum CmaParserError {
120 Success,
121 IncompatibleInput,
122 MalformedInput,
123 Unknown,
124 Message(String),
125}
126
127impl CmaParserError {
128 pub fn from_code(code: i32) -> Self {
129 match code {
130 0 => Self::Success,
131 -2001 => Self::IncompatibleInput,
132 -2002 => Self::MalformedInput,
133 -2003 => Self::Unknown,
134 -2004 => Self::Message("Unknown error".to_string()),
135 _ => Self::Unknown,
136 }
137 }
138
139 pub fn to_code(self) -> i32 {
140 match self {
141 Self::Success => 0,
142 Self::IncompatibleInput => -2001,
143 Self::MalformedInput => -2002,
144 Self::Unknown => -2003,
145 Self::Message(_) => -2004,
146 }
147 }
148}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub struct CmaVoucher {
152 pub destination: String,
153 pub value: String,
154 pub payload: String,
155}
156
157pub struct CmaParserVoucherData {
158 pub voucher_fields: CmaVoucherFieldType,
159}
160
161pub struct CmaParserEtherVoucherFields {
162 pub amount: U256,
163 pub receiver: Address,
164}
165pub struct CmaParserErc20VoucherFields {
166 pub token: Address,
167 pub receiver: Address,
168 pub value: U256,
169 pub amount: U256,
170}
171pub struct CmaParserErc721VoucherFields {
172 pub token: Address,
173 pub token_id: U256,
174 pub receiver: Address,
175 pub value: U256,
176 pub application_address: Address,
177}
178pub struct CmaParserErc1155SingleVoucherFields {
179 pub token: Address,
180 pub token_id: U256,
181 pub receiver: Address,
182 pub value: U256,
183 pub amount: U256,
184}
185pub struct CmaParserErc1155BatchVoucherFields {
186 pub token: Address,
187 pub receiver: Address,
188 pub count: usize,
189 pub token_ids: Vec<U256>,
190 pub value: U256,
191 pub amounts: Vec<U256>,
192}
193
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct CmaParserEtherDeposit {
196 pub sender: Address,
197 pub amount: U256,
198 pub exec_layer_data: Bytes,
199}
200
201pub struct CmaParserErc20Deposit {
202 pub sender: Address,
203 pub token: Address,
204 pub amount: U256,
205 pub exec_layer_data: Bytes,
206}
207
208pub struct CmaParserErc721Deposit {
209 pub sender: Address,
210 pub token: Address,
211 pub token_id: U256,
212 pub exec_layer_data: Bytes,
213}
214
215pub struct CmaParserErc1155SingleDeposit {
216 pub sender: Address,
217 pub token: Address,
218 pub token_id: U256,
219 pub amount: U256,
220 pub exec_layer_data: Bytes,
221}
222
223pub struct CmaParserErc1155BatchDeposit {
224 pub sender: Address,
225 pub token: Address,
226 pub count: usize,
227 pub token_ids: Vec<U256>,
228 pub amounts: Vec<U256>,
229 pub base_layer_data: Bytes,
230 pub exec_layer_data: Bytes,
231}
232
233pub struct CmaParserEtherWithdrawal {
234 pub receiver: Address,
235 pub amount: U256,
236 pub exec_layer_data: String,
237}
238
239pub struct CmaParserErc20Withdrawal {
240 pub receiver: Address,
241 pub token: Address,
242 pub amount: U256,
243 pub exec_layer_data: String,
244}
245
246pub struct CmaParserErc721Withdrawal {
247 pub receiver: Address,
248 pub token: Address,
249 pub token_id: U256,
250 pub exec_layer_data: String,
251}
252
253pub struct CmaParserErc1155SingleWithdrawal {
254 pub receiver: Address,
255 pub token: Address,
256 pub token_id: U256,
257 pub amount: U256,
258 pub exec_layer_data: String,
259}
260
261pub struct CmaParserErc1155BatchWithdrawal {
262 pub receiver: Address,
263 pub token: Address,
264 pub count: usize,
265 pub token_ids: Vec<U256>,
266 pub amounts: Vec<U256>,
267 pub base_layer_data: String,
268 pub exec_layer_data: String,
269}
270
271pub struct CmaParserEtherTransfer {
272 pub sender: Address,
273 pub receiver: Address,
274 pub amount: U256,
275 pub exec_layer_data: String,
276}
277
278pub struct CmaParserErc20Transfer {
279 pub sender: Address,
280 pub receiver: Address,
281 pub token: Address,
282 pub amount: U256,
283 pub exec_layer_data: String,
284}
285
286pub struct CmaParserErc721Transfer {
287 pub sender: Address,
288 pub receiver: Address,
289 pub token: Address,
290 pub token_id: U256,
291 pub exec_layer_data: String,
292}
293
294pub struct CmaParserErc1155SingleTransfer {
295 pub sender: Address,
296 pub receiver: Address,
297 pub token: Address,
298 pub token_id: U256,
299 pub amount: U256,
300 pub exec_layer_data: String,
301}
302
303pub struct CmaParserErc1155BatchTransfer {
304 pub sender: Address,
305 pub receiver: Address,
306 pub token: Address,
307 pub count: usize,
308 pub token_ids: Vec<U256>,
309 pub amounts: Vec<U256>,
310 pub base_layer_data: String,
311 pub exec_layer_data: String,
312}
313
314pub struct CmaParserBalance {
315 pub account: Address,
316 pub token: Address,
317 pub token_ids: Option<Vec<U256>>,
318}
319
320pub struct CmaParserSupply {
321 pub token: Address,
322 pub token_ids: Vec<U256>,
323}
324
325pub enum CmaParserInputData {
326 EtherDeposit(CmaParserEtherDeposit),
327 Erc20Deposit(CmaParserErc20Deposit),
328 Erc721Deposit(CmaParserErc721Deposit),
329 Erc1155SingleDeposit(CmaParserErc1155SingleDeposit),
330 Erc1155BatchDeposit(CmaParserErc1155BatchDeposit),
331 EtherWithdrawal(CmaParserEtherWithdrawal),
332 Erc20Withdrawal(CmaParserErc20Withdrawal),
333 Erc721Withdrawal(CmaParserErc721Withdrawal),
334 Erc1155SingleWithdrawal(CmaParserErc1155SingleWithdrawal),
335 Erc1155BatchWithdrawal(CmaParserErc1155BatchWithdrawal),
336 EtherTransfer(CmaParserEtherTransfer),
337 Erc20Transfer(CmaParserErc20Transfer),
338 Erc721Transfer(CmaParserErc721Transfer),
339 Erc1155SingleTransfer(CmaParserErc1155SingleTransfer),
340 Erc1155BatchTransfer(CmaParserErc1155BatchTransfer),
341 Balance(CmaParserBalance),
342 Supply(CmaParserSupply),
343}
344
345pub struct CmaParserInput {
346 pub req_type: CmaParserInputType,
347 pub input: CmaParserInputData,
348}
349
350fn handle_parse_ether_deposit(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
351 let payload_hex = input["data"]["payload"]
352 .as_str()
353 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
354 let payload = payload_hex.trim_start_matches("0x");
355
356 let bytes = hex::decode(payload)
357 .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?;
358
359 if bytes.len() < 20 + 32 {
360 return Err(CmaParserError::Message(
361 "Invalid payload length".to_string(),
362 ));
363 }
364
365 let sender_bytes = &bytes[0..20];
366 let sender = Address::from_slice(sender_bytes);
367
368 let value_bytes = &bytes[20..52];
369 let value = U256::from_big_endian(value_bytes);
370
371 let exec_layer_data = Bytes::from(bytes[52..].to_vec());
372
373 Ok(CmaParserInputData::EtherDeposit(CmaParserEtherDeposit {
374 sender,
375 amount: value,
376 exec_layer_data,
377 }))
378}
379
380fn handle_parse_erc20_and_erc721_deposit(
381 input: JsonValue,
382 t_type: TokenType,
383) -> Result<CmaParserInputData, CmaParserError> {
384 let payload_hex = input["data"]["payload"]
385 .as_str()
386 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
387 let payload = payload_hex.trim_start_matches("0x");
388
389 let bytes = hex::decode(payload)
390 .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?;
391
392 if bytes.len() < 20 + 20 + 32 {
393 return Err(CmaParserError::Message(
394 "Invalid payload length".to_string(),
395 ));
396 }
397
398 let token = &bytes[0..20];
399 let sender = &bytes[20..40];
400 let amount_bytes = &bytes[40..72];
401 let amount = U256::from_big_endian(amount_bytes);
402 let exec_layer_data = Bytes::from(bytes[72..].to_vec());
403
404 match t_type {
405 TokenType::Erc20 => Ok(CmaParserInputData::Erc20Deposit(CmaParserErc20Deposit {
406 sender: Address::from_slice(sender),
407 token: Address::from_slice(token),
408 amount,
409 exec_layer_data,
410 })),
411 TokenType::Erc721 => Ok(CmaParserInputData::Erc721Deposit(CmaParserErc721Deposit {
412 sender: Address::from_slice(sender),
413 token: Address::from_slice(token),
414 token_id: amount,
415 exec_layer_data,
416 })),
417 }
418}
419
420fn handle_parse_erc1155_single_deposit(
421 input: JsonValue,
422) -> Result<CmaParserInputData, CmaParserError> {
423 let payload_hex = input["data"]["payload"]
424 .as_str()
425 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
426 let payload = payload_hex.trim_start_matches("0x");
427
428 let bytes = hex::decode(payload)
429 .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?;
430
431 if bytes.len() < 20 + 20 + 32 + 32 {
432 return Err(CmaParserError::Message(
433 "Invalid payload length".to_string(),
434 ));
435 }
436
437 let token = &bytes[0..20];
438 let sender = &bytes[20..40];
439 let token_id_bytes = &bytes[40..72];
440 let token_id = U256::from_big_endian(token_id_bytes);
441 let amount_bytes = &bytes[72..104];
442 let amount = U256::from_big_endian(amount_bytes);
443 let _base_layer_data = Bytes::from(bytes[104..136].to_vec());
444 let exec_layer_data = Bytes::from(bytes[136..].to_vec());
445
446 Ok(CmaParserInputData::Erc1155SingleDeposit(
447 CmaParserErc1155SingleDeposit {
448 sender: Address::from_slice(sender),
449 token: Address::from_slice(token),
450 token_id,
451 amount,
452 exec_layer_data,
453 },
454 ))
455}
456
457fn handle_parse_erc1155_batch_deposit(
458 input: JsonValue,
459) -> Result<CmaParserInputData, CmaParserError> {
460 let payload_hex = input["data"]["payload"]
461 .as_str()
462 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
463 let payload = payload_hex.trim_start_matches("0x");
464
465 let bytes = hex::decode(payload)
466 .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?;
467
468 if bytes.len() < 20 + 20 + 32 + 32 + 32 {
469 return Err(CmaParserError::Message(
470 "Invalid payload length".to_string(),
471 ));
472 }
473
474 let u256_from = |b: &[u8]| U256::from_big_endian(b);
475 let as_addr = |b: &[u8]| Address::from_slice(&b[12..32]);
476
477 let token = as_addr(&bytes[0..32]);
478 let sender = as_addr(&bytes[32..64]);
479
480 let token_ids_offset = u256_from(&bytes[64..96]).as_usize();
481 let values_offset = u256_from(&bytes[96..128]).as_usize();
482 let base_offset = u256_from(&bytes[128..160]).as_usize();
483 let exec_offset = u256_from(&bytes[160..192]).as_usize();
484
485 let token_ids_len = u256_from(&bytes[token_ids_offset..token_ids_offset + 32]).as_usize();
486 let mut token_ids = Vec::with_capacity(token_ids_len);
487
488 let mut cursor = token_ids_offset + 32;
489 for _ in 0..token_ids_len {
490 token_ids.push(u256_from(&bytes[cursor..cursor + 32]));
491 cursor += 32;
492 }
493
494 let values_len = u256_from(&bytes[values_offset..values_offset + 32]).as_usize();
495 let mut values = Vec::with_capacity(values_len);
496
497 let mut cursor2 = values_offset + 32;
498 for _ in 0..values_len {
499 values.push(u256_from(&bytes[cursor2..cursor2 + 32]));
500 cursor2 += 32;
501 }
502
503 let base_len = u256_from(&bytes[base_offset..base_offset + 32]).as_usize();
504 let base_start = base_offset + 32;
505 let base_end = base_start + base_len;
506 let base_layer_data = Bytes::from(bytes[base_start..base_end].to_vec());
507
508 let exec_len = u256_from(&bytes[exec_offset..exec_offset + 32]).as_usize();
509 let exec_start = exec_offset + 32;
510 let exec_end = exec_start + exec_len;
511 let exec_layer_data = Bytes::from(bytes[exec_start..exec_end].to_vec());
512
513 if token_ids_len == 0 || values_len == 0 || token_ids_len != values_len {
514 return Err(CmaParserError::Message("Invalid payload data".to_string()));
515 }
516
517 Ok(CmaParserInputData::Erc1155BatchDeposit(
518 CmaParserErc1155BatchDeposit {
519 sender,
520 token,
521 count: token_ids_len,
522 token_ids,
523 amounts: values,
524 base_layer_data,
525 exec_layer_data,
526 },
527 ))
528}
529
530fn handle_ether_withdrawal(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
531 let payload_hex = input["data"]["payload"]
532 .as_str()
533 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
534 let payload_str = hex_to_string(payload_hex)
535 .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
536 let msg_sender =
537 input["data"]["metadata"]["msg_sender"]
538 .as_str()
539 .ok_or(CmaParserError::Message(String::from(
540 "Invalid msg_sender address",
541 )))?;
542
543 match json::parse(&payload_str) {
544 Ok(parsed_json) => {
545 let receiver = msg_sender
546 .parse::<Address>()
547 .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
548 let amount_str = parsed_json["amount"]
549 .as_str()
550 .ok_or(CmaParserError::Message(String::from("Invalid amount")))?;
551 let amount = U256::from_dec_str(amount_str)
552 .map_err(|e| CmaParserError::Message(format!("amount parse error: {}", e)))?;
553 let exec_layer_data = parsed_json["exec_layer_data"].to_string();
554
555 Ok(CmaParserInputData::EtherWithdrawal(
556 CmaParserEtherWithdrawal {
557 receiver,
558 amount,
559 exec_layer_data,
560 },
561 ))
562 }
563 Err(_) => Err(CmaParserError::Message(String::from(
564 "Failed to parse JSON payload",
565 ))),
566 }
567}
568
569fn handle_erc20_withdrawal(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
570 let payload_hex = input["data"]["payload"]
571 .as_str()
572 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
573 let payload_str = hex_to_string(payload_hex)
574 .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
575 let msg_sender =
576 input["data"]["metadata"]["msg_sender"]
577 .as_str()
578 .ok_or(CmaParserError::Message(String::from(
579 "Invalid msg_sender address",
580 )))?;
581
582 match json::parse(&payload_str) {
583 Ok(parsed_json) => {
584 let receiver = msg_sender
585 .parse::<Address>()
586 .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
587 let token_str = parsed_json["token"]
588 .as_str()
589 .ok_or(CmaParserError::Message(String::from(
590 "Invalid token address",
591 )))?;
592 let token = token_str
593 .parse::<Address>()
594 .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
595 let amount_str = parsed_json["amount"]
596 .as_str()
597 .ok_or(CmaParserError::Message(String::from("Invalid amount")))?;
598 let amount = U256::from_dec_str(amount_str)
599 .map_err(|e| CmaParserError::Message(format!("amount parse error: {}", e)))?;
600 let exec_layer_data = parsed_json["exec_layer_data"].to_string();
601
602 Ok(CmaParserInputData::Erc20Withdrawal(
603 CmaParserErc20Withdrawal {
604 receiver,
605 token,
606 amount,
607 exec_layer_data,
608 },
609 ))
610 }
611 Err(_) => Err(CmaParserError::Message(String::from(
612 "Failed to parse JSON payload",
613 ))),
614 }
615}
616
617fn handle_erc721_withdrawal(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
618 let payload_hex = input["data"]["payload"]
619 .as_str()
620 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
621 let payload_str = hex_to_string(payload_hex)
622 .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
623 let msg_sender =
624 input["data"]["metadata"]["msg_sender"]
625 .as_str()
626 .ok_or(CmaParserError::Message(String::from(
627 "Invalid msg_sender address",
628 )))?;
629
630 match json::parse(&payload_str) {
631 Ok(parsed_json) => {
632 let receiver = msg_sender
633 .parse::<Address>()
634 .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
635 let token_str = parsed_json["token"]
636 .as_str()
637 .ok_or(CmaParserError::Message(String::from(
638 "Invalid token address",
639 )))?;
640 let token = token_str
641 .parse::<Address>()
642 .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
643 let token_id_str = parsed_json["id"]
644 .as_str()
645 .ok_or(CmaParserError::Message(String::from("Invalid token id")))?;
646 let token_id = U256::from_dec_str(token_id_str)
647 .map_err(|e| CmaParserError::Message(format!("token id parse error: {}", e)))?;
648 let exec_layer_data = parsed_json["exec_layer_data"].to_string();
649
650 Ok(CmaParserInputData::Erc721Withdrawal(
651 CmaParserErc721Withdrawal {
652 receiver,
653 token,
654 token_id,
655 exec_layer_data,
656 },
657 ))
658 }
659 Err(_) => Err(CmaParserError::Message(String::from(
660 "Failed to parse JSON payload",
661 ))),
662 }
663}
664
665fn handle_ether_transfer(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
666 let payload_hex = input["data"]["payload"]
667 .as_str()
668 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
669 let payload_str = hex_to_string(payload_hex)
670 .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
671 let msg_sender =
672 input["data"]["metadata"]["msg_sender"]
673 .as_str()
674 .ok_or(CmaParserError::Message(String::from(
675 "Invalid msg_sender address",
676 )))?;
677
678 match json::parse(&payload_str) {
679 Ok(parsed_json) => {
680 let sender = msg_sender
681 .parse::<Address>()
682 .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
683 let receiver_str = parsed_json["receiver"]
684 .as_str()
685 .ok_or(CmaParserError::Message(String::from(
686 "Invalid receiver address",
687 )))?;
688 let receiver = receiver_str
689 .parse::<Address>()
690 .map_err(|e| CmaParserError::Message(format!("receiver address error: {}", e)))?;
691 let amount_str = parsed_json["amount"]
692 .as_str()
693 .ok_or(CmaParserError::Message(String::from("Invalid amount")))?;
694 let amount = U256::from_dec_str(amount_str)
695 .map_err(|e| CmaParserError::Message(format!("amount parse error: {}", e)))?;
696 let exec_layer_data = parsed_json["exec_layer_data"].to_string();
697
698 Ok(CmaParserInputData::EtherTransfer(CmaParserEtherTransfer {
699 sender,
700 receiver,
701 amount,
702 exec_layer_data,
703 }))
704 }
705 Err(_) => Err(CmaParserError::Message(String::from(
706 "Failed to parse JSON payload",
707 ))),
708 }
709}
710
711fn handle_erc20_transfer(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
712 let payload_hex = input["data"]["payload"]
713 .as_str()
714 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
715 let payload_str = hex_to_string(payload_hex)
716 .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
717 let msg_sender =
718 input["data"]["metadata"]["msg_sender"]
719 .as_str()
720 .ok_or(CmaParserError::Message(String::from(
721 "Invalid msg_sender address",
722 )))?;
723
724 match json::parse(&payload_str) {
725 Ok(parsed_json) => {
726 let sender = msg_sender
727 .parse::<Address>()
728 .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
729 let receiver_str = parsed_json["receiver"]
730 .as_str()
731 .ok_or(CmaParserError::Message(String::from(
732 "Invalid receiver address",
733 )))?;
734 let receiver = receiver_str
735 .parse::<Address>()
736 .map_err(|e| CmaParserError::Message(format!("receiver address error: {}", e)))?;
737 let token_str = parsed_json["token"]
738 .as_str()
739 .ok_or(CmaParserError::Message(String::from(
740 "Invalid token address",
741 )))?;
742 let token = token_str
743 .parse::<Address>()
744 .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
745 let amount_str = parsed_json["amount"]
746 .as_str()
747 .ok_or(CmaParserError::Message(String::from("Invalid amount")))?;
748 let amount = U256::from_dec_str(amount_str)
749 .map_err(|e| CmaParserError::Message(format!("amount parse error: {}", e)))?;
750 let exec_layer_data = parsed_json["exec_layer_data"].to_string();
751
752 Ok(CmaParserInputData::Erc20Transfer(CmaParserErc20Transfer {
753 sender,
754 receiver,
755 token,
756 amount,
757 exec_layer_data,
758 }))
759 }
760 Err(_) => Err(CmaParserError::Message(String::from(
761 "Failed to parse JSON payload",
762 ))),
763 }
764}
765
766fn handle_erc721_transfer(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
767 let payload_hex = input["data"]["payload"]
768 .as_str()
769 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
770 let payload_str = hex_to_string(payload_hex)
771 .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
772 let msg_sender =
773 input["data"]["metadata"]["msg_sender"]
774 .as_str()
775 .ok_or(CmaParserError::Message(String::from(
776 "Invalid msg_sender address",
777 )))?;
778
779 match json::parse(&payload_str) {
780 Ok(parsed_json) => {
781 let sender = msg_sender
782 .parse::<Address>()
783 .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
784 let receiver_str = parsed_json["receiver"]
785 .as_str()
786 .ok_or(CmaParserError::Message(String::from(
787 "Invalid receiver address",
788 )))?;
789 let receiver = receiver_str
790 .parse::<Address>()
791 .map_err(|e| CmaParserError::Message(format!("receiver address error: {}", e)))?;
792 let token_str = parsed_json["token"]
793 .as_str()
794 .ok_or(CmaParserError::Message(String::from(
795 "Invalid token address",
796 )))?;
797 let token = token_str
798 .parse::<Address>()
799 .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
800 let token_id_str = parsed_json["id"]
801 .as_str()
802 .ok_or(CmaParserError::Message(String::from("Invalid token id")))?;
803 let token_id = U256::from_dec_str(token_id_str)
804 .map_err(|e| CmaParserError::Message(format!("token id parse error: {}", e)))?;
805 let exec_layer_data = parsed_json["exec_layer_data"].to_string();
806
807 Ok(CmaParserInputData::Erc721Transfer(
808 CmaParserErc721Transfer {
809 sender,
810 receiver,
811 token,
812 token_id,
813 exec_layer_data,
814 },
815 ))
816 }
817 Err(_) => Err(CmaParserError::Message(String::from(
818 "Failed to parse JSON payload",
819 ))),
820 }
821}
822
823pub fn cma_decode_advance(input: JsonValue) -> Result<CmaParserInput, CmaParserError> {
824 let msg_sender =
825 input["data"]["metadata"]["msg_sender"]
826 .as_str()
827 .ok_or(CmaParserError::Message(String::from(
828 "Invalid msg_sender address",
829 )))?;
830 let req_type: CmaParserInputType;
831
832 match CARTESI_ADDRESSES.match_portal(msg_sender) {
834 Portals::ERC1155BatchPortal => {
835 req_type = CmaParserInputType::CmaParserInputTypeErc1155BatchDeposit;
836 return handle_parse_erc1155_batch_deposit(input).map(|data| CmaParserInput {
837 req_type,
838 input: data,
839 });
840 }
841 Portals::ERC1155SinglePortal => {
842 req_type = CmaParserInputType::CmaParserInputTypeErc1155SingleDeposit;
843 return handle_parse_erc1155_single_deposit(input).map(|data| CmaParserInput {
844 req_type,
845 input: data,
846 });
847 }
848 Portals::ERC721Portal => {
849 req_type = CmaParserInputType::CmaParserInputTypeErc721Deposit;
850 return handle_parse_erc20_and_erc721_deposit(input, TokenType::Erc721).map(|data| {
851 CmaParserInput {
852 req_type,
853 input: data,
854 }
855 });
856 }
857 Portals::ERC20Portal => {
858 req_type = CmaParserInputType::CmaParserInputTypeErc20Deposit;
859 return handle_parse_erc20_and_erc721_deposit(input, TokenType::Erc20).map(|data| {
860 CmaParserInput {
861 req_type,
862 input: data,
863 }
864 });
865 }
866 Portals::EtherPortal => {
867 req_type = CmaParserInputType::CmaParserInputTypeEtherDeposit;
868 return handle_parse_ether_deposit(input).map(|data| CmaParserInput {
869 req_type,
870 input: data,
871 });
872 }
873 Portals::None => {
875 let payload_hex = input["data"]["payload"]
876 .as_str()
877 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
878 let payload_str = hex_to_string(payload_hex).map_err(|e| {
879 CmaParserError::Message(format!("hex to string conversion error: {}", e))
880 })?;
881
882 match json::parse(&payload_str) {
883 Ok(parsed_json) => {
884 let function_type =
885 parsed_json["function_type"]
886 .as_str()
887 .ok_or(CmaParserError::Message(String::from(
888 "Invalid function type",
889 )))?;
890
891 req_type = CmaParserInputType::from_string(function_type);
893
894 match req_type {
896 CmaParserInputType::CmaParserInputTypeEtherWithdrawal => {
897 return handle_ether_withdrawal(input).map(|data| CmaParserInput {
898 req_type,
899 input: data,
900 });
901 }
902
903 CmaParserInputType::CmaParserInputTypeErc20Withdrawal => {
904 return handle_erc20_withdrawal(input).map(|data| CmaParserInput {
905 req_type,
906 input: data,
907 });
908 }
909 CmaParserInputType::CmaParserInputTypeErc721Withdrawal => {
910 return handle_erc721_withdrawal(input).map(|data| CmaParserInput {
911 req_type,
912 input: data,
913 });
914 }
915 CmaParserInputType::CmaParserInputTypeEtherTransfer => {
916 return handle_ether_transfer(input).map(|data| CmaParserInput {
917 req_type,
918 input: data,
919 });
920 }
921 CmaParserInputType::CmaParserInputTypeErc20Transfer => {
922 return handle_erc20_transfer(input).map(|data| CmaParserInput {
923 req_type,
924 input: data,
925 });
926 }
927 CmaParserInputType::CmaParserInputTypeErc721Transfer => {
928 return handle_erc721_transfer(input).map(|data| CmaParserInput {
929 req_type,
930 input: data,
931 });
932 }
933 _ => Err(CmaParserError::IncompatibleInput),
934 }
935 }
936 Err(_) => {
937 return Err(CmaParserError::Message(String::from(
938 "Failed to parse JSON payload",
939 )))
940 }
941 }
942 }
943 }
944}
945
946fn handle_ledger_get_balance(parsed_json: JsonValue) -> Result<CmaParserBalance, CmaParserError> {
947 let params_val = &parsed_json["params"];
949 if !params_val.is_array() {
950 return Err(CmaParserError::Message(
951 "Invalid params: not an array".into(),
952 ));
953 }
954
955 let account_str = params_val[0]
957 .as_str()
958 .ok_or_else(|| CmaParserError::Message("Invalid account param".into()))?;
959
960 let account = account_str
961 .parse::<Address>()
962 .map_err(|e| CmaParserError::Message(format!("account address error: {}", e)))?;
963
964 let token_str = params_val[1]
966 .as_str()
967 .ok_or_else(|| CmaParserError::Message("Invalid token param".into()))?;
968
969 let token = token_str
970 .parse::<Address>()
971 .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
972
973 let mut token_id: Vec<U256> = Vec::new();
975 if params_val.len() > 2 && params_val[2].is_array() {
976 if params_val[2][0].is_array() {
978 for v in params_val[2][0].members() {
979 let s = v
980 .as_str()
981 .ok_or_else(|| CmaParserError::Message("Invalid token id".into()))?;
982 let id = U256::from_dec_str(s)
983 .map_err(|e| CmaParserError::Message(format!("token id parse error: {}", e)))?;
984 token_id.push(id);
985 }
986 } else {
987 for v in params_val[2].members() {
989 if let Some(s) = v.as_str() {
990 if s.contains(',') {
991 for part in s.split(',').map(str::trim).filter(|p| !p.is_empty()) {
992 let id = U256::from_dec_str(part).map_err(|e| {
993 CmaParserError::Message(format!("token id parse error: {}", e))
994 })?;
995 token_id.push(id);
996 }
997 } else {
998 let id = U256::from_dec_str(s).map_err(|e| {
999 CmaParserError::Message(format!("token id parse error: {}", e))
1000 })?;
1001 token_id.push(id);
1002 }
1003 } else if v.is_number() {
1004 let id = U256::from_dec_str(&v.to_string()).map_err(|e| {
1005 CmaParserError::Message(format!("token id parse error: {}", e))
1006 })?;
1007 token_id.push(id);
1008 } else {
1009 return Err(CmaParserError::Message("Invalid token id format".into()));
1010 }
1011 }
1012 }
1013 }
1014
1015 Ok(CmaParserBalance {
1016 account,
1017 token,
1018 token_ids: Some(token_id),
1019 })
1020}
1021
1022fn handle_ledger_get_supply(parsed_json: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
1023 let params_val = &parsed_json["params"];
1025 if !params_val.is_array() {
1026 return Err(CmaParserError::Message(
1027 "Invalid params: not an array".into(),
1028 ));
1029 }
1030
1031 let token_str = params_val[0]
1033 .as_str()
1034 .ok_or_else(|| CmaParserError::Message("Invalid token param".into()))?;
1035
1036 let token = token_str
1037 .parse::<Address>()
1038 .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
1039
1040 let mut token_id: Vec<U256> = Vec::new();
1042 if params_val.len() > 1 && params_val[1].is_array() {
1043 if params_val[1][0].is_array() {
1045 for v in params_val[1][0].members() {
1046 let s = v
1047 .as_str()
1048 .ok_or_else(|| CmaParserError::Message("Invalid token id".into()))?;
1049 let id = U256::from_dec_str(s)
1050 .map_err(|e| CmaParserError::Message(format!("token id parse error: {}", e)))?;
1051 token_id.push(id);
1052 }
1053 } else {
1054 for v in params_val[1].members() {
1056 if let Some(s) = v.as_str() {
1057 if s.contains(',') {
1058 for part in s.split(',').map(str::trim).filter(|p| !p.is_empty()) {
1059 let id = U256::from_dec_str(part).map_err(|e| {
1060 CmaParserError::Message(format!("token id parse error: {}", e))
1061 })?;
1062 token_id.push(id);
1063 }
1064 } else {
1065 let id = U256::from_dec_str(s).map_err(|e| {
1066 CmaParserError::Message(format!("token id parse error: {}", e))
1067 })?;
1068 token_id.push(id);
1069 }
1070 } else if v.is_number() {
1071 let id = U256::from_dec_str(&v.to_string()).map_err(|e| {
1072 CmaParserError::Message(format!("token id parse error: {}", e))
1073 })?;
1074 token_id.push(id);
1075 } else {
1076 return Err(CmaParserError::Message("Invalid token id format".into()));
1077 }
1078 }
1079 }
1080 }
1081
1082 Ok(CmaParserInputData::Supply(CmaParserSupply {
1083 token,
1084 token_ids: token_id,
1085 }))
1086}
1087
1088pub fn cma_decode_inspect(input: JsonValue) -> Result<CmaParserInput, CmaParserError> {
1089 let payload_hex = input["data"]["payload"]
1090 .as_str()
1091 .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
1092 let payload_str = hex_to_string(payload_hex)
1093 .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
1094 let payload_json = json::parse(&payload_str)
1095 .map_err(|e| CmaParserError::Message(format!("Error parsing string to JSON: {}", e)))?;
1096
1097 let req_type: CmaParserInputType =
1098 CmaParserInputType::from_string(payload_json["method"].as_str().ok_or(
1099 CmaParserError::Message(String::from("Invalid inspection type")),
1100 )?);
1101
1102 match req_type {
1103 CmaParserInputType::CmaParserInputTypeBalance => {
1104 return handle_ledger_get_balance(payload_json).map(|data| CmaParserInput {
1105 req_type,
1106 input: CmaParserInputData::Balance(data),
1107 });
1108 }
1109 CmaParserInputType::CmaParserInputTypeSupply => {
1110 return handle_ledger_get_supply(payload_json).map(|data| CmaParserInput {
1111 req_type,
1112 input: data,
1113 });
1114 }
1115 _ => {
1116 return Err(CmaParserError::IncompatibleInput);
1118 }
1119 }
1120}
1121
1122fn handle_ether_voucher_encoding(
1123 voucher_request: &CmaParserVoucherData,
1124) -> Result<CmaVoucher, CmaParserError> {
1125 if let CmaVoucherFieldType::EtherVoucherFields(fields) = &voucher_request.voucher_fields {
1126 let payload = "0x".to_string();
1127
1128 let mut value_bytes = [0u8; 32];
1129 fields.amount.to_big_endian(&mut value_bytes);
1130
1131 let voucher = CmaVoucher {
1132 destination: to_checksum(&fields.receiver, None),
1133 value: format!("0x{}", hex::encode(value_bytes)),
1134 payload,
1135 };
1136
1137 Ok(voucher)
1138 } else {
1139 Err(CmaParserError::Message(String::from(
1140 "Invalid voucher fields for Ether",
1141 )))
1142 }
1143}
1144
1145fn handle_erc20_voucher_encoding(
1146 voucher_request: &CmaParserVoucherData,
1147) -> Result<CmaVoucher, CmaParserError> {
1148 if let CmaVoucherFieldType::Erc20VoucherFields(fields) = &voucher_request.voucher_fields {
1149 let token = fields.token;
1150
1151 let args: Vec<Token> = vec![Token::Address(fields.receiver), Token::Uint(fields.amount)];
1152
1153 let function_sig = "transfer(address,uint256)";
1154 let selector = &id(function_sig)[..4];
1155
1156 let encoded_args = encode(&args);
1157 let value = fields.value;
1158 let mut payload_bytes = Vec::new();
1159 payload_bytes.extend_from_slice(selector);
1160 payload_bytes.extend_from_slice(&encoded_args);
1161 let payload = format!("0x{}", hex::encode(payload_bytes));
1162
1163 let mut value_bytes = [0u8; 32];
1164 value.to_big_endian(&mut value_bytes);
1165
1166 let voucher = CmaVoucher {
1167 destination: format!("{:?}", token),
1168 value: format!("0x{}", hex::encode(value_bytes)),
1169 payload: format!("{}", payload),
1170 };
1171 return Ok(voucher);
1172 } else {
1173 Err(CmaParserError::Message(String::from(
1174 "Invalid voucher fields for ERC20",
1175 )))
1176 }
1177}
1178
1179fn handle_erc721_voucher_encoding(
1180 voucher_request: &CmaParserVoucherData,
1181) -> Result<CmaVoucher, CmaParserError> {
1182 if let CmaVoucherFieldType::Erc721VoucherFields(fields) = &voucher_request.voucher_fields {
1183 let token = fields.token;
1184
1185 let args: Vec<Token> = vec![
1186 Token::Address(fields.application_address),
1187 Token::Address(fields.receiver),
1188 Token::Uint(fields.token_id.into()),
1189 ];
1190 let function_sig = "transferFrom(address,address,uint256)";
1191 let selector = &id(function_sig)[..4];
1192 let encoded_args = encode(&args);
1193 let value = fields.value;
1194 let mut payload_bytes = Vec::new();
1195 payload_bytes.extend_from_slice(selector);
1196 payload_bytes.extend_from_slice(&encoded_args);
1197 let payload = format!("0x{}", hex::encode(payload_bytes));
1198
1199 let mut value_bytes = [0u8; 32];
1200 value.to_big_endian(&mut value_bytes);
1201
1202 let voucher = CmaVoucher {
1203 destination: format!("{:?}", token),
1204 value: format!("0x{}", hex::encode(value_bytes)),
1205 payload: format!("{}", payload),
1206 };
1207
1208 return Ok(voucher);
1209 } else {
1210 Err(CmaParserError::Message(String::from(
1211 "Invalid voucher fields for ERC721",
1212 )))
1213 }
1214}
1215
1216pub fn cma_encode_voucher(
1217 req_type: CmaParserVoucherType,
1218 voucher_request: CmaParserVoucherData,
1219) -> Result<CmaVoucher, CmaParserError> {
1220 match req_type {
1221 CmaParserVoucherType::CmaParserVoucherTypeEther => {
1222 return handle_ether_voucher_encoding(&voucher_request);
1223 }
1224 CmaParserVoucherType::CmaParserVoucherTypeErc20 => {
1225 return handle_erc20_voucher_encoding(&voucher_request);
1226 }
1227 CmaParserVoucherType::CmaParserVoucherTypeErc721 => {
1228 return handle_erc721_voucher_encoding(&voucher_request);
1229 }
1230 CmaParserVoucherType::CmaParserVoucherTypeErc1155Single => {
1231 return Err(CmaParserError::Message(String::from("Not Implemented yet")));
1233 }
1234 CmaParserVoucherType::CmaParserVoucherTypeErc1155Batch => {
1235 return Err(CmaParserError::Message(String::from("Not Implemented yet")));
1237 }
1238 CmaParserVoucherType::CmaParserVoucherTypeNone => {
1239 return Err(CmaParserError::Message(String::from("Not Implemented yet")))
1240 }
1241 }
1242}