Smart Contract
GreenBitcoin
A.078a8129525775dd.GreenBitcoin
1import FungibleToken from 0xf233dcee88fe0abe
2import FungibleTokenMetadataViews from 0xf233dcee88fe0abe
3import MetadataViews from 0x1d7e57aa55817448
4import Toucans from 0x577a3c409c5dcb5e
5import ToucansTokens from 0x577a3c409c5dcb5e
6
7pub contract GreenBitcoin: FungibleToken {
8
9 // The amount of tokens in existance
10 pub var totalSupply: UFix64
11 // nil if there is none
12 pub let maxSupply: UFix64?
13
14 // Paths
15 pub let VaultStoragePath: StoragePath
16 pub let ReceiverPublicPath: PublicPath
17 pub let VaultPublicPath: PublicPath
18 pub let MinterStoragePath: StoragePath
19 pub let AdministratorStoragePath: StoragePath
20
21 // Events
22 pub event TokensInitialized(initialSupply: UFix64)
23 pub event TokensWithdrawn(amount: UFix64, from: Address?)
24 pub event TokensDeposited(amount: UFix64, to: Address?)
25 pub event TokensTransferred(amount: UFix64, from: Address, to: Address)
26 pub event TokensMinted(amount: UFix64)
27 pub event TokensBurned(amount: UFix64)
28
29 pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance, MetadataViews.Resolver {
30 pub var balance: UFix64
31
32 pub fun withdraw(amount: UFix64): @FungibleToken.Vault {
33 self.balance = self.balance - amount
34 emit TokensWithdrawn(amount: amount, from: self.owner?.address)
35
36 if let owner: Address = self.owner?.address {
37 GreenBitcoin.setBalance(address: owner, balance: self.balance)
38 }
39 return <- create Vault(balance: amount)
40 }
41
42 pub fun deposit(from: @FungibleToken.Vault) {
43 let vault: @Vault <- from as! @Vault
44 self.balance = self.balance + vault.balance
45 emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
46
47 // We set the balance to 0.0 here so that it doesn't
48 // decrease the totalSupply in the `destroy` function.
49 vault.balance = 0.0
50 destroy vault
51
52 if let owner: Address = self.owner?.address {
53 GreenBitcoin.setBalance(address: owner, balance: self.balance)
54 }
55 }
56
57 pub fun getViews(): [Type]{
58 return [Type<FungibleTokenMetadataViews.FTView>(),
59 Type<FungibleTokenMetadataViews.FTDisplay>(),
60 Type<FungibleTokenMetadataViews.FTVaultData>()]
61 }
62
63 pub fun resolveView(_ view: Type): AnyStruct? {
64 switch view {
65 case Type<FungibleTokenMetadataViews.FTView>():
66 return FungibleTokenMetadataViews.FTView(
67 ftDisplay: self.resolveView(Type<FungibleTokenMetadataViews.FTDisplay>()) as! FungibleTokenMetadataViews.FTDisplay?,
68 ftVaultData: self.resolveView(Type<FungibleTokenMetadataViews.FTVaultData>()) as! FungibleTokenMetadataViews.FTVaultData?
69 )
70 case Type<FungibleTokenMetadataViews.FTDisplay>():
71 let media = MetadataViews.Media(
72 file: MetadataViews.HTTPFile(
73 url: "https://nftstorage.link/ipfs/bafkreigglohoo25a4zqqf6qauofnkaufoz3g7g4huijphy3jwhyyzbpnxa"
74 ),
75 mediaType: "image"
76 )
77 let medias = MetadataViews.Medias([media])
78 return FungibleTokenMetadataViews.FTDisplay(
79 name: "Green Bitcoin",
80 symbol: "GBTC",
81 description: "Every blockchain deserves a Bitcoin, and with Green Bitcoin, we aim to provide the long-awaited stability that users deserve.In a world filled with digital transactions and innovation, cryptocurrencies have revolutionized the way we store and exchange value. Blockchain technology has brought unprecedented levels of decentralization and security, but it is not without challenges.Green Bitcoin takes it a step further by focusing on sustainability and ecological responsibility. We recognize that the success of a cryptocurrency should not only be measured in financial gains but also in its impact on the environment. Therefore, we strive to create a green and sustainable Bitcoin, utilizing energy-efficient mining processes and renewable energy sources.With Green Bitcoin, we want to bestow the long-awaited stability upon users. We understand the need for stability and reliability in the cryptocurrency market. By combining a solid technological foundation, green mining practices, and a passionate community, we aim to provide a cryptocurrency that not only preserves value but also maximizes positive environmental impact.Join the Green Bitcoin movement and experience a new dimension of cryptocurrency. Together, we can pave the way towards a more sustainable and stable future.",
82 externalURL: MetadataViews.ExternalURL(""),
83 logos: medias,
84 socials: {
85 "twitter": MetadataViews.ExternalURL(""),
86 "discord": MetadataViews.ExternalURL("https://discord.gg/vY8pK9x8")
87 }
88 )
89 case Type<FungibleTokenMetadataViews.FTVaultData>():
90 return FungibleTokenMetadataViews.FTVaultData(
91 storagePath: GreenBitcoin.VaultStoragePath,
92 receiverPath: GreenBitcoin.ReceiverPublicPath,
93 metadataPath: GreenBitcoin.VaultPublicPath,
94 providerPath: /private/GreenBitcoinVault,
95 receiverLinkedType: Type<&Vault{FungibleToken.Receiver}>(),
96 metadataLinkedType: Type<&Vault{FungibleToken.Balance, MetadataViews.Resolver}>(),
97 providerLinkedType: Type<&Vault{FungibleToken.Provider}>(),
98 createEmptyVaultFunction: (fun (): @Vault {
99 return <- GreenBitcoin.createEmptyVault()
100 })
101 )
102 }
103 return nil
104 }
105
106 init(balance: UFix64) {
107 self.balance = balance
108 }
109
110 destroy() {
111 emit TokensBurned(amount: self.balance)
112 GreenBitcoin.totalSupply = GreenBitcoin.totalSupply - self.balance
113 }
114 }
115
116 pub fun createEmptyVault(): @Vault {
117 return <- create Vault(balance: 0.0)
118 }
119
120 pub resource Minter: Toucans.Minter {
121 pub fun mint(amount: UFix64): @Vault {
122 post {
123 GreenBitcoin.maxSupply == nil || GreenBitcoin.totalSupply <= GreenBitcoin.maxSupply!:
124 "Exceeded the max supply of tokens allowd."
125 }
126 GreenBitcoin.totalSupply = GreenBitcoin.totalSupply + amount
127 emit TokensMinted(amount: amount)
128 return <- create Vault(balance: amount)
129 }
130 }
131
132 // We follow this pattern of storage
133 // so the (potentially) huge dictionary
134 // isn't loaded when the contract is imported
135 pub resource Administrator {
136 // This is an experimental index and should
137 // not be used for anything official
138 // or monetary related
139 access(self) let balances: {Address: UFix64}
140
141 access(contract) fun setBalance(address: Address, balance: UFix64) {
142 self.balances[address] = balance
143 }
144
145 pub fun getBalance(address: Address): UFix64 {
146 return self.balances[address] ?? 0.0
147 }
148
149 pub fun getBalances(): {Address: UFix64} {
150 return self.balances
151 }
152
153 init() {
154 self.balances = {}
155 }
156 }
157
158 access(contract) fun setBalance(address: Address, balance: UFix64) {
159 let admin: &Administrator = self.account.borrow<&Administrator>(from: self.AdministratorStoragePath)!
160 admin.setBalance(address: address, balance: balance)
161 }
162
163 pub fun getBalance(address: Address): UFix64 {
164 let admin: &Administrator = self.account.borrow<&Administrator>(from: self.AdministratorStoragePath)!
165 return admin.getBalance(address: address)
166 }
167
168 pub fun getBalances(): {Address: UFix64} {
169 let admin: &Administrator = self.account.borrow<&Administrator>(from: self.AdministratorStoragePath)!
170 return admin.getBalances()
171 }
172
173 init(
174 _paymentTokenInfo: ToucansTokens.TokenInfo,
175 _editDelay: UFix64,
176 _minting: Bool,
177 _initialTreasurySupply: UFix64,
178 _maxSupply: UFix64?,
179 _extra: {String: AnyStruct}
180 ) {
181
182 // Contract Variables
183 self.totalSupply = 0.0
184 self.maxSupply = _maxSupply
185
186 // Paths
187 self.VaultStoragePath = /storage/GreenBitcoinVault
188 self.ReceiverPublicPath = /public/GreenBitcoinReceiver
189 self.VaultPublicPath = /public/GreenBitcoinMetadata
190 self.MinterStoragePath = /storage/GreenBitcoinMinter
191 self.AdministratorStoragePath = /storage/GreenBitcoinAdmin
192
193 // Admin Setup
194 let vault <- create Vault(balance: self.totalSupply)
195 self.account.save(<- vault, to: self.VaultStoragePath)
196
197 self.account.link<&Vault{FungibleToken.Receiver}>(
198 self.ReceiverPublicPath,
199 target: self.VaultStoragePath
200 )
201
202 self.account.link<&Vault{FungibleToken.Balance, MetadataViews.Resolver}>(
203 self.VaultPublicPath,
204 target: self.VaultStoragePath
205 )
206
207 if self.account.borrow<&Toucans.Collection>(from: Toucans.CollectionStoragePath) == nil {
208 self.account.save(<- Toucans.createCollection(), to: Toucans.CollectionStoragePath)
209 self.account.link<&Toucans.Collection{Toucans.CollectionPublic}>(Toucans.CollectionPublicPath, target: Toucans.CollectionStoragePath)
210 }
211
212 let toucansProjectCollection = self.account.borrow<&Toucans.Collection>(from: Toucans.CollectionStoragePath)!
213 toucansProjectCollection.createProject(
214 projectTokenInfo: ToucansTokens.TokenInfo("GreenBitcoin", self.account.address, "GBTC", self.ReceiverPublicPath, self.VaultPublicPath, self.VaultStoragePath),
215 paymentTokenInfo: _paymentTokenInfo,
216 minter: <- create Minter(),
217 editDelay: _editDelay,
218 minting: _minting,
219 initialTreasurySupply: _initialTreasurySupply,
220 extra: _extra
221 )
222
223 self.account.save(<- create Administrator(), to: self.AdministratorStoragePath)
224
225 // Events
226 emit TokensInitialized(initialSupply: self.totalSupply)
227 }
228}
229