numbat_wasm_module_dcdt/
lib.rs1#![no_std]
2
3numbat_wasm::imports!();
4
5#[numbat_wasm::module]
7pub trait DcdtModule {
8 #[storage_mapper("token_id")]
9 fn token_id(&self) -> SingleValueMapper<TokenIdentifier>;
10
11 #[payable("REWA")]
12 #[endpoint(issueToken)]
13 fn issue_token(
14 &self,
15 token_display_name: ManagedBuffer,
16 token_ticker: ManagedBuffer,
17 num_decimals: usize,
18 #[payment] issue_cost: BigUint,
19 ) -> SCResult<AsyncCall> {
20 only_owner!(self, "only owner can issue token");
21 require!(self.token_id().is_empty(), "Token already issued");
22
23 let initial_supply = self.types().big_uint_from(1u32);
24
25 Ok(self
26 .send()
27 .dcdt_system_sc_proxy()
28 .issue_fungible(
29 issue_cost,
30 &token_display_name,
31 &token_ticker,
32 &initial_supply,
33 FungibleTokenProperties {
34 can_burn: false,
35 can_mint: false,
36 num_decimals,
37 can_freeze: true,
38 can_wipe: true,
39 can_pause: true,
40 can_change_owner: false,
41 can_upgrade: false,
42 can_add_special_roles: true,
43 },
44 )
45 .async_call()
46 .with_callback(self.callbacks().issue_callback()))
47 }
48
49 #[endpoint(setLocalRoles)]
51 fn set_local_roles(
52 &self,
53 #[var_args] opt_dest_address: OptionalArg<ManagedAddress>,
54 ) -> SCResult<AsyncCall> {
55 only_owner!(self, "only owner can set roles");
56
57 let dest_address = match opt_dest_address {
58 OptionalArg::Some(addr) => addr,
59 OptionalArg::None => self.blockchain().get_sc_address(),
60 };
61 let token_id = self.token_id().get();
62 let roles = [DcdtLocalRole::Mint, DcdtLocalRole::Burn];
63
64 Ok(self
65 .send()
66 .dcdt_system_sc_proxy()
67 .set_special_roles(&dest_address, &token_id, (&roles[..]).into_iter().cloned())
68 .async_call())
69 }
70
71 #[callback]
72 fn issue_callback(&self, #[call_result] result: ManagedAsyncCallResult<TokenIdentifier>) {
73 match result {
74 ManagedAsyncCallResult::Ok(token_id) => {
75 self.token_id().set(&token_id);
76 },
77 ManagedAsyncCallResult::Err(_) => {
78 let initial_caller = self.blockchain().get_owner_address();
80 let rewa_returned = self.call_value().rewa_value();
81 if rewa_returned > 0u32 {
82 self.send()
83 .direct_rewa(&initial_caller, &rewa_returned, &[]);
84 }
85 },
86 }
87 }
88
89 fn mint(&self, amount: &BigUint) -> SCResult<()> {
90 let token_id = self.token_id().get();
91
92 self.require_local_roles_set(&token_id)?;
93 self.send().dcdt_local_mint(&token_id, 0, amount);
94
95 Ok(())
96 }
97
98 fn burn(&self, amount: &BigUint) -> SCResult<()> {
99 let token_id = self.token_id().get();
100
101 self.require_local_roles_set(&token_id)?;
102 self.send().dcdt_local_burn(&token_id, 0, amount);
103
104 Ok(())
105 }
106
107 fn require_token_issued(&self) -> SCResult<()> {
108 require!(!self.token_id().is_empty(), "Token must be issued first");
109 Ok(())
110 }
111
112 fn require_local_roles_set(&self, token_id: &TokenIdentifier) -> SCResult<()> {
113 let roles = self.blockchain().get_dcdt_local_roles(token_id);
114 require!(
115 roles.contains(&DcdtLocalRole::Mint) && roles.contains(&DcdtLocalRole::Burn),
116 "Must set local roles first"
117 );
118 Ok(())
119 }
120}