Smart Contract

RohamsWieners

A.39bd8fa7414207cb.RohamsWieners

Deployed

1d ago
Feb 26, 2026, 10:18:24 PM UTC

Dependents

0 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import FungibleTokenMetadataViews from 0xf233dcee88fe0abe
3import MetadataViews from 0x1d7e57aa55817448
4import Toucans from 0x577a3c409c5dcb5e
5import ToucansTokens from 0x577a3c409c5dcb5e
6 
7pub contract RohamsWieners: 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                RohamsWieners.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                RohamsWieners.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/bafkreifecwzpw5xoufaakty4eekxbuobitshs3kbdzjtm7t3pbicbf3v5u"
74                        ),
75                        mediaType: "image"
76                    )
77                    let bannerMedia = MetadataViews.Media(
78                            file: MetadataViews.HTTPFile(
79                            url: "https://nftstorage.link/ipfs/bafkreieef4d3di7mz4pdb73mlozwso5ys6nwqmxqs5wbdbqrhbr57zlpda"
80                        ),
81                        mediaType: "image"
82                    )
83                    let medias = MetadataViews.Medias([media, bannerMedia])
84                    return FungibleTokenMetadataViews.FTDisplay(
85                        name: "Roham's Wieners",
86                        symbol: "ROHAM",
87                        description: "Nearly 2 years ago, Dapper CEO Roham Gharegozlou promised that a key perk of being a Top Shot collector would be free hot dogs at NBA arenas. As of today, that promise has yet to be delivered upon. We are here to change that.",
88                        externalURL: MetadataViews.ExternalURL(""),
89                        logos: medias,
90                        socials: {
91                            "twitter": MetadataViews.ExternalURL("RohamsWieners"),
92                            "discord": MetadataViews.ExternalURL("")
93                        }
94                    )
95                case Type<FungibleTokenMetadataViews.FTVaultData>():
96                    return FungibleTokenMetadataViews.FTVaultData(
97                        storagePath: RohamsWieners.VaultStoragePath,
98                        receiverPath: RohamsWieners.ReceiverPublicPath,
99                        metadataPath: RohamsWieners.VaultPublicPath,
100                        providerPath: /private/RohamsWienersVault,
101                        receiverLinkedType: Type<&Vault{FungibleToken.Receiver}>(),
102                        metadataLinkedType: Type<&Vault{FungibleToken.Balance, MetadataViews.Resolver}>(),
103                        providerLinkedType: Type<&Vault{FungibleToken.Provider}>(),
104                        createEmptyVaultFunction: (fun (): @Vault {
105                            return <- RohamsWieners.createEmptyVault()
106                        })
107                    )
108            }
109            return nil
110        }
111  
112        init(balance: UFix64) {
113            self.balance = balance
114        }
115
116        destroy() {
117            if (self.balance > 0.0) {
118                emit TokensBurned(amount: self.balance)
119                RohamsWieners.totalSupply = RohamsWieners.totalSupply - self.balance
120            }
121        }
122    }
123
124    pub fun createEmptyVault(): @Vault {
125        return <- create Vault(balance: 0.0)
126    }
127
128    pub resource Minter: Toucans.Minter {
129        pub fun mint(amount: UFix64): @Vault {
130            post {
131                RohamsWieners.maxSupply == nil || RohamsWieners.totalSupply <= RohamsWieners.maxSupply!: 
132                    "Exceeded the max supply of tokens allowd."
133            }
134            RohamsWieners.totalSupply = RohamsWieners.totalSupply + amount
135            emit TokensMinted(amount: amount)
136            return <- create Vault(balance: amount)
137        }
138    }
139
140    // We follow this pattern of storage
141    // so the (potentially) huge dictionary 
142    // isn't loaded when the contract is imported
143    pub resource Administrator {
144        // This is an experimental index and should
145        // not be used for anything official
146        // or monetary related
147        access(self) let balances: {Address: UFix64}
148
149        access(contract) fun setBalance(address: Address, balance: UFix64) {
150            self.balances[address] = balance
151        }
152
153        pub fun getBalance(address: Address): UFix64 {
154            return self.balances[address] ?? 0.0
155        }
156
157        pub fun getBalances(): {Address: UFix64} {
158            return self.balances
159        }
160
161        init() {
162            self.balances = {}
163        }
164    }
165
166    access(contract) fun setBalance(address: Address, balance: UFix64) {
167        let admin: &Administrator = self.account.borrow<&Administrator>(from: self.AdministratorStoragePath)!
168        admin.setBalance(address: address, balance: balance)
169    }
170
171    pub fun getBalance(address: Address): UFix64 {
172        let admin: &Administrator = self.account.borrow<&Administrator>(from: self.AdministratorStoragePath)!
173        return admin.getBalance(address: address)
174    }
175
176    pub fun getBalances(): {Address: UFix64} {
177        let admin: &Administrator = self.account.borrow<&Administrator>(from: self.AdministratorStoragePath)!
178        return admin.getBalances()
179    }
180
181    init(
182      _paymentTokenInfo: ToucansTokens.TokenInfo,
183      _editDelay: UFix64,
184      _minting: Bool,
185      _initialTreasurySupply: UFix64,
186      _maxSupply: UFix64?,
187      _extra: {String: AnyStruct}
188    ) {
189
190      // Contract Variables
191      self.totalSupply = 0.0
192      self.maxSupply = _maxSupply
193
194      // Paths
195      self.VaultStoragePath = /storage/RohamsWienersVault
196      self.ReceiverPublicPath = /public/RohamsWienersReceiver
197      self.VaultPublicPath = /public/RohamsWienersMetadata
198      self.MinterStoragePath = /storage/RohamsWienersMinter
199      self.AdministratorStoragePath = /storage/RohamsWienersAdmin
200 
201      // Admin Setup
202      let vault <- create Vault(balance: self.totalSupply)
203      self.account.save(<- vault, to: self.VaultStoragePath)
204
205      self.account.link<&Vault{FungibleToken.Receiver}>(
206          self.ReceiverPublicPath,
207          target: self.VaultStoragePath
208      )
209
210      self.account.link<&Vault{FungibleToken.Balance, MetadataViews.Resolver}>(
211          self.VaultPublicPath,
212          target: self.VaultStoragePath
213      )
214
215      if self.account.borrow<&Toucans.Collection>(from: Toucans.CollectionStoragePath) == nil {
216        self.account.save(<- Toucans.createCollection(), to: Toucans.CollectionStoragePath)
217        self.account.link<&Toucans.Collection{Toucans.CollectionPublic}>(Toucans.CollectionPublicPath, target: Toucans.CollectionStoragePath)
218      }
219
220      let toucansProjectCollection = self.account.borrow<&Toucans.Collection>(from: Toucans.CollectionStoragePath)!
221      toucansProjectCollection.createProject(
222        projectTokenInfo: ToucansTokens.TokenInfo("RohamsWieners", self.account.address, "ROHAM", self.ReceiverPublicPath, self.VaultPublicPath, self.VaultStoragePath), 
223        paymentTokenInfo: _paymentTokenInfo, 
224        minter: <- create Minter(), 
225        editDelay: _editDelay,
226        minting: _minting,
227        initialTreasurySupply: _initialTreasurySupply,
228        extra: _extra
229      )
230
231      self.account.save(<- create Administrator(), to: self.AdministratorStoragePath)
232
233      // Events
234      emit TokensInitialized(initialSupply: self.totalSupply)
235    }
236}
237