Smart Contract

ThulToken

A.e3ad6030cbaff1c2.ThulToken

Deployed

1d ago
Feb 26, 2026, 11:03:37 PM UTC

Dependents

0 imports
1import FungibleToken from 0xf233dcee88fe0abe
2
3pub contract ThulToken: FungibleToken {
4
5    /// Total supply of ThulTokens in existence
6    pub var totalSupply: UFix64
7
8    /// Storage and Public Paths
9    pub let VaultStoragePath: StoragePath
10    pub let ReceiverPublicPath: PublicPath
11    pub let BalancePublicPath: PublicPath
12    pub let AdminStoragePath: StoragePath
13
14    /// TokensInitialized
15    ///
16    /// The event that is emitted when the contract is created
17    pub event TokensInitialized(initialSupply: UFix64)
18
19    /// TokensWithdrawn
20    ///
21    /// The event that is emitted when tokens are withdrawn from a Vault
22    pub event TokensWithdrawn(amount: UFix64, from: Address?)
23
24    /// TokensDeposited
25    ///
26    /// The event that is emitted when tokens are deposited to a Vault
27    pub event TokensDeposited(amount: UFix64, to: Address?)
28
29    /// TokensMinted
30    ///
31    /// The event that is emitted when new tokens are minted
32    pub event TokensMinted(amount: UFix64)
33
34    /// TokensBurned
35    ///
36    /// The event that is emitted when tokens are destroyed
37    pub event TokensBurned(amount: UFix64)
38
39    /// MinterCreated
40    ///
41    /// The event that is emitted when a new minter resource is created
42    pub event MinterCreated(allowedAmount: UFix64)
43
44    /// BurnerCreated
45    ///
46    /// The event that is emitted when a new burner resource is created
47    pub event BurnerCreated()
48
49    /// Vault
50    ///
51    /// Each user stores an instance of only the Vault in their storage
52    /// The functions in the Vault and governed by the pre and post conditions
53    /// in FungibleToken when they are called.
54    /// The checks happen at runtime whenever a function is called.
55    ///
56    /// Resources can only be created in the context of the contract that they
57    /// are defined in, so there is no way for a malicious user to create Vaults
58    /// out of thin air. A special Minter resource needs to be defined to mint
59    /// new tokens.
60    ///
61    pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance {
62
63        /// The total balance of this vault
64        pub var balance: UFix64
65
66        // initialize the balance at resource creation time
67        init(balance: UFix64) {
68            self.balance = balance
69        }
70
71        /// withdraw
72        ///
73        /// Function that takes an amount as an argument
74        /// and withdraws that amount from the Vault.
75        ///
76        /// It creates a new temporary Vault that is used to hold
77        /// the money that is being transferred. It returns the newly
78        /// created Vault to the context that called so it can be deposited
79        /// elsewhere.
80        ///
81        pub fun withdraw(amount: UFix64): @FungibleToken.Vault {
82            self.balance = self.balance - amount
83            emit TokensWithdrawn(amount: amount, from: self.owner?.address)
84            return <-create Vault(balance: amount)
85        }
86
87        /// deposit
88        ///
89        /// Function that takes a Vault object as an argument and adds
90        /// its balance to the balance of the owners Vault.
91        ///
92        /// It is allowed to destroy the sent Vault because the Vault
93        /// was a temporary holder of the tokens. The Vault's balance has
94        /// been consumed and therefore can be destroyed.
95        ///
96        pub fun deposit(from: @FungibleToken.Vault) {
97            let vault <- from as! @ThulToken.Vault
98            self.balance = self.balance + vault.balance
99            emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
100            vault.balance = 0.0
101            destroy vault
102        }
103
104        destroy() {
105            ThulToken.totalSupply = ThulToken.totalSupply - self.balance
106        }
107    }
108
109    /// createEmptyVault
110    ///
111    /// Function that creates a new Vault with a balance of zero
112    /// and returns it to the calling context. A user must call this function
113    /// and store the returned Vault in their storage in order to allow their
114    /// account to be able to receive deposits of this token type.
115    ///
116    pub fun createEmptyVault(): @Vault {
117        return <-create Vault(balance: 0.0)
118    }
119
120    pub resource Administrator {
121
122        /// createNewMinter
123        ///
124        /// Function that creates and returns a new minter resource
125        ///
126        pub fun createNewMinter(allowedAmount: UFix64): @Minter {
127            emit MinterCreated(allowedAmount: allowedAmount)
128            return <-create Minter(allowedAmount: allowedAmount)
129        }
130
131        /// createNewBurner
132        ///
133        /// Function that creates and returns a new burner resource
134        ///
135        pub fun createNewBurner(): @Burner {
136            emit BurnerCreated()
137            return <-create Burner()
138        }
139    }
140
141    /// Minter
142    ///
143    /// Resource object that token admin accounts can hold to mint new tokens.
144    ///
145    pub resource Minter {
146
147        /// The amount of tokens that the minter is allowed to mint
148        pub var allowedAmount: UFix64
149
150        /// mintTokens
151        ///
152        /// Function that mints new tokens, adds them to the total supply,
153        /// and returns them to the calling context.
154        ///
155        pub fun mintTokens(amount: UFix64): @ThulToken.Vault {
156            pre {
157                amount > 0.0: "Amount minted must be greater than zero"
158                amount <= self.allowedAmount: "Amount minted must be less than the allowed amount"
159            }
160            ThulToken.totalSupply = ThulToken.totalSupply + amount
161            self.allowedAmount = self.allowedAmount - amount
162            emit TokensMinted(amount: amount)
163            return <-create Vault(balance: amount)
164        }
165
166        init(allowedAmount: UFix64) {
167            self.allowedAmount = allowedAmount
168        }
169    }
170
171    /// Burner
172    ///
173    /// Resource object that token admin accounts can hold to burn tokens.
174    ///
175    pub resource Burner {
176
177        /// burnTokens
178        ///
179        /// Function that destroys a Vault instance, effectively burning the tokens.
180        ///
181        /// Note: the burned tokens are automatically subtracted from the
182        /// total supply in the Vault destructor.
183        ///
184        pub fun burnTokens(from: @FungibleToken.Vault) {
185            let vault <- from as! @ThulToken.Vault
186            let amount = vault.balance
187            destroy vault
188            emit TokensBurned(amount: amount)
189        }
190    }
191
192    init() {
193        self.totalSupply = 1000.0
194
195        self.VaultStoragePath = /storage/thulTokenVault
196        self.ReceiverPublicPath = /public/thulTokenReceiver
197        self.BalancePublicPath = /public/thulTokenBalance
198        self.AdminStoragePath = /storage/thulTokenAdmin
199
200        // Create the Vault with the total supply of tokens and save it in storage
201        //
202        let vault <- create Vault(balance: self.totalSupply)
203        self.account.save(<-vault, to: self.VaultStoragePath)
204
205        // Create a public capability to the stored Vault that only exposes
206        // the `deposit` method through the `Receiver` interface
207        //
208        self.account.link<&{FungibleToken.Receiver}>(
209            self.ReceiverPublicPath,
210            target: self.VaultStoragePath
211        )
212
213        // Create a public capability to the stored Vault that only exposes
214        // the `balance` field through the `Balance` interface
215        //
216        self.account.link<&ThulToken.Vault{FungibleToken.Balance}>(
217            self.BalancePublicPath,
218            target: self.VaultStoragePath
219        )
220
221        let admin <- create Administrator()
222        self.account.save(<-admin, to: self.AdminStoragePath)
223
224        // Emit an event that shows that the contract was initialized
225        //
226        emit TokensInitialized(initialSupply: self.totalSupply)
227    }
228}
229