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