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