odra_core/
entry_point.rs

1//! This module defines various types of entry points for smart contracts
2use alloc::boxed::Box;
3use alloc::{vec, vec::Vec};
4use casper_types::{CLType, CLTyped, Parameter};
5
6/// Represents different kinds of entry points in a contract.
7pub enum EntryPoint {
8    /// A regular entry point.
9    Regular {
10        /// The name of the entry point.
11        name: &'static str,
12        /// The arguments for the entry point.
13        args: Vec<Option<Parameter>>,
14        /// The return type of the entry point.
15        ret_ty: CLType,
16        /// Indicates if the entry point is non-reentrant.
17        is_non_reentrant: bool,
18        /// Indicates if the entry point is payable.
19        is_payable: bool
20    },
21    /// A constructor entry point.
22    Constructor {
23        /// The arguments for the constructor.
24        args: Vec<Option<Parameter>>
25    },
26    /// A template entry point, used in a factory pattern.
27    Template {
28        /// The name of the entry point.
29        name: &'static str,
30        /// The arguments for the entry point.
31        args: Vec<Option<Parameter>>,
32        /// The return type of the entry point.
33        ret_ty: CLType
34    },
35    /// A factory entry point.
36    Factory {
37        /// The arguments for the factory.
38        args: Vec<Option<Parameter>>
39    },
40    /// A factory upgrade entry point.
41    FactoryUpgrade {
42        /// The arguments for the factory.
43        args: Vec<Option<Parameter>>
44    },
45    /// A factory batch upgrade entry point.
46    FactoryBatchUpgrade,
47    /// An upgrader entry point.
48    Upgrader {
49        /// The arguments for the upgrader entry point.
50        args: Vec<Option<Parameter>>
51    }
52}
53
54/// Extension trait for adding entry points to `casper_types::EntryPoints`.
55pub trait EntityEntryPointsExt {
56    /// Adds an entry point to the collection.
57    fn add<T: Into<casper_types::EntityEntryPoint>>(&mut self, ep: T);
58}
59
60impl EntityEntryPointsExt for casper_types::EntryPoints {
61    fn add<T: Into<casper_types::EntityEntryPoint>>(&mut self, ep: T) {
62        self.add_entry_point(ep.into());
63    }
64}
65
66impl From<EntryPoint> for casper_types::EntityEntryPoint {
67    fn from(val: EntryPoint) -> Self {
68        match val {
69            EntryPoint::Regular {
70                name, args, ret_ty, ..
71            } => entry_point(name, args, ret_ty),
72            EntryPoint::Constructor { args } => constructor(args),
73            EntryPoint::Template { name, args, ret_ty } => template(name, args, ret_ty),
74            EntryPoint::Factory { args } => factory(args),
75            EntryPoint::Upgrader { args } => upgrader(args),
76            EntryPoint::FactoryUpgrade { args } => factory_upgrade(args),
77            EntryPoint::FactoryBatchUpgrade => factory_batch_upgrade()
78        }
79    }
80}
81
82impl TryFrom<EntryPoint> for crate::contract_def::Entrypoint {
83    type Error = &'static str;
84
85    fn try_from(val: EntryPoint) -> Result<Self, Self::Error> {
86        match val {
87            EntryPoint::Regular { name, args, ret_ty, is_non_reentrant, is_payable } => Ok(crate::contract_def::Entrypoint {
88                name: crate::prelude::string::String::from(name),
89                args: convert_args(args),
90                is_mutable: true,
91                return_ty: ret_ty,
92                ty: crate::contract_def::EntrypointType::Public,
93                attributes: match (is_non_reentrant, is_payable) {
94                    (true, true) => vec![
95                        crate::contract_def::EntrypointAttribute::NonReentrant,
96                        crate::contract_def::EntrypointAttribute::Payable
97                    ],
98                    (true, false) => vec![
99                        crate::contract_def::EntrypointAttribute::NonReentrant
100                    ],
101                    (false, true) => vec![
102                        crate::contract_def::EntrypointAttribute::Payable
103                    ],
104                    (false, false) => vec![]
105                }
106            }),
107            EntryPoint::Constructor { args } => Ok(crate::contract_def::Entrypoint {
108                name: crate::prelude::String::from("init"),
109                args: convert_args(args),
110                is_mutable: true,
111                return_ty: <() as crate::casper_types::CLTyped>::cl_type(),
112                ty: crate::contract_def::EntrypointType::Constructor,
113                attributes: crate::prelude::vec![]
114            }),
115            EntryPoint::Factory { args } => Ok(crate::contract_def::Entrypoint {
116                name: crate::prelude::string::String::from("new_contract"),
117                args: convert_args(args),
118                is_mutable: true,
119                return_ty: <(crate::prelude::Address, crate::casper_types::URef) as crate::casper_types::CLTyped>::cl_type(),
120                ty: crate::contract_def::EntrypointType::Public,
121                attributes: crate::prelude::vec![]
122            }),
123            EntryPoint::FactoryUpgrade { args } => Ok(crate::contract_def::Entrypoint {
124                name: crate::prelude::String::from("upgrade_child_contract"),
125                args: convert_args(args),
126                is_mutable: true,
127                return_ty: <() as crate::casper_types::CLTyped>::cl_type(),
128                ty: crate::contract_def::EntrypointType::Public,
129                attributes: crate::prelude::vec![]
130            }),
131            EntryPoint::FactoryBatchUpgrade => Ok(crate::contract_def::Entrypoint {
132                name: crate::prelude::String::from("batch_upgrade_child_contract"),
133                args: crate::prelude::vec![
134                    crate::contract_def::Argument {
135                        name: crate::prelude::String::from("args"),
136                        ty: Vec::<u8>::cl_type(),
137                        is_ref: false,
138                        is_slice: false,
139                        is_required: true
140                    }
141                ],
142                is_mutable: true,
143                return_ty: <() as crate::casper_types::CLTyped>::cl_type(),
144                ty: crate::contract_def::EntrypointType::Public,
145                attributes: crate::prelude::vec![]
146            }),
147            _ => Err("Conversion not implemented for this entry point type"),
148        }
149    }
150}
151
152fn convert_args(args: Vec<Option<Parameter>>) -> Vec<crate::contract_def::Argument> {
153    args.into_iter()
154        .flatten()
155        .map(|p| crate::contract_def::Argument {
156            name: crate::prelude::string::String::from(p.name()),
157            ty: p.cl_type().clone(),
158            is_ref: false,
159            is_slice: false,
160            is_required: true
161        })
162        .collect()
163}
164
165fn entry_point(
166    name: &str,
167    args: Vec<Option<Parameter>>,
168    ret_ty: CLType
169) -> casper_types::EntityEntryPoint {
170    casper_types::EntityEntryPoint::new(
171        name,
172        args.into_iter().flatten().collect(),
173        ret_ty,
174        casper_types::EntryPointAccess::Public,
175        casper_types::EntryPointType::Called,
176        casper_types::EntryPointPayment::Caller
177    )
178}
179
180fn constructor(args: Vec<Option<Parameter>>) -> casper_types::EntityEntryPoint {
181    casper_types::EntityEntryPoint::new(
182        "init",
183        args.into_iter().flatten().collect(),
184        CLType::Unit,
185        casper_types::EntryPointAccess::Groups(vec![casper_types::Group::new("constructor_group")]),
186        casper_types::EntryPointType::Called,
187        casper_types::EntryPointPayment::Caller
188    )
189}
190
191fn template(
192    name: &str,
193    args: Vec<Option<Parameter>>,
194    ret_ty: CLType
195) -> casper_types::EntityEntryPoint {
196    casper_types::EntityEntryPoint::new(
197        name,
198        args.into_iter().flatten().collect(),
199        ret_ty,
200        casper_types::EntryPointAccess::Template,
201        casper_types::EntryPointType::Called,
202        casper_types::EntryPointPayment::Caller
203    )
204}
205
206fn factory(args: Vec<Option<Parameter>>) -> casper_types::EntityEntryPoint {
207    casper_types::EntityEntryPoint::new(
208        "new_contract",
209        args.into_iter().flatten().collect(),
210        CLType::Tuple2([Box::new(CLType::Key), Box::new(CLType::URef)]),
211        casper_types::EntryPointAccess::Public,
212        casper_types::EntryPointType::Factory,
213        casper_types::EntryPointPayment::Caller
214    )
215}
216
217fn factory_upgrade(args: Vec<Option<Parameter>>) -> casper_types::EntityEntryPoint {
218    casper_types::EntityEntryPoint::new(
219        "upgrade_child_contract",
220        args.into_iter().flatten().collect(),
221        CLType::Unit,
222        casper_types::EntryPointAccess::Groups(vec![casper_types::Group::new("factory_group")]),
223        casper_types::EntryPointType::Called,
224        casper_types::EntryPointPayment::Caller
225    )
226}
227
228fn factory_batch_upgrade() -> casper_types::EntityEntryPoint {
229    casper_types::EntityEntryPoint::new(
230        "batch_upgrade_child_contract",
231        vec![casper_types::Parameter::new("args", Vec::<u8>::cl_type())],
232        CLType::Unit,
233        casper_types::EntryPointAccess::Groups(vec![casper_types::Group::new("factory_group")]),
234        casper_types::EntryPointType::Called,
235        casper_types::EntryPointPayment::Caller
236    )
237}
238
239fn upgrader(args: Vec<Option<Parameter>>) -> casper_types::EntityEntryPoint {
240    casper_types::EntityEntryPoint::new(
241        "upgrade",
242        args.into_iter().flatten().collect(),
243        CLType::Unit,
244        casper_types::EntryPointAccess::Groups(vec![casper_types::Group::new("upgrader_group")]),
245        casper_types::EntryPointType::Called,
246        casper_types::EntryPointPayment::Caller
247    )
248}