1use crate::error::SignerError;
29use sha3::{Digest, Keccak256};
30
31#[derive(Debug, Clone, PartialEq)]
35pub enum AbiValue {
36 Uint256([u8; 32]),
38 Int256([u8; 32]),
40 Address([u8; 20]),
42 Bool(bool),
44 FixedBytes(Vec<u8>),
46 Bytes(Vec<u8>),
48 String(String),
50 Array(Vec<AbiValue>),
52 Tuple(Vec<AbiValue>),
54}
55
56impl AbiValue {
57 #[must_use]
59 pub fn from_u64(val: u64) -> Self {
60 let mut buf = [0u8; 32];
61 buf[24..].copy_from_slice(&val.to_be_bytes());
62 AbiValue::Uint256(buf)
63 }
64
65 #[must_use]
67 pub fn from_u128(val: u128) -> Self {
68 let mut buf = [0u8; 32];
69 buf[16..].copy_from_slice(&val.to_be_bytes());
70 AbiValue::Uint256(buf)
71 }
72
73 fn is_dynamic(&self) -> bool {
75 matches!(
76 self,
77 AbiValue::Bytes(_) | AbiValue::String(_) | AbiValue::Array(_)
78 ) || matches!(self, AbiValue::Tuple(items) if items.iter().any(|i| i.is_dynamic()))
79 }
80
81 fn encode_head(&self) -> Vec<u8> {
83 match self {
84 AbiValue::Uint256(val) => val.to_vec(),
85 AbiValue::Int256(val) => val.to_vec(),
86 AbiValue::Address(addr) => {
87 let mut buf = [0u8; 32];
88 buf[12..].copy_from_slice(addr);
89 buf.to_vec()
90 }
91 AbiValue::Bool(b) => {
92 let mut buf = [0u8; 32];
93 buf[31] = if *b { 1 } else { 0 };
94 buf.to_vec()
95 }
96 AbiValue::FixedBytes(data) => {
97 let mut buf = [0u8; 32];
98 let len = data.len().min(32);
99 buf[..len].copy_from_slice(&data[..len]);
100 buf.to_vec()
101 }
102 _ => vec![0u8; 32],
104 }
105 }
106
107 fn encode_tail(&self) -> Vec<u8> {
109 match self {
110 AbiValue::Bytes(data) => encode_dynamic_bytes(data),
111 AbiValue::String(s) => encode_dynamic_bytes(s.as_bytes()),
112 AbiValue::Array(items) => {
113 let mut buf = Vec::new();
114 let mut len = [0u8; 32];
116 len[24..].copy_from_slice(&(items.len() as u64).to_be_bytes());
117 buf.extend_from_slice(&len);
118 buf.extend_from_slice(&encode_tuple(items));
120 buf
121 }
122 AbiValue::Tuple(items) => encode_tuple(items),
123 _ => vec![], }
125 }
126}
127
128pub fn encode(values: &[AbiValue]) -> Vec<u8> {
134 encode_tuple(values)
135}
136
137pub fn encode_packed(values: &[AbiValue]) -> Vec<u8> {
142 let mut buf = Vec::new();
143 for v in values {
144 match v {
145 AbiValue::Uint256(val) => {
146 let start = val.iter().position(|b| *b != 0).unwrap_or(31);
148 buf.extend_from_slice(&val[start..]);
149 }
150 AbiValue::Int256(val) => buf.extend_from_slice(val),
151 AbiValue::Address(addr) => buf.extend_from_slice(addr),
152 AbiValue::Bool(b) => buf.push(if *b { 1 } else { 0 }),
153 AbiValue::FixedBytes(data) => buf.extend_from_slice(data),
154 AbiValue::Bytes(data) => buf.extend_from_slice(data),
155 AbiValue::String(s) => buf.extend_from_slice(s.as_bytes()),
156 AbiValue::Array(items) => {
157 for item in items {
158 buf.extend_from_slice(&encode_packed(std::slice::from_ref(item)));
159 }
160 }
161 AbiValue::Tuple(items) => {
162 buf.extend_from_slice(&encode_packed(items));
163 }
164 }
165 }
166 buf
167}
168
169pub fn encode_and_hash(values: &[AbiValue]) -> [u8; 32] {
171 keccak256(&encode(values))
172}
173
174pub fn encode_packed_and_hash(values: &[AbiValue]) -> [u8; 32] {
178 keccak256(&encode_packed(values))
179}
180
181pub struct Function {
198 signature: String,
200 selector_bytes: [u8; 4],
202}
203
204impl Function {
205 #[must_use]
209 pub fn new(signature: &str) -> Self {
210 let hash = keccak256(signature.as_bytes());
211 let mut selector = [0u8; 4];
212 selector.copy_from_slice(&hash[..4]);
213 Self {
214 signature: signature.to_string(),
215 selector_bytes: selector,
216 }
217 }
218
219 #[must_use]
221 pub fn selector(&self) -> [u8; 4] {
222 self.selector_bytes
223 }
224
225 #[must_use]
227 pub fn signature(&self) -> &str {
228 &self.signature
229 }
230
231 #[must_use]
235 pub fn encode(&self, args: &[AbiValue]) -> Vec<u8> {
236 let mut calldata = Vec::with_capacity(4 + args.len() * 32);
237 calldata.extend_from_slice(&self.selector_bytes);
238 calldata.extend_from_slice(&encode(args));
239 calldata
240 }
241}
242
243#[must_use]
247pub fn function_selector(signature: &str) -> [u8; 4] {
248 Function::new(signature).selector()
249}
250
251#[must_use]
255pub fn event_topic(signature: &str) -> [u8; 32] {
256 keccak256(signature.as_bytes())
257}
258
259pub fn decode_uint256(data: &[u8]) -> Result<[u8; 32], SignerError> {
263 if data.len() < 32 {
264 return Err(SignerError::ParseError(
265 "ABI: need 32 bytes for uint256".into(),
266 ));
267 }
268 let mut buf = [0u8; 32];
269 buf.copy_from_slice(&data[..32]);
270 Ok(buf)
271}
272
273pub fn decode_uint256_as_u64(data: &[u8]) -> Result<u64, SignerError> {
275 let raw = decode_uint256(data)?;
276 if raw[..24].iter().any(|b| *b != 0) {
278 return Err(SignerError::ParseError(
279 "ABI: uint256 overflow for u64".into(),
280 ));
281 }
282 let mut buf = [0u8; 8];
283 buf.copy_from_slice(&raw[24..32]);
284 Ok(u64::from_be_bytes(buf))
285}
286
287pub fn decode_address(data: &[u8]) -> Result<[u8; 20], SignerError> {
289 if data.len() < 32 {
290 return Err(SignerError::ParseError(
291 "ABI: need 32 bytes for address".into(),
292 ));
293 }
294 let mut addr = [0u8; 20];
295 addr.copy_from_slice(&data[12..32]);
296 Ok(addr)
297}
298
299pub fn decode_bool(data: &[u8]) -> Result<bool, SignerError> {
301 if data.len() < 32 {
302 return Err(SignerError::ParseError(
303 "ABI: need 32 bytes for bool".into(),
304 ));
305 }
306 Ok(data[31] != 0)
307}
308
309pub fn decode_bytes(data: &[u8], param_offset: usize) -> Result<Vec<u8>, SignerError> {
313 let offset = decode_uint256_as_u64(&data[param_offset..])? as usize;
315 if offset + 32 > data.len() {
317 return Err(SignerError::ParseError(
318 "ABI: bytes offset out of range".into(),
319 ));
320 }
321 let len = decode_uint256_as_u64(&data[offset..])? as usize;
322 let start = offset + 32;
323 if start + len > data.len() {
324 return Err(SignerError::ParseError("ABI: bytes data truncated".into()));
325 }
326 Ok(data[start..start + len].to_vec())
327}
328
329pub fn decode_string(data: &[u8], param_offset: usize) -> Result<String, SignerError> {
331 let bytes = decode_bytes(data, param_offset)?;
332 String::from_utf8(bytes)
333 .map_err(|e| SignerError::ParseError(format!("ABI: invalid UTF-8: {e}")))
334}
335
336#[must_use]
346pub fn encode_constructor(bytecode: &[u8], constructor_args: &[AbiValue]) -> Vec<u8> {
347 let mut data = bytecode.to_vec();
348 if !constructor_args.is_empty() {
349 data.extend_from_slice(&encode(constructor_args));
350 }
351 data
352}
353
354#[allow(clippy::too_many_arguments)]
356pub fn deploy_contract(
357 signer: &super::EthereumSigner,
358 bytecode: &[u8],
359 constructor_args: &[AbiValue],
360 chain_id: u64,
361 nonce: u64,
362 max_priority_fee_per_gas: u128,
363 max_fee_per_gas: u128,
364 gas_limit: u64,
365) -> Result<super::transaction::SignedTransaction, SignerError> {
366 let tx = super::transaction::EIP1559Transaction {
367 chain_id,
368 nonce,
369 max_priority_fee_per_gas,
370 max_fee_per_gas,
371 gas_limit,
372 to: None, value: 0,
374 data: encode_constructor(bytecode, constructor_args),
375 access_list: vec![],
376 };
377 tx.sign(signer)
378}
379
380pub struct ContractCall {
399 contract: [u8; 20],
401 function: Function,
403 args: Vec<AbiValue>,
405 value_wei: u128,
407}
408
409impl ContractCall {
410 #[must_use]
412 pub fn new(contract: [u8; 20], function_signature: &str) -> Self {
413 Self {
414 contract,
415 function: Function::new(function_signature),
416 args: Vec::new(),
417 value_wei: 0,
418 }
419 }
420
421 #[must_use]
423 pub fn args(mut self, args: &[AbiValue]) -> Self {
424 self.args = args.to_vec();
425 self
426 }
427
428 #[must_use]
430 pub fn value(mut self, value_wei: u128) -> Self {
431 self.value_wei = value_wei;
432 self
433 }
434
435 #[must_use]
439 pub fn calldata(&self) -> Vec<u8> {
440 self.function.encode(&self.args)
441 }
442
443 pub fn sign(
445 &self,
446 signer: &super::EthereumSigner,
447 chain_id: u64,
448 nonce: u64,
449 max_priority_fee_per_gas: u128,
450 max_fee_per_gas: u128,
451 gas_limit: u64,
452 ) -> Result<super::transaction::SignedTransaction, SignerError> {
453 let tx = super::transaction::EIP1559Transaction {
454 chain_id,
455 nonce,
456 max_priority_fee_per_gas,
457 max_fee_per_gas,
458 gas_limit,
459 to: Some(self.contract),
460 value: self.value_wei,
461 data: self.calldata(),
462 access_list: vec![],
463 };
464 tx.sign(signer)
465 }
466}
467
468fn keccak256(data: &[u8]) -> [u8; 32] {
471 let mut out = [0u8; 32];
472 out.copy_from_slice(&Keccak256::digest(data));
473 out
474}
475
476fn encode_dynamic_bytes(data: &[u8]) -> Vec<u8> {
477 let mut buf = Vec::new();
478 let mut len = [0u8; 32];
480 len[24..].copy_from_slice(&(data.len() as u64).to_be_bytes());
481 buf.extend_from_slice(&len);
482 buf.extend_from_slice(data);
484 let padding = (32 - (data.len() % 32)) % 32;
485 buf.extend_from_slice(&vec![0u8; padding]);
486 buf
487}
488
489fn encode_tuple(values: &[AbiValue]) -> Vec<u8> {
490 let head_size = values.len() * 32;
491 let mut heads = Vec::with_capacity(head_size);
492 let mut tails = Vec::new();
493
494 for v in values {
495 if v.is_dynamic() {
496 let offset = head_size + tails.len();
498 let mut offset_bytes = [0u8; 32];
499 offset_bytes[24..].copy_from_slice(&(offset as u64).to_be_bytes());
500 heads.extend_from_slice(&offset_bytes);
501 tails.extend_from_slice(&v.encode_tail());
502 } else {
503 heads.extend_from_slice(&v.encode_head());
504 }
505 }
506
507 let mut result = Vec::with_capacity(heads.len() + tails.len());
508 result.extend_from_slice(&heads);
509 result.extend_from_slice(&tails);
510 result
511}
512
513#[cfg(test)]
516#[allow(clippy::unwrap_used, clippy::expect_used)]
517mod tests {
518 use super::*;
519 use crate::traits::KeyPair;
520
521 #[test]
524 fn test_selector_transfer() {
525 let sel = function_selector("transfer(address,uint256)");
527 assert_eq!(hex::encode(sel), "a9059cbb");
528 }
529
530 #[test]
531 fn test_selector_approve() {
532 let sel = function_selector("approve(address,uint256)");
534 assert_eq!(hex::encode(sel), "095ea7b3");
535 }
536
537 #[test]
538 fn test_selector_balance_of() {
539 let sel = function_selector("balanceOf(address)");
541 assert_eq!(hex::encode(sel), "70a08231");
542 }
543
544 #[test]
545 fn test_selector_total_supply() {
546 let sel = function_selector("totalSupply()");
548 assert_eq!(hex::encode(sel), "18160ddd");
549 }
550
551 #[test]
552 fn test_event_topic_transfer() {
553 let topic = event_topic("Transfer(address,address,uint256)");
555 assert_eq!(
556 hex::encode(topic),
557 "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
558 );
559 }
560
561 #[test]
562 fn test_event_topic_approval() {
563 let topic = event_topic("Approval(address,address,uint256)");
564 assert_eq!(
565 hex::encode(topic),
566 "8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"
567 );
568 }
569
570 #[test]
573 fn test_encode_uint256() {
574 let val = AbiValue::from_u64(42);
575 let encoded = encode(&[val]);
576 assert_eq!(encoded.len(), 32);
577 assert_eq!(encoded[31], 42);
578 assert!(encoded[..31].iter().all(|b| *b == 0));
579 }
580
581 #[test]
582 fn test_encode_address() {
583 let addr = [0xAA; 20];
584 let encoded = encode(&[AbiValue::Address(addr)]);
585 assert_eq!(encoded.len(), 32);
586 assert!(encoded[..12].iter().all(|b| *b == 0)); assert_eq!(&encoded[12..], &[0xAA; 20]);
588 }
589
590 #[test]
591 fn test_encode_bool() {
592 let encoded_true = encode(&[AbiValue::Bool(true)]);
593 assert_eq!(encoded_true[31], 1);
594 let encoded_false = encode(&[AbiValue::Bool(false)]);
595 assert_eq!(encoded_false[31], 0);
596 }
597
598 #[test]
599 fn test_encode_dynamic_bytes() {
600 let data = vec![0xDE, 0xAD, 0xBE, 0xEF];
601 let encoded = encode(&[AbiValue::Bytes(data.clone())]);
602 assert_eq!(encoded[31], 32);
604 assert_eq!(encoded[63], 4); assert_eq!(&encoded[64..68], &data);
607 }
608
609 #[test]
610 fn test_encode_string() {
611 let s = "hello";
612 let encoded = encode(&[AbiValue::String(s.to_string())]);
613 assert_eq!(encoded[31], 32); assert_eq!(encoded[63], 5); assert_eq!(&encoded[64..69], b"hello");
616 }
617
618 #[test]
619 fn test_encode_multiple_static() {
620 let encoded = encode(&[AbiValue::Address([0xBB; 20]), AbiValue::from_u64(100)]);
622 assert_eq!(encoded.len(), 64); assert_eq!(&encoded[12..32], &[0xBB; 20]);
624 assert_eq!(encoded[63], 100);
625 }
626
627 #[test]
628 fn test_function_encode_transfer() {
629 let transfer = Function::new("transfer(address,uint256)");
630 let calldata = transfer.encode(&[AbiValue::Address([0xCC; 20]), AbiValue::from_u64(1000)]);
631 assert_eq!(&calldata[..4], &hex::decode("a9059cbb").unwrap());
632 assert_eq!(calldata.len(), 4 + 64);
633 }
634
635 #[test]
638 fn test_encode_packed_address_uint() {
639 let packed = encode_packed(&[AbiValue::Address([0xAA; 20]), AbiValue::from_u64(1)]);
640 assert_eq!(&packed[..20], &[0xAA; 20]);
642 assert_eq!(packed[20], 1);
643 }
644
645 #[test]
646 fn test_encode_packed_and_hash() {
647 let hash = encode_packed_and_hash(&[
648 AbiValue::String("hello".to_string()),
649 AbiValue::String("world".to_string()),
650 ]);
651 let expected = keccak256(b"helloworld");
653 assert_eq!(hash, expected);
654 }
655
656 #[test]
659 fn test_decode_uint256_roundtrip() {
660 let val = AbiValue::from_u64(12345);
661 let encoded = encode(&[val]);
662 let decoded = decode_uint256_as_u64(&encoded).unwrap();
663 assert_eq!(decoded, 12345);
664 }
665
666 #[test]
667 fn test_decode_address_roundtrip() {
668 let addr = [0xDD; 20];
669 let encoded = encode(&[AbiValue::Address(addr)]);
670 let decoded = decode_address(&encoded).unwrap();
671 assert_eq!(decoded, addr);
672 }
673
674 #[test]
675 fn test_decode_bool_roundtrip() {
676 let encoded = encode(&[AbiValue::Bool(true)]);
677 assert!(decode_bool(&encoded).unwrap());
678 let encoded = encode(&[AbiValue::Bool(false)]);
679 assert!(!decode_bool(&encoded).unwrap());
680 }
681
682 #[test]
683 fn test_decode_bytes_roundtrip() {
684 let data = vec![0xCA, 0xFE, 0xBA, 0xBE];
685 let encoded = encode(&[AbiValue::Bytes(data.clone())]);
686 let decoded = decode_bytes(&encoded, 0).unwrap();
687 assert_eq!(decoded, data);
688 }
689
690 #[test]
691 fn test_decode_string_roundtrip() {
692 let s = "Hello, Ethereum!";
693 let encoded = encode(&[AbiValue::String(s.to_string())]);
694 let decoded = decode_string(&encoded, 0).unwrap();
695 assert_eq!(decoded, s);
696 }
697
698 #[test]
701 fn test_encode_constructor_no_args() {
702 let bytecode = vec![0x60, 0x00, 0x60, 0x00]; let data = encode_constructor(&bytecode, &[]);
704 assert_eq!(data, bytecode);
705 }
706
707 #[test]
708 fn test_encode_constructor_with_args() {
709 let bytecode = vec![0x60, 0x00];
710 let data = encode_constructor(&bytecode, &[AbiValue::from_u64(42)]);
711 assert_eq!(&data[..2], &bytecode);
712 assert_eq!(data.len(), 2 + 32);
713 assert_eq!(data[33], 42);
714 }
715
716 #[test]
717 fn test_deploy_contract_signs() {
718 let signer = super::super::EthereumSigner::generate().unwrap();
719 let signed = deploy_contract(
720 &signer,
721 &[0x60, 0x00],
722 &[],
723 1,
724 0,
725 2_000_000_000,
726 100_000_000_000,
727 1_000_000,
728 )
729 .unwrap();
730 assert_eq!(signed.raw_tx()[0], 0x02); }
732
733 #[test]
736 fn test_contract_call_calldata() {
737 let call = ContractCall::new([0xAA; 20], "transfer(address,uint256)")
738 .args(&[AbiValue::Address([0xBB; 20]), AbiValue::from_u64(1000)]);
739 let cd = call.calldata();
740 assert_eq!(&cd[..4], &hex::decode("a9059cbb").unwrap());
741 }
742
743 #[test]
744 fn test_contract_call_sign() {
745 let signer = super::super::EthereumSigner::generate().unwrap();
746 let call = ContractCall::new([0xAA; 20], "transfer(address,uint256)")
747 .args(&[AbiValue::Address([0xBB; 20]), AbiValue::from_u64(1000)])
748 .value(0);
749 let signed = call
750 .sign(&signer, 1, 0, 2_000_000_000, 100_000_000_000, 100_000)
751 .unwrap();
752 assert_eq!(signed.raw_tx()[0], 0x02);
753 }
754
755 #[test]
758 fn test_encode_fixed_bytes() {
759 let val = AbiValue::FixedBytes(vec![0xAA, 0xBB, 0xCC, 0xDD]);
760 let encoded = encode(&[val]);
761 assert_eq!(encoded.len(), 32);
762 assert_eq!(&encoded[..4], &[0xAA, 0xBB, 0xCC, 0xDD]);
763 assert!(encoded[4..].iter().all(|b| *b == 0)); }
765
766 #[test]
769 fn test_encode_array() {
770 let arr = AbiValue::Array(vec![
771 AbiValue::from_u64(1),
772 AbiValue::from_u64(2),
773 AbiValue::from_u64(3),
774 ]);
775 let encoded = encode(&[arr]);
776 assert_eq!(encoded.len(), 32 + 32 + 3 * 32); }
780}