tycho_types/abi/
contract.rs

1use std::borrow::Cow;
2use std::collections::HashSet;
3use std::str::FromStr;
4use std::sync::Arc;
5
6use ahash::HashMap;
7use anyhow::Result;
8use serde::Deserialize;
9use sha2::Digest;
10
11use super::error::AbiError;
12use super::{AbiHeaderType, AbiType, AbiValue, AbiVersion, NamedAbiType, NamedAbiValue};
13use crate::abi::AbiHeader;
14use crate::abi::value::ser::AbiSerializer;
15use crate::cell::{
16    Cell, CellBuilder, CellDataBuilder, CellFamily, CellSlice, DynCell, HashBytes, Size, Store,
17};
18use crate::dict::RawDict;
19use crate::models::{
20    ExtInMsgInfo, IntAddr, MsgInfo, OwnedMessage, OwnedRelaxedMessage, RelaxedIntMsgInfo,
21    RelaxedMsgInfo, StateInit, StdAddr,
22};
23use crate::num::Tokens;
24use crate::prelude::Dict;
25
26const PUBKEY_FIELD: &str = "_pubkey";
27
28/// Contract ABI definition.
29pub struct Contract {
30    /// ABI version.
31    pub abi_version: AbiVersion,
32
33    /// List of headers for external messages.
34    ///
35    /// NOTE: header order matters.
36    pub headers: Arc<[AbiHeaderType]>,
37
38    /// A mapping with all contract methods by name.
39    pub functions: HashMap<Arc<str>, Function>,
40
41    /// A mapping with all contract events by name.
42    pub events: HashMap<Arc<str>, Event>,
43
44    /// Contract init data.
45    pub init_data: ContractInitData,
46
47    /// Contract storage fields.
48    pub fields: Arc<[NamedAbiType]>,
49
50    /// A mapping with all contract getters by name. Supported for ABI 2.7 and later
51    pub getters: HashMap<Arc<str>, Getter>,
52}
53
54pub enum ContractInitData {
55    Dict(HashMap<Arc<str>, (u64, NamedAbiType)>),
56    PlainFields(HashSet<Arc<str>>),
57}
58
59impl Contract {
60    /// Finds a method declaration with the specfied id.
61    pub fn find_function_by_id(&self, id: u32, input: bool) -> Option<&Function> {
62        self.functions
63            .values()
64            .find(|item| input && item.input_id == id || !input && item.output_id == id)
65    }
66
67    /// Finds an event with the specified id.
68    pub fn find_event_by_id(&self, id: u32) -> Option<&Event> {
69        self.events.values().find(|event| event.id == id)
70    }
71
72    /// Returns a new init data with replaced items.
73    ///
74    /// NOTE: `tokens` can be a subset of init data fields, all other
75    /// will not be touched.
76    pub fn update_init_data(
77        &self,
78        pubkey: Option<&ed25519_dalek::VerifyingKey>,
79        tokens: &[NamedAbiValue],
80        data: &Cell,
81    ) -> Result<Cell> {
82        if self.abi_version < AbiVersion::V2_4 {
83            self.update_init_data_dict(pubkey, tokens, data)
84        } else {
85            self.update_init_data_plain(pubkey, tokens, data)
86        }
87    }
88
89    fn update_init_data_dict(
90        &self,
91        pubkey: Option<&ed25519_dalek::VerifyingKey>,
92        tokens: &[NamedAbiValue],
93        data: &Cell,
94    ) -> Result<Cell> {
95        // Always check if data is valid
96        let mut result = data.parse::<RawDict<64>>()?;
97
98        if pubkey.is_none() && tokens.is_empty() {
99            // Do nothing if no items are updated
100            return Ok(data.clone());
101        }
102
103        let ContractInitData::Dict(init_data) = &self.init_data else {
104            anyhow::bail!("Plain init_data is not supported for ABI version < 2.4")
105        };
106
107        let context = Cell::empty_context();
108        let mut key_builder = CellDataBuilder::new();
109
110        for token in tokens {
111            let Some((key, ty)) = init_data.get(token.name.as_ref()) else {
112                anyhow::bail!(AbiError::UnexpectedInitDataParam(token.name.clone()));
113            };
114            token.check_type(ty)?;
115
116            key_builder.store_u64(*key)?;
117
118            result.set_ext(
119                key_builder.as_data_slice(),
120                &token.make_builder(self.abi_version)?.as_full_slice(),
121                context,
122            )?;
123
124            key_builder.clear_bits();
125        }
126
127        // Set public key if specified
128        if let Some(pubkey) = pubkey {
129            key_builder.store_u64(0)?;
130            result.set_ext(
131                key_builder.as_data_slice(),
132                &CellBuilder::from_raw_data(pubkey.as_bytes(), 256)?.as_data_slice(),
133                context,
134            )?;
135        }
136
137        // Encode init data as mapping
138        CellBuilder::build_from_ext(result, context).map_err(From::from)
139    }
140
141    fn update_init_data_plain(
142        &self,
143        mut pubkey: Option<&ed25519_dalek::VerifyingKey>,
144        tokens: &[NamedAbiValue],
145        data: &Cell,
146    ) -> Result<Cell> {
147        let ContractInitData::PlainFields(init_data) = &self.init_data else {
148            anyhow::bail!("Dict init_data is not supported for ABI version >= 2.4")
149        };
150
151        let mut data_slice = data.as_slice()?;
152
153        let mut init_values = Vec::with_capacity(self.fields.len());
154
155        let mut tokens_map = HashMap::with_capacity_and_hasher(tokens.len(), Default::default());
156        for i in tokens {
157            tokens_map.insert(i.name.as_ref(), i.value.clone());
158        }
159
160        for i in self.fields.as_ref() {
161            let old_value = AbiValue::load_partial(&i.ty, self.abi_version, &mut data_slice)?;
162
163            let mut token = tokens_map.remove(i.name.as_ref());
164
165            if i.name.as_ref() == PUBKEY_FIELD
166                && let Some(pubkey) = pubkey.take()
167            {
168                // Overwrite pubkey if specified.
169                token = Some(AbiValue::Uint(
170                    256,
171                    HashBytes::wrap(pubkey.as_bytes()).as_biguint(),
172                ));
173            }
174
175            init_values.push(if let Some(token) = token {
176                anyhow::ensure!(
177                    init_data.contains(i.name.as_ref()),
178                    AbiError::UnexpectedInitDataParam(i.name.clone())
179                );
180                token
181            } else {
182                old_value
183            });
184        }
185
186        anyhow::ensure!(pubkey.is_none(), AbiError::PubkeyNotUsed);
187
188        let cell = AbiValue::tuple_to_cell(init_values.as_ref(), self.abi_version)?;
189        Ok(cell)
190    }
191
192    /// Encodes an account data with the specified initial parameters.
193    ///
194    /// NOTE: `tokens` can be a subset of init data fields, all other
195    /// will be set to default.
196    pub fn encode_init_data(
197        &self,
198        pubkey: Option<&ed25519_dalek::VerifyingKey>,
199        tokens: &[NamedAbiValue],
200    ) -> Result<Cell> {
201        if self.abi_version < AbiVersion::V2_4 {
202            self.encode_init_data_dict(pubkey, tokens)
203        } else {
204            self.encode_init_data_plain(pubkey, tokens)
205        }
206    }
207
208    fn encode_init_data_dict(
209        &self,
210        pubkey: Option<&ed25519_dalek::VerifyingKey>,
211        tokens: &[NamedAbiValue],
212    ) -> Result<Cell> {
213        let ContractInitData::Dict(init_data) = &self.init_data else {
214            anyhow::bail!("Plain init fields are not supported")
215        };
216
217        let mut result = RawDict::<64>::new();
218
219        let mut init_data = init_data
220            .iter()
221            .map(|(name, value)| (name.as_ref(), value))
222            .collect::<HashMap<_, _>>();
223
224        let context = Cell::empty_context();
225        let mut key_builder = CellDataBuilder::new();
226
227        // Write explicitly provided values
228        for token in tokens {
229            let Some((key, ty)) = init_data.remove(token.name.as_ref()) else {
230                anyhow::bail!(AbiError::UnexpectedInitDataParam(token.name.clone()));
231            };
232            token.check_type(ty)?;
233
234            key_builder.store_u64(*key)?;
235
236            result.set_ext(
237                key_builder.as_data_slice(),
238                &token.make_builder(self.abi_version)?.as_full_slice(),
239                context,
240            )?;
241
242            key_builder.clear_bits();
243        }
244
245        // Write remaining values with default values
246        for (key, ty) in init_data.into_values() {
247            key_builder.store_u64(*key)?;
248
249            result.set_ext(
250                key_builder.as_data_slice(),
251                &ty.make_default_value()
252                    .make_builder(self.abi_version)?
253                    .as_full_slice(),
254                context,
255            )?;
256
257            key_builder.clear_bits();
258        }
259
260        // Set public key
261        key_builder.store_u64(0)?;
262        result.set_ext(
263            key_builder.as_data_slice(),
264            &CellBuilder::from_raw_data(
265                pubkey.map(|value| value.as_bytes()).unwrap_or(&[0; 32]),
266                256,
267            )?
268            .as_data_slice(),
269            context,
270        )?;
271
272        // Encode init data as mapping
273        CellBuilder::build_from_ext(result, context).map_err(From::from)
274    }
275
276    fn encode_init_data_plain(
277        &self,
278        mut pubkey: Option<&ed25519_dalek::VerifyingKey>,
279        tokens: &[NamedAbiValue],
280    ) -> Result<Cell> {
281        let ContractInitData::PlainFields(init_data) = &self.init_data else {
282            anyhow::bail!("Dict init_data is not supported for ABI version >= 2.4")
283        };
284
285        let mut init_values = Vec::with_capacity(self.fields.len());
286
287        let mut tokens_map = HashMap::with_capacity_and_hasher(tokens.len(), Default::default());
288        for i in tokens {
289            tokens_map.insert(i.name.as_ref(), i.value.clone());
290        }
291
292        for i in self.fields.as_ref() {
293            let mut token = tokens_map.remove(i.name.as_ref());
294
295            if i.name.as_ref() == PUBKEY_FIELD
296                && let Some(pubkey) = pubkey.take()
297            {
298                // Overwrite pubkey if specified.
299                token = Some(AbiValue::Uint(
300                    256,
301                    HashBytes::wrap(pubkey.as_bytes()).as_biguint(),
302                ));
303            }
304
305            init_values.push(if init_data.contains(i.name.as_ref()) {
306                token.ok_or_else(|| AbiError::InitDataFieldNotFound(i.name.clone()))?
307            } else {
308                anyhow::ensure!(
309                    token.is_none(),
310                    AbiError::UnexpectedInitDataParam(i.name.clone())
311                );
312                i.ty.make_default_value()
313            });
314        }
315
316        anyhow::ensure!(pubkey.is_none(), AbiError::PubkeyNotUsed);
317
318        let cell = AbiValue::tuple_to_cell(init_values.as_ref(), self.abi_version)?;
319        Ok(cell)
320    }
321
322    /// Tries to parse init data fields of this contract from an account data.
323    pub fn decode_init_data(&self, data: &DynCell) -> Result<Vec<NamedAbiValue>> {
324        if self.abi_version < AbiVersion::V2_4 {
325            self.decode_init_data_internal(data)
326        } else {
327            self.decode_init_fields(data)
328        }
329    }
330
331    fn decode_init_data_internal(&self, data: &DynCell) -> Result<Vec<NamedAbiValue>> {
332        let init_data = data.parse::<Dict<u64, CellSlice>>()?;
333
334        let ContractInitData::Dict(init_data_map) = &self.init_data else {
335            anyhow::bail!("Plain init fields are not supported")
336        };
337        let mut result = Vec::with_capacity(init_data_map.len());
338
339        for (key, item) in init_data_map.values() {
340            let Some(mut value) = init_data.get(key)? else {
341                anyhow::bail!(AbiError::InitDataFieldNotFound(item.name.clone()));
342            };
343            result.push(NamedAbiValue::load(item, self.abi_version, &mut value)?);
344        }
345
346        Ok(result)
347    }
348
349    fn decode_init_fields(&self, data: &DynCell) -> Result<Vec<NamedAbiValue>> {
350        let ContractInitData::PlainFields(init_fields) = &self.init_data else {
351            anyhow::bail!("Plain init fields are not supported")
352        };
353
354        let values = self.decode_fields(data.as_slice()?)?;
355
356        let mut init_values = Vec::with_capacity(init_fields.len());
357
358        for i in values {
359            if init_fields.contains(i.name.as_ref()) {
360                init_values.push(i)
361            }
362        }
363
364        Ok(init_values)
365    }
366
367    /// Encodes an account data with the specified storage fields of this contract.
368    pub fn encode_fields(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
369        ok!(NamedAbiValue::check_types(tokens, &self.fields));
370        NamedAbiValue::tuple_to_builder(tokens, self.abi_version).map_err(From::from)
371    }
372
373    /// Tries to parse storage fields of this contract from an account data.
374    ///
375    /// NOTE: The slice is required to contain nothing other than these fields.
376    pub fn decode_fields(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
377        self.decode_fields_ext(&mut slice, false)
378    }
379
380    /// Tries to parse storage fields of this contract from an account data.
381    pub fn decode_fields_ext(
382        &self,
383        slice: &mut CellSlice<'_>,
384        allow_partial: bool,
385    ) -> Result<Vec<NamedAbiValue>> {
386        let res = ok!(NamedAbiValue::load_tuple_ext(
387            &self.fields,
388            self.abi_version,
389            true,
390            allow_partial,
391            slice
392        ));
393        ok!(AbiValue::check_remaining(slice, allow_partial));
394        Ok(res)
395    }
396}
397
398impl<'de> Deserialize<'de> for Contract {
399    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
400    where
401        D: serde::Deserializer<'de>,
402    {
403        use serde::de::Error;
404
405        #[repr(transparent)]
406        struct Id(u32);
407
408        impl<'de> Deserialize<'de> for Id {
409            fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
410            where
411                D: serde::Deserializer<'de>,
412            {
413                #[derive(Deserialize)]
414                #[serde(transparent)]
415                struct Id<'a>(#[serde(borrow)] Cow<'a, str>);
416
417                match ok!(Id::deserialize(deserializer)).0.strip_prefix("0x") {
418                    Some(s) => u32::from_str_radix(s, 16).map(Self).map_err(Error::custom),
419                    None => Err(Error::custom("Hex number must be prefixed with 0x")),
420                }
421            }
422        }
423
424        #[derive(Deserialize)]
425        struct SerdeNamedAbiType {
426            #[serde(flatten)]
427            named_abi_type: NamedAbiType,
428            #[serde(default)]
429            init: bool,
430        }
431
432        #[derive(Deserialize)]
433        struct SerdeContract {
434            #[serde(default, rename = "ABI version")]
435            abi_version: Option<u8>,
436            #[serde(default)]
437            version: Option<String>,
438            #[serde(default)]
439            header: Vec<AbiHeaderType>,
440            functions: Vec<SerdeFunction>,
441            #[serde(default)]
442            events: Vec<SerdeEvent>,
443            #[serde(default)]
444            data: Vec<InitData>,
445            #[serde(default)]
446            fields: Vec<SerdeNamedAbiType>,
447            #[serde(default)]
448            getters: Vec<SerdeFunction>,
449        }
450
451        #[derive(Deserialize)]
452        struct SerdeFunction {
453            name: String,
454            #[serde(default)]
455            inputs: Vec<NamedAbiType>,
456            #[serde(default)]
457            outputs: Vec<NamedAbiType>,
458            #[serde(default)]
459            id: Option<Id>,
460        }
461
462        #[derive(Deserialize)]
463        struct SerdeEvent {
464            name: String,
465            #[serde(default)]
466            inputs: Vec<NamedAbiType>,
467            #[serde(default)]
468            id: Option<Id>,
469        }
470
471        #[derive(Deserialize)]
472        struct InitData {
473            key: u64,
474            #[serde(flatten)]
475            ty: NamedAbiType,
476        }
477
478        let contract = ok!(SerdeContract::deserialize(deserializer));
479        let abi_version = if let Some(version) = &contract.version {
480            ok!(AbiVersion::from_str(version).map_err(Error::custom))
481        } else if let Some(major) = contract.abi_version {
482            AbiVersion::new(major, 0)
483        } else {
484            return Err(Error::custom("No ABI version found"));
485        };
486
487        let headers = Arc::<[AbiHeaderType]>::from(contract.header);
488
489        let functions = contract
490            .functions
491            .into_iter()
492            .map(|item| {
493                let (input_id, output_id) = match item.id {
494                    Some(Id(id)) => (id, id),
495                    None => {
496                        let id = Function::compute_function_id(
497                            abi_version,
498                            &item.name,
499                            headers.as_ref(),
500                            &item.inputs,
501                            &item.outputs,
502                        );
503                        (id & Function::INPUT_ID_MASK, id | !Function::INPUT_ID_MASK)
504                    }
505                };
506                let name = Arc::<str>::from(item.name);
507                (name.clone(), Function {
508                    abi_version,
509                    name,
510                    headers: headers.clone(),
511                    inputs: Arc::from(item.inputs),
512                    outputs: Arc::from(item.outputs),
513                    input_id,
514                    output_id,
515                })
516            })
517            .collect();
518
519        let getters = contract
520            .getters
521            .into_iter()
522            .map(|item| {
523                let id = match item.id {
524                    Some(Id(id)) => id,
525                    None => Getter::compute_getter_id::<&str>(item.name.as_ref()),
526                };
527                let name = Arc::<str>::from(item.name);
528                (name.clone(), Getter {
529                    name,
530                    outputs: Arc::from(item.outputs),
531                    id,
532                })
533            })
534            .collect();
535
536        let events = contract
537            .events
538            .into_iter()
539            .map(|item| {
540                let id = match item.id {
541                    Some(Id(id)) => id,
542                    None => {
543                        let id = Event::compute_event_id(abi_version, &item.name, &item.inputs);
544                        id & Function::INPUT_ID_MASK
545                    }
546                };
547                let name = Arc::<str>::from(item.name);
548                (name.clone(), Event {
549                    abi_version,
550                    name,
551                    inputs: Arc::from(item.inputs),
552                    id,
553                })
554            })
555            .collect();
556
557        let init_data = if abi_version >= AbiVersion::V2_4 {
558            let init_fields = contract
559                .fields
560                .iter()
561                .filter(|x| x.init)
562                .map(|x| x.named_abi_type.name.clone())
563                .collect();
564            ContractInitData::PlainFields(init_fields)
565        } else {
566            let data = contract
567                .data
568                .into_iter()
569                .map(|item| {
570                    let name = item.ty.name.clone();
571                    (name, (item.key, item.ty))
572                })
573                .collect();
574
575            ContractInitData::Dict(data)
576        };
577
578        Ok(Self {
579            abi_version,
580            headers,
581            functions,
582            events,
583            init_data,
584            fields: Arc::from(
585                contract
586                    .fields
587                    .into_iter()
588                    .map(|x| x.named_abi_type)
589                    .collect::<Vec<_>>(),
590            ),
591            getters,
592        })
593    }
594}
595
596/// Helper trait to convert various types to u32 getter id
597pub trait AsGetterMethodId {
598    fn as_getter_method_id(&self) -> u32;
599}
600
601impl<T: AsGetterMethodId + ?Sized> AsGetterMethodId for &T {
602    fn as_getter_method_id(&self) -> u32 {
603        T::as_getter_method_id(*self)
604    }
605}
606
607impl<T: AsGetterMethodId + ?Sized> AsGetterMethodId for &mut T {
608    fn as_getter_method_id(&self) -> u32 {
609        T::as_getter_method_id(*self)
610    }
611}
612
613impl AsGetterMethodId for u32 {
614    fn as_getter_method_id(&self) -> u32 {
615        *self
616    }
617}
618
619impl AsGetterMethodId for str {
620    fn as_getter_method_id(&self) -> u32 {
621        let crc = crate::crc::crc_16(self.as_bytes());
622        crc as u32 | 0x10000
623    }
624}
625
626#[derive(Debug, Clone)]
627pub struct Getter {
628    /// Getter name.
629    pub name: Arc<str>,
630    /// Getter output types
631    pub outputs: Arc<[NamedAbiType]>,
632    /// Getter id
633    pub id: u32,
634}
635
636impl Getter {
637    pub fn compute_getter_id<T: AsGetterMethodId>(input: T) -> u32 {
638        input.as_getter_method_id()
639    }
640}
641
642/// Contract method ABI definition.
643#[derive(Debug, Clone)]
644pub struct Function {
645    /// ABI version (same as contract ABI version).
646    pub abi_version: AbiVersion,
647    /// List of headers for external messages.
648    /// Must be the same as in contract.
649    ///
650    /// NOTE: header order matters.
651    pub headers: Arc<[AbiHeaderType]>,
652    /// Method name.
653    pub name: Arc<str>,
654    /// Method input argument types.
655    pub inputs: Arc<[NamedAbiType]>,
656    /// Method output types.
657    pub outputs: Arc<[NamedAbiType]>,
658    /// Function id in incoming messages (with input).
659    pub input_id: u32,
660    /// Function id in outgoing messages (with output).
661    pub output_id: u32,
662}
663
664impl Function {
665    /// Mask with a bit difference of input id and output id.
666    pub const INPUT_ID_MASK: u32 = 0x7fffffff;
667
668    /// Computes function id from the full function signature.
669    pub fn compute_function_id(
670        abi_version: AbiVersion,
671        name: &str,
672        headers: &[AbiHeaderType],
673        inputs: &[NamedAbiType],
674        outputs: &[NamedAbiType],
675    ) -> u32 {
676        let mut hasher = sha2::Sha256::new();
677        FunctionSignatureRaw {
678            abi_version,
679            name,
680            headers,
681            inputs,
682            outputs,
683        }
684        .update_hasher(&mut hasher);
685
686        let hash: [u8; 32] = hasher.finalize().into();
687        u32::from_be_bytes(hash[0..4].try_into().unwrap())
688    }
689
690    /// Encodes message body without headers.
691    pub fn encode_internal_msg_body(
692        version: AbiVersion,
693        id: u32,
694        tokens: &[NamedAbiValue],
695    ) -> Result<CellBuilder> {
696        let mut serializer = AbiSerializer::new(version);
697        let output_id = AbiValue::uint(32, id);
698
699        serializer.reserve_value(&output_id);
700        for token in tokens {
701            serializer.reserve_value(&token.value);
702        }
703
704        let context = Cell::empty_context();
705        serializer.write_value(&output_id, version, context)?;
706        serializer.write_tuple(tokens, version, context)?;
707        serializer.finalize(context).map_err(From::from)
708    }
709
710    /// Returns a method builder with the specified ABI version and name.
711    #[inline]
712    pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> FunctionBuilder {
713        FunctionBuilder::new(abi_version, name)
714    }
715
716    /// Encodes an unsigned body with invocation of this method as an external message.
717    pub fn encode_external<'f, 'a: 'f>(
718        &'f self,
719        tokens: &'a [NamedAbiValue],
720    ) -> ExternalInput<'f, 'a> {
721        ExternalInput {
722            function: self,
723            tokens,
724            time: None,
725            expire_at: None,
726            pubkey: None,
727            address: None,
728        }
729    }
730
731    /// Tries to parse input arguments for this method from an external message body.
732    ///
733    /// NOTE: The slice is required to contain nothing other than these arguments.
734    pub fn decode_external_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
735        self.decode_external_input_ext(&mut slice, false)
736    }
737
738    /// Tries to parse input arguments for this method from an external message body.
739    pub fn decode_external_input_ext(
740        &self,
741        slice: &mut CellSlice<'_>,
742        allow_partial: bool,
743    ) -> Result<Vec<NamedAbiValue>> {
744        // Read prefix
745        let id = if self.abi_version.major == 1 {
746            // Load input id
747            let id = slice.load_u32()?;
748            // Skip signature
749            slice.load_reference()?;
750            // Skip headers
751            ok!(AbiHeader::skip_all(&self.headers, slice));
752
753            id
754        } else {
755            // Skip signature
756            if slice.load_bit()? {
757                slice.skip_first(512, 0)?;
758            }
759            // Skip headers
760            ok!(AbiHeader::skip_all(&self.headers, slice));
761            // Load input id
762            slice.load_u32()?
763        };
764
765        // Check input id
766        anyhow::ensure!(id == self.input_id, AbiError::InputIdMismatch {
767            expected: self.input_id,
768            id
769        });
770
771        let res = ok!(NamedAbiValue::load_tuple_ext(
772            &self.inputs,
773            self.abi_version,
774            true,
775            allow_partial,
776            slice
777        ));
778        ok!(AbiValue::check_remaining(slice, allow_partial));
779        Ok(res)
780    }
781
782    /// Encodes a message body with invocation of this method as an internal message.
783    pub fn encode_internal_input(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
784        ok!(NamedAbiValue::check_types(tokens, &self.inputs));
785        Self::encode_internal_msg_body(self.abi_version, self.input_id, tokens)
786    }
787
788    /// Encodes an internal message with invocation of this method.
789    pub fn encode_internal_message(
790        &self,
791        tokens: &[NamedAbiValue],
792        dst: IntAddr,
793        value: Tokens,
794        bounce: bool,
795        state_init: Option<&StateInit>,
796    ) -> Result<Box<OwnedRelaxedMessage>> {
797        let body = self.encode_internal_input(tokens)?;
798        let body = body.build()?;
799
800        Ok(Box::new(OwnedRelaxedMessage {
801            info: RelaxedMsgInfo::Int(RelaxedIntMsgInfo {
802                dst,
803                bounce,
804                value: value.into(),
805                ..Default::default()
806            }),
807            body: body.into(),
808            init: state_init.cloned(),
809            layout: None,
810        }))
811    }
812
813    /// Tries to parse input arguments for this method from an internal message body.
814    ///
815    /// NOTE: The slice is required to contain nothing other than these arguments.
816    pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
817        self.decode_internal_input_ext(&mut slice, false)
818    }
819
820    /// Tries to parse input arguments for this method from an internal message body.
821    pub fn decode_internal_input_ext(
822        &self,
823        slice: &mut CellSlice<'_>,
824        allow_partial: bool,
825    ) -> Result<Vec<NamedAbiValue>> {
826        let id = slice.load_u32()?;
827        anyhow::ensure!(id == self.input_id, AbiError::InputIdMismatch {
828            expected: self.input_id,
829            id
830        });
831        let res = ok!(NamedAbiValue::load_tuple_ext(
832            &self.inputs,
833            self.abi_version,
834            true,
835            allow_partial,
836            slice
837        ));
838        ok!(AbiValue::check_remaining(slice, allow_partial));
839        Ok(res)
840    }
841
842    /// Encodes a message body with result of invocation of this method.
843    pub fn encode_output(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
844        ok!(NamedAbiValue::check_types(tokens, &self.outputs));
845        Self::encode_internal_msg_body(self.abi_version, self.output_id, tokens)
846    }
847
848    /// Tries to parse output arguments of this method from a message body.
849    ///
850    /// NOTE: The slice is required to contain nothing other than these arguments.
851    pub fn decode_output(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
852        self.decode_output_ext(&mut slice, false)
853    }
854
855    /// Tries to parse output arguments of this method from a message body.
856    pub fn decode_output_ext(
857        &self,
858        slice: &mut CellSlice<'_>,
859        allow_partial: bool,
860    ) -> Result<Vec<NamedAbiValue>> {
861        let id = slice.load_u32()?;
862        anyhow::ensure!(id == self.output_id, AbiError::OutputIdMismatch {
863            expected: self.output_id,
864            id
865        });
866        let res = ok!(NamedAbiValue::load_tuple_ext(
867            &self.outputs,
868            self.abi_version,
869            true,
870            allow_partial,
871            slice
872        ));
873        ok!(AbiValue::check_remaining(slice, allow_partial));
874        Ok(res)
875    }
876
877    /// Returns an object which can be used to display the normalized signature of this method.
878    pub fn display_signature(&self) -> impl std::fmt::Display + '_ {
879        FunctionSignatureRaw {
880            abi_version: self.abi_version,
881            name: &self.name,
882            headers: &self.headers,
883            inputs: &self.inputs,
884            outputs: &self.outputs,
885        }
886    }
887}
888
889/// External input builder.
890#[derive(Clone)]
891pub struct ExternalInput<'f, 'a> {
892    function: &'f Function,
893    tokens: &'a [NamedAbiValue],
894    time: Option<u64>,
895    expire_at: Option<u32>,
896    pubkey: Option<&'a ed25519_dalek::VerifyingKey>,
897    address: Option<&'a StdAddr>,
898}
899
900impl<'a> ExternalInput<'_, 'a> {
901    /// Builds an external message to the specified address.
902    pub fn build_message(&self, address: &StdAddr) -> Result<UnsignedExternalMessage> {
903        Ok(ok!(self.build_input_ext(Some(address))).with_dst(address.clone()))
904    }
905
906    /// Builds an exteranl message to the specified address without signature.
907    ///
908    /// Returns an expiration timestamp along with message.
909    pub fn build_message_without_signature(
910        &self,
911        address: &StdAddr,
912    ) -> Result<(u32, OwnedMessage)> {
913        let (expire_at, body) = ok!(self.build_input_without_signature());
914        Ok((expire_at, OwnedMessage {
915            info: MsgInfo::ExtIn(ExtInMsgInfo {
916                dst: IntAddr::Std(address.clone()),
917                ..Default::default()
918            }),
919            body: body.into(),
920            init: None,
921            layout: None,
922        }))
923    }
924
925    /// Builds an external message body.
926    pub fn build_input(&self) -> Result<UnsignedBody> {
927        self.build_input_ext(self.address)
928    }
929
930    fn build_input_ext(&self, address: Option<&StdAddr>) -> Result<UnsignedBody> {
931        let (expire_at, payload) = self.build_payload(true)?;
932
933        let context = Cell::empty_context();
934        let hash = if self.function.abi_version >= AbiVersion::V2_3 {
935            let mut to_sign = CellBuilder::new();
936            match address {
937                Some(address) => address.store_into(&mut to_sign, context)?,
938                None => anyhow::bail!(AbiError::AddressNotProvided),
939            };
940            to_sign.store_slice(payload.as_slice()?)?;
941            *to_sign.build_ext(context)?.repr_hash()
942        } else {
943            *payload.repr_hash()
944        };
945
946        Ok(UnsignedBody {
947            abi_version: self.function.abi_version,
948            expire_at,
949            payload,
950            hash,
951        })
952    }
953
954    /// Builds an external message body without signature.
955    pub fn build_input_without_signature(&self) -> Result<(u32, Cell)> {
956        self.build_payload(false)
957    }
958
959    fn build_payload(&self, reserve_signature: bool) -> Result<(u32, Cell)> {
960        const DEFAULT_TIMEOUT_SEC: u32 = 60;
961
962        fn now_ms() -> u64 {
963            std::time::SystemTime::now()
964                .duration_since(std::time::SystemTime::UNIX_EPOCH)
965                .unwrap()
966                .as_millis() as u64
967        }
968
969        ok!(NamedAbiValue::check_types(
970            self.tokens,
971            &self.function.inputs
972        ));
973
974        let abi_version = self.function.abi_version;
975
976        let mut serializer = AbiSerializer::new(abi_version);
977
978        serializer.add_offset(if abi_version.major == 1 {
979            // Reserve reference for signature
980            Size { bits: 0, refs: 1 }
981        } else {
982            let bits = if abi_version >= AbiVersion::V2_3 {
983                // Reserve only for address as it also ensures the the signature will fit
984                IntAddr::BITS_MAX
985            } else {
986                // Reserve for `Some` non-empty signature
987                1 + 512
988            };
989            Size { bits, refs: 0 }
990        });
991
992        let input_id = AbiValue::uint(32, self.function.input_id);
993
994        serializer.reserve_headers(&self.function.headers, self.pubkey.is_some());
995        serializer.reserve_value(&input_id);
996        for token in self.tokens {
997            serializer.reserve_value(&token.value);
998        }
999
1000        let context = Cell::empty_context();
1001
1002        if !reserve_signature {
1003            let value = if abi_version.major == 1 {
1004                AbiValue::Cell(Cell::default())
1005            } else {
1006                AbiValue::Bool(false)
1007            };
1008            serializer.reserve_value(&value);
1009            serializer.write_value(&value, abi_version, context)?;
1010        }
1011
1012        let time = self.time.unwrap_or_else(now_ms);
1013        let expire_at = self
1014            .expire_at
1015            .unwrap_or((time / 1000) as u32 + DEFAULT_TIMEOUT_SEC);
1016
1017        for header in self.function.headers.as_ref() {
1018            serializer.write_header_value(&match header {
1019                AbiHeaderType::Time => AbiHeader::Time(time),
1020                AbiHeaderType::Expire => AbiHeader::Expire(expire_at),
1021                AbiHeaderType::PublicKey => {
1022                    AbiHeader::PublicKey(self.pubkey.map(|key| Box::new(*key)))
1023                }
1024            })?;
1025        }
1026
1027        serializer.write_value(&input_id, abi_version, context)?;
1028        serializer.write_tuple(self.tokens, abi_version, context)?;
1029
1030        let payload = serializer.finalize(context)?.build_ext(context)?;
1031        Ok((expire_at, payload))
1032    }
1033
1034    /// Use the specified time for the `time` header.
1035    #[inline]
1036    pub fn set_time(&mut self, time: u64) {
1037        self.time = Some(time);
1038    }
1039
1040    /// Use the specified time for the `time` header.
1041    #[inline]
1042    pub fn with_time(mut self, time: u64) -> Self {
1043        self.set_time(time);
1044        self
1045    }
1046
1047    /// Use the specified expiration timestamp for the `expire` header.
1048    #[inline]
1049    pub fn set_expire_at(&mut self, expire_at: u32) {
1050        self.expire_at = Some(expire_at);
1051    }
1052
1053    /// Use the specified expiration timestamp for the `expire` header.
1054    #[inline]
1055    pub fn with_expire_at(mut self, expire_at: u32) -> Self {
1056        self.set_expire_at(expire_at);
1057        self
1058    }
1059
1060    /// Use the specified public key for the `pubkey` header.
1061    #[inline]
1062    pub fn set_pubkey(&mut self, pubkey: &'a ed25519_dalek::VerifyingKey) {
1063        self.pubkey = Some(pubkey);
1064    }
1065
1066    /// Use the specified public key for the `pubkey` header.
1067    #[inline]
1068    pub fn with_pubkey(mut self, pubkey: &'a ed25519_dalek::VerifyingKey) -> Self {
1069        self.set_pubkey(pubkey);
1070        self
1071    }
1072
1073    /// Use the specified address for ABIv2.3 signature.
1074    #[inline]
1075    pub fn set_address(&mut self, address: &'a StdAddr) {
1076        self.address = Some(address);
1077    }
1078
1079    /// Use the specified address for ABIv2.3 signature.
1080    #[inline]
1081    pub fn with_address(mut self, address: &'a StdAddr) -> Self {
1082        self.set_address(address);
1083        self
1084    }
1085}
1086
1087/// Method ABI declaration builder.
1088#[derive(Debug, Clone)]
1089pub struct FunctionBuilder {
1090    abi_version: AbiVersion,
1091    name: String,
1092    headers: Vec<AbiHeaderType>,
1093    inputs: Vec<NamedAbiType>,
1094    outputs: Vec<NamedAbiType>,
1095    id: Option<u32>,
1096}
1097
1098impl FunctionBuilder {
1099    /// Creates an empty ABI declaration for a method with the specified ABI version and name.
1100    pub fn new<T: Into<String>>(abi_version: AbiVersion, name: T) -> Self {
1101        Self {
1102            abi_version,
1103            name: name.into(),
1104            headers: Default::default(),
1105            inputs: Default::default(),
1106            outputs: Default::default(),
1107            id: None,
1108        }
1109    }
1110
1111    /// Finalizes an ABI declaration.
1112    pub fn build(self) -> Function {
1113        let (input_id, output_id) = match self.id {
1114            Some(id) => (id, id),
1115            None => {
1116                let id = Function::compute_function_id(
1117                    self.abi_version,
1118                    &self.name,
1119                    &self.headers,
1120                    &self.inputs,
1121                    &self.outputs,
1122                );
1123                (id & Function::INPUT_ID_MASK, id | !Function::INPUT_ID_MASK)
1124            }
1125        };
1126
1127        Function {
1128            abi_version: self.abi_version,
1129            headers: Arc::from(self.headers),
1130            name: Arc::from(self.name),
1131            inputs: Arc::from(self.inputs),
1132            outputs: Arc::from(self.outputs),
1133            input_id,
1134            output_id,
1135        }
1136    }
1137
1138    /// Sets method headers to the specified list.
1139    pub fn with_headers<I: IntoIterator<Item = AbiHeaderType>>(mut self, headers: I) -> Self {
1140        self.headers = headers.into_iter().collect();
1141        self
1142    }
1143
1144    /// Sets method input types to the specified list of named arguments.
1145    pub fn with_inputs<I, T>(mut self, inputs: I) -> Self
1146    where
1147        I: IntoIterator<Item = T>,
1148        T: Into<NamedAbiType>,
1149    {
1150        self.inputs = inputs.into_iter().map(Into::into).collect();
1151        self
1152    }
1153
1154    /// Sets method input types to the specified list of unnamed arguments.
1155    pub fn with_unnamed_inputs<I: IntoIterator<Item = AbiType>>(mut self, inputs: I) -> Self {
1156        self.inputs = inputs
1157            .into_iter()
1158            .enumerate()
1159            .map(NamedAbiType::from)
1160            .collect();
1161        self
1162    }
1163
1164    /// Sets method output types to the specified list of named arguments.
1165    pub fn with_outputs<I, T>(mut self, outputs: I) -> Self
1166    where
1167        I: IntoIterator<Item = T>,
1168        T: Into<NamedAbiType>,
1169    {
1170        self.outputs = outputs.into_iter().map(Into::into).collect();
1171        self
1172    }
1173
1174    /// Sets method output types to the specified list of unnamed arguments.
1175    pub fn with_unnamed_outputs<I: IntoIterator<Item = AbiType>>(mut self, outputs: I) -> Self {
1176        self.outputs = outputs
1177            .into_iter()
1178            .enumerate()
1179            .map(NamedAbiType::from)
1180            .collect();
1181        self
1182    }
1183
1184    /// Sets an explicit function id.
1185    pub fn with_id(mut self, id: u32) -> Self {
1186        self.id = Some(id);
1187        self
1188    }
1189}
1190
1191/// Contract event ABI definition.
1192#[derive(Debug, Clone)]
1193pub struct Event {
1194    /// ABI version (same as contract ABI version).
1195    pub abi_version: AbiVersion,
1196    /// Event name.
1197    pub name: Arc<str>,
1198    /// Event arguments.
1199    pub inputs: Arc<[NamedAbiType]>,
1200    /// Event id derived from signature.
1201    pub id: u32,
1202}
1203
1204impl Event {
1205    /// Computes event id from the full event signature.
1206    pub fn compute_event_id(abi_version: AbiVersion, name: &str, inputs: &[NamedAbiType]) -> u32 {
1207        let mut hasher = sha2::Sha256::new();
1208        EventSignatureRaw {
1209            abi_version,
1210            name,
1211            inputs,
1212        }
1213        .update_hasher(&mut hasher);
1214
1215        let hash: [u8; 32] = hasher.finalize().into();
1216        u32::from_be_bytes(hash[0..4].try_into().unwrap())
1217    }
1218
1219    /// Returns an event builder with the specified ABI version and name.
1220    #[inline]
1221    pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> EventBuilder {
1222        EventBuilder::new(abi_version, name)
1223    }
1224
1225    /// Encodes a message body with this event as an internal message.
1226    pub fn encode_internal_input(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
1227        ok!(NamedAbiValue::check_types(tokens, &self.inputs));
1228        Function::encode_internal_msg_body(self.abi_version, self.id, tokens)
1229    }
1230
1231    /// Tries to parse input arguments for this event from an internal message body.
1232    ///
1233    /// NOTE: The slice is required to contain nothing other than these arguments.
1234    pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
1235        self.decode_internal_input_ext(&mut slice, false)
1236    }
1237
1238    /// Tries to parse input arguments for this event from an internal message body.
1239    pub fn decode_internal_input_ext(
1240        &self,
1241        slice: &mut CellSlice<'_>,
1242        allow_partial: bool,
1243    ) -> Result<Vec<NamedAbiValue>> {
1244        let id = slice.load_u32()?;
1245        anyhow::ensure!(id == self.id, AbiError::InputIdMismatch {
1246            expected: self.id,
1247            id
1248        });
1249        let res = ok!(NamedAbiValue::load_tuple_ext(
1250            &self.inputs,
1251            self.abi_version,
1252            true,
1253            allow_partial,
1254            slice
1255        ));
1256        ok!(AbiValue::check_remaining(slice, allow_partial));
1257        Ok(res)
1258    }
1259
1260    /// Returns an object which can be used to display the normalized signature of this event.
1261    pub fn display_signature(&self) -> impl std::fmt::Display + '_ {
1262        EventSignatureRaw {
1263            abi_version: self.abi_version,
1264            name: &self.name,
1265            inputs: &self.inputs,
1266        }
1267    }
1268}
1269
1270/// Event ABI declaration builder.
1271#[derive(Debug, Clone)]
1272pub struct EventBuilder {
1273    abi_version: AbiVersion,
1274    name: String,
1275    inputs: Vec<NamedAbiType>,
1276    id: Option<u32>,
1277}
1278
1279impl EventBuilder {
1280    /// Creates an empty ABI declaration for an event with the specified ABI version and name.
1281    pub fn new<T: Into<String>>(abi_version: AbiVersion, name: T) -> Self {
1282        Self {
1283            abi_version,
1284            name: name.into(),
1285            inputs: Default::default(),
1286            id: None,
1287        }
1288    }
1289
1290    /// Finalizes an ABI declaration.
1291    pub fn build(self) -> Event {
1292        let id = match self.id {
1293            Some(id) => id,
1294            None => {
1295                let id = Event::compute_event_id(self.abi_version, &self.name, &self.inputs);
1296                id & Function::INPUT_ID_MASK
1297            }
1298        };
1299
1300        Event {
1301            abi_version: self.abi_version,
1302            name: Arc::from(self.name),
1303            inputs: Arc::from(self.inputs),
1304            id,
1305        }
1306    }
1307
1308    /// Sets event input types to the specified list of named arguments.
1309    pub fn with_inputs<I, T>(mut self, inputs: I) -> Self
1310    where
1311        I: IntoIterator<Item = T>,
1312        T: Into<NamedAbiType>,
1313    {
1314        self.inputs = inputs.into_iter().map(Into::into).collect();
1315        self
1316    }
1317
1318    /// Sets event input types to the specified list of unnamed arguments.
1319    pub fn with_unnamed_inputs<I: IntoIterator<Item = AbiType>>(mut self, inputs: I) -> Self {
1320        self.inputs = inputs
1321            .into_iter()
1322            .enumerate()
1323            .map(NamedAbiType::from)
1324            .collect();
1325        self
1326    }
1327
1328    /// Sets an explicit event id.
1329    pub fn with_id(mut self, id: u32) -> Self {
1330        self.id = Some(id);
1331        self
1332    }
1333}
1334
1335/// Unsigned external message.
1336pub struct UnsignedExternalMessage {
1337    /// Destination contract address.
1338    pub dst: StdAddr,
1339    /// Unsigned payload.
1340    pub body: UnsignedBody,
1341    /// Optional initial contract state.
1342    pub init: Option<StateInit>,
1343}
1344
1345impl UnsignedExternalMessage {
1346    /// Updates the state init of the external message to the specified one.
1347    pub fn set_state_init(&mut self, init: Option<StateInit>) {
1348        self.init = init;
1349    }
1350
1351    /// Returns an external message with the specified state init.
1352    pub fn with_state_init(mut self, init: StateInit) -> Self {
1353        self.set_state_init(Some(init));
1354        self
1355    }
1356
1357    /// Returns the expiration timestamp of this message.
1358    #[inline]
1359    pub fn expire_at(&self) -> u32 {
1360        self.body.expire_at
1361    }
1362
1363    /// Signs the payload and returns an external message with filled signature.
1364    pub fn sign(
1365        self,
1366        key: &ed25519_dalek::SigningKey,
1367        signature_id: Option<i32>,
1368    ) -> Result<OwnedMessage> {
1369        let signature =
1370            crate::abi::sign_with_signature_id(key, self.body.hash.as_slice(), signature_id);
1371        self.with_signature(&signature)
1372    }
1373
1374    /// Returns an external message with filled signature.
1375    pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<OwnedMessage> {
1376        self.into_signed(Some(&signature.to_bytes()))
1377    }
1378
1379    /// Returns an external message with signature filled with zero bytes.
1380    pub fn with_fake_signature(self) -> Result<OwnedMessage> {
1381        self.into_signed(Some(&[0u8; 64]))
1382    }
1383
1384    /// Returns an external message with empty signature.
1385    pub fn without_signature(self) -> Result<OwnedMessage> {
1386        self.into_signed(None)
1387    }
1388
1389    /// Returns an external message with filled signature.
1390    pub fn fill_signature(&self, signature: Option<&[u8; 64]>) -> Result<OwnedMessage> {
1391        let body = self.body.fill_signature(signature)?;
1392        Ok(OwnedMessage {
1393            info: MsgInfo::ExtIn(ExtInMsgInfo {
1394                dst: IntAddr::Std(self.dst.clone()),
1395                ..Default::default()
1396            }),
1397            body: body.into(),
1398            init: self.init.clone(),
1399            layout: None,
1400        })
1401    }
1402
1403    /// Converts an unsigned message into an external message with filled signature.
1404    fn into_signed(self, signature: Option<&[u8; 64]>) -> Result<OwnedMessage> {
1405        let body = self.body.fill_signature(signature)?;
1406        Ok(OwnedMessage {
1407            info: MsgInfo::ExtIn(ExtInMsgInfo {
1408                dst: IntAddr::Std(self.dst),
1409                ..Default::default()
1410            }),
1411            body: body.into(),
1412            init: self.init,
1413            layout: None,
1414        })
1415    }
1416}
1417
1418/// Unsigned external message payload.
1419pub struct UnsignedBody {
1420    /// ABI version used during encoding.
1421    pub abi_version: AbiVersion,
1422    /// Unsigned payload.
1423    pub payload: Cell,
1424    /// A hash to sign.
1425    pub hash: HashBytes,
1426    /// Message expiration timestamp (in seconds).
1427    pub expire_at: u32,
1428}
1429
1430impl UnsignedBody {
1431    /// Extends message with the specified destination address and returns an
1432    /// unsigned external message.
1433    pub fn with_dst(self, dst: StdAddr) -> UnsignedExternalMessage {
1434        UnsignedExternalMessage {
1435            dst,
1436            body: self,
1437            init: None,
1438        }
1439    }
1440
1441    /// Signs the payload and returns a body cell with filled signature.
1442    pub fn sign(self, key: &ed25519_dalek::SigningKey, signature_id: Option<i32>) -> Result<Cell> {
1443        let signature = crate::abi::sign_with_signature_id(key, self.hash.as_slice(), signature_id);
1444        self.with_signature(&signature)
1445    }
1446
1447    /// Returns a body cell with filled signature.
1448    pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<Cell> {
1449        self.fill_signature(Some(&signature.to_bytes()))
1450    }
1451
1452    /// Returns a body cell with signature filled with zero bytes.
1453    pub fn with_fake_signature(self) -> Result<Cell> {
1454        self.fill_signature(Some(&[0u8; 64]))
1455    }
1456
1457    /// Returns a body cell with empty signature.
1458    pub fn without_signature(self) -> Result<Cell> {
1459        self.fill_signature(None)
1460    }
1461
1462    /// Returns a body cell with filled signature.
1463    pub fn fill_signature(&self, signature: Option<&[u8; 64]>) -> Result<Cell> {
1464        let mut builder = CellBuilder::new();
1465
1466        if self.abi_version.major == 1 {
1467            builder.store_reference(match signature {
1468                Some(signature) => {
1469                    // TODO: extend with public key?
1470                    CellBuilder::from_raw_data(signature, 512).and_then(CellBuilder::build)?
1471                }
1472                None => Cell::empty_cell(),
1473            })?;
1474        } else {
1475            match signature {
1476                Some(signature) => {
1477                    builder.store_bit_one()?;
1478                    builder.store_raw(signature, 512)?;
1479                }
1480                None => builder.store_bit_zero()?,
1481            }
1482            builder.store_slice(self.payload.as_slice()?)?;
1483        }
1484
1485        builder.build().map_err(From::from)
1486    }
1487}
1488
1489struct FunctionSignatureRaw<'a> {
1490    abi_version: AbiVersion,
1491    name: &'a str,
1492    headers: &'a [AbiHeaderType],
1493    inputs: &'a [NamedAbiType],
1494    outputs: &'a [NamedAbiType],
1495}
1496
1497impl FunctionSignatureRaw<'_> {
1498    fn update_hasher<H: Digest>(&self, engine: &mut H) {
1499        std::fmt::write(&mut DisplayHasher(engine), format_args!("{self}")).unwrap();
1500    }
1501}
1502
1503impl std::fmt::Display for FunctionSignatureRaw<'_> {
1504    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1505        ok!(write!(f, "{}(", self.name));
1506
1507        let mut first = true;
1508        if self.abi_version.major == 1 {
1509            for header in self.headers {
1510                if !std::mem::take(&mut first) {
1511                    ok!(f.write_str(","));
1512                }
1513                ok!(std::fmt::Display::fmt(header, f));
1514            }
1515        }
1516        for item in self.inputs {
1517            if !std::mem::take(&mut first) {
1518                ok!(f.write_str(","));
1519            }
1520            ok!(std::fmt::Display::fmt(&item.ty, f));
1521        }
1522
1523        ok!(f.write_str(")("));
1524
1525        first = true;
1526        for item in self.outputs {
1527            if !std::mem::take(&mut first) {
1528                ok!(f.write_str(","));
1529            }
1530            ok!(std::fmt::Display::fmt(&item.ty, f));
1531        }
1532
1533        write!(f, ")v{}", self.abi_version.major)
1534    }
1535}
1536
1537struct EventSignatureRaw<'a> {
1538    abi_version: AbiVersion,
1539    name: &'a str,
1540    inputs: &'a [NamedAbiType],
1541}
1542
1543impl EventSignatureRaw<'_> {
1544    fn update_hasher<H: Digest>(&self, engine: &mut H) {
1545        std::fmt::write(&mut DisplayHasher(engine), format_args!("{self}")).unwrap();
1546    }
1547}
1548
1549impl std::fmt::Display for EventSignatureRaw<'_> {
1550    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1551        ok!(write!(f, "{}(", self.name));
1552
1553        let mut first = true;
1554        for item in self.inputs {
1555            if !std::mem::take(&mut first) {
1556                ok!(f.write_str(","));
1557            }
1558            ok!(std::fmt::Display::fmt(&item.ty, f));
1559        }
1560        write!(f, ")v{}", self.abi_version.major)
1561    }
1562}
1563
1564#[repr(transparent)]
1565struct DisplayHasher<'a, H>(&'a mut H);
1566
1567impl<H: Digest> std::fmt::Write for DisplayHasher<'_, H> {
1568    #[inline]
1569    fn write_str(&mut self, s: &str) -> std::fmt::Result {
1570        self.0.update(s.as_bytes());
1571        Ok(())
1572    }
1573}