Smart Contract
MEDI
A.8f4f599546e2d7eb.MEDI
1/*
2 * Copyright (c) 2021 24Karat. All rights reserved.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * This file is part of Project: 24karat flow contract (https://github.com/24karat-gld/flow-24karat-contract)
7 *
8 * This source code is licensed under the MIT License found in the
9 * LICENSE file in the root directory of this source tree or at
10 * https://opensource.org/licenses/MIT.
11 */
12
13import FungibleToken from 0xf233dcee88fe0abe
14
15pub contract MEDI: FungibleToken {
16 // TokensInitialized
17 //
18 // The event that is emitted when the contract is created
19 pub event TokensInitialized(initialSupply: UFix64)
20
21 // TokensWithdrawn
22 //
23 // The event that is emitted when tokens are withdrawn from a Vault
24 pub event TokensWithdrawn(amount: UFix64, from: Address?)
25
26 // TokensDeposited
27 //
28 // The event that is emitted when tokens are deposited to a Vault
29 pub event TokensDeposited(amount: UFix64, to: Address?)
30
31 // TokensMinted
32 //
33 // The event that is emitted when new tokens are minted
34 pub event TokensMinted(amount: UFix64)
35
36 // TokensBurned
37 //
38 // The event that is emitted when tokens are destroyed
39 pub event TokensBurned(amount: UFix64)
40
41 // MinterCreated
42 //
43 // The event that is emitted when a new minter resource is created
44 pub event MinterCreated(allowedAmount: UFix64)
45
46 // Named paths
47 //
48 pub let VaultStoragePath: StoragePath
49 pub let ReceiverPublicPath: PublicPath
50 pub let BalancePublicPath: PublicPath
51 pub let AdminStoragePath: StoragePath
52
53 // Total supply of token in existence
54 pub var totalSupply: UFix64
55
56 // Vault
57 //
58 // Each user stores an instance of only the Vault in their storage
59 // The functions in the Vault and governed by the pre and post conditions
60 // in FungibleToken when they are called.
61 // The checks happen at runtime whenever a function is called.
62 //
63 // Resources can only be created in the context of the contract that they
64 // are defined in, so there is no way for a malicious user to create Vaults
65 // out of thin air. A special Minter resource needs to be defined to mint
66 // new tokens.
67 //
68 pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance {
69
70 // The total balance of this vault
71 pub var balance: UFix64
72
73 // initialize the balance at resource creation time
74 init(balance: UFix64) {
75 self.balance = balance
76 }
77
78 // withdraw
79 //
80 // Function that takes an amount as an argument
81 // and withdraws that amount from the Vault.
82 //
83 // It creates a new temporary Vault that is used to hold
84 // the money that is being transferred. It returns the newly
85 // created Vault to the context that called so it can be deposited
86 // elsewhere.
87 //
88 pub fun withdraw(amount: UFix64): @FungibleToken.Vault {
89 self.balance = self.balance - amount
90 emit TokensWithdrawn(amount: amount, from: self.owner?.address)
91 return <-create Vault(balance: amount)
92 }
93
94 // deposit
95 //
96 // Function that takes a Vault object as an argument and adds
97 // its balance to the balance of the owners Vault.
98 //
99 // It is allowed to destroy the sent Vault because the Vault
100 // was a temporary holder of the tokens. The Vault's balance has
101 // been consumed and therefore can be destroyed.
102 //
103 pub fun deposit(from: @FungibleToken.Vault) {
104 let vault <- from as! @MEDI.Vault
105 self.balance = self.balance + vault.balance
106 emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
107 vault.balance = 0.0
108 destroy vault
109 }
110
111 destroy() {
112 MEDI.totalSupply = MEDI.totalSupply - self.balance
113 if(self.balance > 0.0) {
114 emit TokensBurned(amount: self.balance)
115 }
116 }
117 }
118
119 // createEmptyVault
120 //
121 // Function that creates a new Vault with a balance of zero
122 // and returns it to the calling context. A user must call this function
123 // and store the returned Vault in their storage in order to allow their
124 // account to be able to receive deposits of this token type.
125 //
126 pub fun createEmptyVault(): @Vault {
127 return <-create Vault(balance: 0.0)
128 }
129
130 pub resource Administrator {
131
132 // createNewMinter
133 //
134 // Function that creates and returns a new minter resource
135 //
136 pub fun createNewMinter(allowedAmount: UFix64): @Minter {
137 emit MinterCreated(allowedAmount: allowedAmount)
138 return <-create Minter(allowedAmount: allowedAmount)
139 }
140 }
141
142 // Minter
143 //
144 // Resource object that token admin accounts can hold to mint new tokens.
145 //
146 pub resource Minter {
147
148 // The amount of tokens that the minter is allowed to mint
149 pub var allowedAmount: UFix64
150
151 // mintTokens
152 //
153 // Function that mints new tokens, adds them to the total supply,
154 // and returns them to the calling context.
155 //
156 pub fun mintTokens(amount: UFix64): @MEDI.Vault {
157 pre {
158 amount > 0.0: "Amount minted must be greater than zero"
159 amount <= self.allowedAmount: "Amount minted must be less than the allowed amount"
160 }
161 MEDI.totalSupply = MEDI.totalSupply + amount
162 self.allowedAmount = self.allowedAmount - amount
163 emit TokensMinted(amount: amount)
164 return <-create Vault(balance: amount)
165 }
166
167 init(allowedAmount: UFix64) {
168 self.allowedAmount = allowedAmount
169 }
170 }
171
172 init() {
173 // Set our named paths.
174 self.VaultStoragePath = /storage/MEDI24KaratVault
175 self.ReceiverPublicPath = /public/MEDI24KaratReceiver
176 self.BalancePublicPath = /public/MEDI24KaratBalance
177 self.AdminStoragePath = /storage/MEDI24KaratAdmin
178
179 // Initialize contract state.
180 self.totalSupply = 0.0
181
182 // Create the one true Admin object and deposit it into the conttract account.
183 let admin <- create Administrator()
184 self.account.save(<-admin, to: self.AdminStoragePath)
185
186 // Emit an event that shows that the contract was initialized.
187 emit TokensInitialized(initialSupply: self.totalSupply)
188 }
189}
190