everscale_types/abi/
contract.rs

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