alloy_dyn_abi/dynamic/
call.rs1use crate::{DynSolType, DynSolValue, Error, Result};
2use alloy_primitives::Selector;
3use alloy_sol_types::abi::Decoder;
4
5#[cfg(not(feature = "std"))]
6use alloc::{string::String, vec::Vec};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct DynSolCall {
11 selector: Selector,
13 parameters: Vec<DynSolType>,
15 method: Option<String>,
17 returns: DynSolReturns,
19}
20
21impl DynSolCall {
22 pub const fn new(
24 selector: Selector,
25 parameters: Vec<DynSolType>,
26 method: Option<String>,
27 returns: DynSolReturns,
28 ) -> Self {
29 Self { selector, parameters, method, returns }
30 }
31
32 pub const fn selector(&self) -> Selector {
34 self.selector
35 }
36
37 pub fn types(&self) -> &[DynSolType] {
39 &self.parameters
40 }
41
42 pub fn method(&self) -> Option<&str> {
44 self.method.as_deref()
45 }
46
47 pub const fn returns(&self) -> &DynSolReturns {
49 &self.returns
50 }
51
52 pub fn abi_encode_input(&self, values: &[DynSolValue]) -> Result<Vec<u8>> {
54 encode_typeck(&self.parameters, values).map(prefix_selector(self.selector))
55 }
56
57 pub fn abi_encode_input_raw(&self, values: &[DynSolValue]) -> Result<Vec<u8>> {
60 encode_typeck(&self.parameters, values)
61 }
62
63 pub fn abi_decode_input(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>> {
65 abi_decode(data, &self.parameters, validate)
66 }
67
68 pub fn abi_encode_output(&self, values: &[DynSolValue]) -> Result<Vec<u8>> {
70 self.returns.abi_encode_output(values)
71 }
72
73 pub fn abi_decode_output(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>> {
75 self.returns.abi_decode_output(data, validate)
76 }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct DynSolReturns(Vec<DynSolType>);
82
83impl From<Vec<DynSolType>> for DynSolReturns {
84 fn from(types: Vec<DynSolType>) -> Self {
85 Self(types)
86 }
87}
88
89impl From<DynSolReturns> for Vec<DynSolType> {
90 fn from(returns: DynSolReturns) -> Self {
91 returns.0
92 }
93}
94
95impl DynSolReturns {
96 pub const fn new(types: Vec<DynSolType>) -> Self {
98 Self(types)
99 }
100
101 pub fn types(&self) -> &[DynSolType] {
103 &self.0
104 }
105
106 pub fn abi_encode_output(&self, values: &[DynSolValue]) -> Result<Vec<u8>> {
108 encode_typeck(self.types(), values)
109 }
110
111 pub fn abi_decode_output(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>> {
113 abi_decode(data, self.types(), validate)
114 }
115}
116
117#[inline]
118pub(crate) fn prefix_selector(selector: Selector) -> impl FnOnce(Vec<u8>) -> Vec<u8> {
119 move |data| {
120 let mut new = Vec::with_capacity(data.len() + 4);
121 new.extend_from_slice(&selector[..]);
122 new.extend_from_slice(&data[..]);
123 new
124 }
125}
126
127pub(crate) fn encode_typeck(tys: &[DynSolType], values: &[DynSolValue]) -> Result<Vec<u8>> {
128 if values.len() != tys.len() {
129 return Err(Error::EncodeLengthMismatch { expected: tys.len(), actual: values.len() });
130 }
131
132 for (value, ty) in core::iter::zip(values, tys) {
133 if !ty.matches(value) {
134 return Err(Error::TypeMismatch {
135 expected: ty.sol_type_name().into_owned(),
136 actual: value.sol_type_name().unwrap_or_else(|| "<none>".into()).into_owned(),
137 });
138 }
139 }
140
141 Ok(abi_encode(values))
142}
143
144#[inline]
145pub(crate) fn abi_encode(values: &[DynSolValue]) -> Vec<u8> {
146 DynSolValue::encode_seq(values)
147}
148
149pub(crate) fn abi_decode(
150 data: &[u8],
151 tys: &[DynSolType],
152 validate: bool,
153) -> Result<Vec<DynSolValue>> {
154 let mut values = Vec::with_capacity(tys.len());
155 let mut decoder = Decoder::new(data, validate);
156 for ty in tys {
157 let value = ty.abi_decode_inner(&mut decoder, crate::DynToken::decode_single_populate)?;
158 values.push(value);
159 }
160 Ok(values)
161}