Smart Contract

FiatToken

A.b19436aae4d94622.FiatToken

Deployed

1d ago
Feb 25, 2026, 01:57:45 AM UTC

Dependents

2317 imports
1import Crypto
2import FungibleToken from 0xf233dcee88fe0abe
3import OnChainMultiSig from 0x220c1b4155f86f2f
4
5pub contract FiatToken: FungibleToken {
6
7    // ------- FiatToken Events -------
8
9    // Admin events    
10    pub event AdminCreated(resourceId: UInt64)
11    pub event AdminChanged(address: Address, resourceId: UInt64)
12
13    // Owner events
14    pub event OwnerCreated(resourceId: UInt64)
15    pub event OwnerChanged(address: Address, resourceId: UInt64)
16
17    // MasterMinter events
18    pub event MasterMinterCreated(resourceId: UInt64)
19    pub event MasterMinterChanged(address: Address, resourceId: UInt64)
20    
21    // Pauser events
22    pub event Paused()
23    pub event Unpaused()
24    pub event PauserCreated(resourceId: UInt64)
25    pub event PauserChanged(address: Address, resourceId: UInt64)
26    
27    // Blocklister events
28    pub event Blocklisted(resourceId: UInt64)
29    pub event Unblocklisted(resourceId: UInt64)
30    pub event BlocklisterCreated(resourceId: UInt64)
31    pub event BlocklisterChanged(address: Address, resourceId: UInt64)
32    
33    // FiatToken.Vault events
34    pub event NewVault(resourceId: UInt64)
35    pub event DestroyVault(resourceId: UInt64)
36    pub event FiatTokenWithdrawn(amount: UFix64, from: UInt64)
37    pub event FiatTokenDeposited(amount: UFix64, to: UInt64)
38
39    // Minting events
40    pub event MinterCreated(resourceId: UInt64)
41    pub event MinterControllerCreated(resourceId: UInt64)
42    pub event Mint(minter: UInt64, amount: UFix64)
43    pub event Burn(minter: UInt64, amount: UFix64)
44    pub event MinterConfigured(controller: UInt64, minter: UInt64, allowance: UFix64)
45    pub event MinterRemoved(controller: UInt64, minter: UInt64)
46    pub event ControllerConfigured(controller: UInt64, minter: UInt64)
47    pub event ControllerRemoved(controller: UInt64)
48
49
50    // ------- FungibleToken Events -------
51
52    pub event TokensInitialized(initialSupply: UFix64)
53    pub event TokensWithdrawn(amount: UFix64, from: Address?)
54    pub event TokensDeposited(amount: UFix64, to: Address?)
55
56
57    // ------- FiatToken Paths -------
58
59    pub let VaultStoragePath: StoragePath
60    pub let VaultBalancePubPath: PublicPath
61    pub let VaultUUIDPubPath: PublicPath
62    pub let VaultReceiverPubPath: PublicPath
63
64    pub let BlocklistExecutorStoragePath: StoragePath
65
66    pub let BlocklisterStoragePath: StoragePath
67    pub let BlocklisterCapReceiverPubPath: PublicPath
68    pub let BlocklisterUUIDPubPath: PublicPath
69    pub let BlocklisterPubSigner: PublicPath
70
71    pub let PauseExecutorStoragePath: StoragePath
72
73    pub let PauserStoragePath: StoragePath
74    pub let PauserCapReceiverPubPath: PublicPath
75    pub let PauserUUIDPubPath: PublicPath
76    pub let PauserPubSigner: PublicPath
77
78    pub let AdminExecutorStoragePath: StoragePath
79
80    pub let AdminStoragePath: StoragePath
81    pub let AdminCapReceiverPubPath: PublicPath
82    pub let AdminUUIDPubPath: PublicPath
83    pub let AdminPubSigner: PublicPath
84
85    pub let OwnerExecutorStoragePath: StoragePath
86
87    pub let OwnerStoragePath: StoragePath
88    pub let OwnerCapReceiverPubPath: PublicPath
89    pub let OwnerUUIDPubPath: PublicPath
90    pub let OwnerPubSigner: PublicPath
91
92    pub let MasterMinterExecutorStoragePath: StoragePath
93
94    pub let MasterMinterStoragePath: StoragePath
95    pub let MasterMinterCapReceiverPubPath: PublicPath
96    pub let MasterMinterUUIDPubPath: PublicPath
97    pub let MasterMinterPubSigner: PublicPath
98
99    pub let MinterControllerStoragePath: StoragePath
100    pub let MinterControllerUUIDPubPath: PublicPath
101    pub let MinterControllerPubSigner: PublicPath
102
103    pub let MinterStoragePath: StoragePath
104    pub let MinterUUIDPubPath: PublicPath
105
106
107    // ------- FiatToken States / Variables -------
108
109    pub let name: String
110    pub var version: String
111    // Set to true if the contract is paused
112    pub var paused: Bool
113    // The token total supply
114    pub var totalSupply: UFix64
115    // Blocked resources dictionary {resourceId: Block Height}
116    access(contract) let blocklist: {UInt64: UInt64}
117    // Managed minters dictionary {MinterController: Minter}
118    access(contract) let managedMinters: {UInt64: UInt64}
119    // Minter allowance dictionary {Minter: Allowance}
120    access(contract) let minterAllowances: { UInt64: UFix64}
121    
122
123    // ------- FiatToken Interfaces  -------
124
125    pub resource interface ResourceId {
126        pub fun UUID(): UInt64
127    }
128
129    pub resource interface AdminCapReceiver {
130        pub fun setAdminCap(cap: Capability<&AdminExecutor>)
131    }
132
133    pub resource interface OwnerCapReceiver {
134        pub fun setOwnerCap(cap: Capability<&OwnerExecutor>)
135    }
136
137    pub resource interface MasterMinterCapReceiver {
138        pub fun setMasterMinterCap(cap: Capability<&MasterMinterExecutor>)
139    }
140
141    pub resource interface BlocklisterCapReceiver {
142        pub fun setBlocklistCap(cap: Capability<&BlocklistExecutor>)
143    }
144
145    pub resource interface PauseCapReceiver {
146        pub fun setPauseCap(cap: Capability<&PauseExecutor>)
147    }
148
149    
150    // ------- Path linking -------
151
152    access(contract) fun linkAdminExec(_ newPrivPath: PrivatePath): Capability<&AdminExecutor>  {
153        return self.account.link<&AdminExecutor>(newPrivPath, target: FiatToken.AdminExecutorStoragePath)
154            ?? panic("could not create new AdminExecutor capability link")
155    }
156
157    access(contract) fun linkOwnerExec(_ newPrivPath: PrivatePath): Capability<&OwnerExecutor>  {
158        return self.account.link<&OwnerExecutor>(newPrivPath, target: FiatToken.OwnerExecutorStoragePath)
159            ?? panic("could not create new OwnerExecutor capability link")
160    }
161
162    access(contract) fun linkMasterMinterExec(_ newPrivPath: PrivatePath): Capability<&MasterMinterExecutor>  {
163        return self.account.link<&MasterMinterExecutor>(newPrivPath, target: FiatToken.MasterMinterExecutorStoragePath)
164            ?? panic("could not create new MasterMinterExecutor capability link")
165    }
166
167    access(contract) fun linkBlocklistExec(_ newPrivPath: PrivatePath): Capability<&FiatToken.BlocklistExecutor>  {
168        return self.account.link<&BlocklistExecutor>(newPrivPath, target: FiatToken.BlocklistExecutorStoragePath)
169            ?? panic("could not create new BlocklistExecutor capability link")
170    }
171
172    access(contract) fun linkPauserExec(_ newPrivPath: PrivatePath): Capability<&FiatToken.PauseExecutor>  {
173        return self.account.link<&FiatToken.PauseExecutor>(newPrivPath, target: FiatToken.PauseExecutorStoragePath)
174            ?? panic("could not create new PauseExecutor capability link")
175    }
176
177    // ------- Path unlinking -------
178
179    access(contract) fun unlinkPriv(_ privPath: PrivatePath) {
180        self.account.unlink(privPath)
181    }
182
183
184    // ------- FiatToken Resources -------
185
186    pub resource Vault:
187        ResourceId,
188        FungibleToken.Provider,
189        FungibleToken.Receiver,
190        FungibleToken.Balance {
191        
192        pub var balance: UFix64
193
194        pub fun withdraw(amount: UFix64): @FungibleToken.Vault {
195            pre {
196                !FiatToken.paused: "FiatToken contract paused"
197                FiatToken.blocklist[self.uuid] == nil: "Vault Blocklisted"
198            }
199            self.balance = self.balance - amount
200            emit FiatTokenWithdrawn(amount: amount, from: self.uuid)
201            emit TokensWithdrawn(amount: amount, from: self.owner?.address)
202            return <-create Vault(balance: amount)
203        }
204
205        pub fun deposit(from: @FungibleToken.Vault) {
206            pre {
207                !FiatToken.paused: "FiatToken contract paused"
208                FiatToken.blocklist[from.uuid] == nil: "Receiving Vault Blocklisted"
209                FiatToken.blocklist[self.uuid] == nil: "Vault Blocklisted"
210            }
211            let vault <- from as! @FiatToken.Vault
212            self.balance = self.balance + vault.balance
213            emit FiatTokenDeposited(amount: vault.balance, to: self.uuid)
214            emit TokensDeposited(amount: vault.balance, to: self.owner?.address)
215            vault.balance = 0.0
216            destroy vault
217        }
218
219        pub fun UUID(): UInt64 {
220            return self.uuid
221        }
222
223        access(contract) fun burn() {
224            pre {
225                self.balance > 0.0: "Cannot burn USDC Vault with zero balance"
226            }
227            FiatToken.totalSupply = FiatToken.totalSupply - self.balance
228            self.balance = 0.0
229        }
230
231        destroy() {
232            pre {
233                self.balance == 0.0: "Cannot destroy USDC Vault with non-zero balance"
234            }
235            emit DestroyVault(resourceId: self.uuid)
236        }
237
238        init(balance: UFix64) {
239            self.balance = balance
240        }
241
242    }
243
244    pub resource AdminExecutor {
245
246        access(self) var currentCapPath: PrivatePath?
247
248        pub fun upgradeContract(name: String, code: [UInt8], version: String) {
249            FiatToken.upgradeContract(name: name, code: code, version: version)
250        }
251
252        pub fun changeAdmin(to: Address, newPath: PrivatePath) {
253            let newCap = FiatToken.linkAdminExec(newPath)
254            let receiver = getAccount(to)
255                .getCapability<&Admin{AdminCapReceiver}>(FiatToken.AdminCapReceiverPubPath)
256                .borrow() ?? panic("could not borrow AdminCapReceiver capability")
257            let idRef = getAccount(to)
258                .getCapability<&Admin{ResourceId}>(FiatToken.AdminUUIDPubPath)
259                .borrow() ?? panic("could not borrow Admin ResourceId capability")
260            receiver.setAdminCap(cap: newCap)
261            if self.currentCapPath != nil {
262                FiatToken.unlinkPriv(self.currentCapPath!)
263            }
264            self.currentCapPath = newPath
265            emit AdminChanged(address: to, resourceId: idRef.UUID())
266        }
267
268        init () {
269            self.currentCapPath = nil
270        }
271
272    }
273
274    pub resource Admin: OnChainMultiSig.PublicSigner, ResourceId, AdminCapReceiver {
275
276        access(self) let multiSigManager: @OnChainMultiSig.Manager
277        access(self) var adminExecutorCapability: Capability<&AdminExecutor>?
278
279        pub fun setAdminCap(cap: Capability<&AdminExecutor>) {
280            pre {
281                self.adminExecutorCapability == nil: "Capability has already been set"
282                cap.borrow() != nil: "Invalid capability"
283            }
284            self.adminExecutorCapability = cap
285        }
286
287        // ------- OnChainMultiSig.PublicSigner interfaces -------
288
289        pub fun addNewPayload(payload: @OnChainMultiSig.PayloadDetails, publicKey: String, sig: [UInt8]) {
290            self.multiSigManager.addNewPayload(resourceId: self.uuid, payload: <-payload, publicKey: publicKey, sig: sig)
291        }
292
293        pub fun addPayloadSignature (txIndex: UInt64, publicKey: String, sig: [UInt8]) {
294            self.multiSigManager.addPayloadSignature(resourceId: self.uuid, txIndex: txIndex, publicKey: publicKey, sig: sig)
295        }
296
297        pub fun executeTx(txIndex: UInt64): @AnyResource? {
298            let p <- self.multiSigManager.readyForExecution(txIndex: txIndex) ?? panic ("no ready transaction payload at given txIndex")
299            switch p.method {
300                case "configureKey":
301                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
302                    let weight = p.getArg(i: 1)! as? UFix64 ?? panic ("cannot downcast weight")
303                    let sa = p.getArg(i: 2)! as? UInt8 ?? panic ("cannot downcast sig algo")
304                    self.multiSigManager.configureKeys(pks: [pubKey], kws: [weight], sa: [sa])
305                case "removeKey":
306                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
307                    self.multiSigManager.removeKeys(pks: [pubKey])
308                case "removePayload":
309                    let txIndex = p.getArg(i: 0)! as? UInt64 ?? panic ("cannot downcast txIndex")
310                    let payloadToRemove <- self.multiSigManager.removePayload(txIndex: txIndex)
311                    destroy(payloadToRemove)
312                case "upgradeContract":
313                    let name = p.getArg(i: 0)! as? String ?? panic ("cannot downcast contract name")
314                    let code = p.getArg(i: 1)! as? String ?? panic ("cannot downcast contract code")
315                    let version = p.getArg(i: 2)! as? String ?? panic ("cannot downcast contract version")
316                    let executor = self.adminExecutorCapability!.borrow() ?? panic("cannot borrow AdminExecutor capability")
317                    executor.upgradeContract(name: name, code: code.decodeHex(), version: version)
318                case "changeAdmin":
319                    let to = p.getArg(i: 0)! as? Address ?? panic("cannot downcast receiver address")
320                    let path = p.getArg(i: 1)! as? PrivatePath ?? panic("cannot downcast new link path")
321                    let executor = self.adminExecutorCapability!.borrow() ?? panic("cannot borrow AdminExecutor capability")
322                    executor.changeAdmin(to: to, newPath: path)
323                default:
324                    panic("Unknown transaction method")
325            }
326            destroy (p)
327            return nil
328        }
329
330        pub fun UUID(): UInt64 {
331            return self.uuid
332        }
333
334        pub fun getTxIndex(): UInt64 {
335            return self.multiSigManager.txIndex
336        }
337
338        pub fun getSignerKeys(): [String] {
339            return self.multiSigManager.getSignerKeys()
340        }
341
342        pub fun getSignerKeyAttr(publicKey: String): OnChainMultiSig.PubKeyAttr? {
343            return self.multiSigManager.getSignerKeyAttr(publicKey: publicKey)
344        }
345
346        destroy() {
347            destroy self.multiSigManager
348        }
349
350        init(pk: [String], pka: [OnChainMultiSig.PubKeyAttr]) {
351            self.multiSigManager <-  OnChainMultiSig.createMultiSigManager(publicKeys: pk, pubKeyAttrs: pka)
352            self.adminExecutorCapability = nil
353        }
354
355    }
356
357    pub resource OwnerExecutor {
358
359        access(self) var ownerCapPath: PrivatePath?
360        access(self) var masterMinterCapPath: PrivatePath?
361        access(self) var blocklisterCapPath: PrivatePath?
362        access(self) var pauserCapPath: PrivatePath?
363
364        pub fun reassignOwner(to: Address, newPath: PrivatePath) {
365            let newCap = FiatToken.linkOwnerExec(newPath)
366            let receiver = getAccount(to)
367                .getCapability<&Owner{OwnerCapReceiver}>(FiatToken.OwnerCapReceiverPubPath)
368                .borrow() ?? panic("could not borrow the OwnerCapReceiver capability")
369            let idRef = getAccount(to)
370                .getCapability<&Owner{ResourceId}>(FiatToken.OwnerUUIDPubPath)
371                .borrow() ?? panic("could not borrow the Owner ResourceId capability")
372            receiver.setOwnerCap(cap: newCap)
373            if self.ownerCapPath != nil {
374                FiatToken.unlinkPriv(self.ownerCapPath!)
375            }
376            self.ownerCapPath = newPath
377            emit OwnerChanged(address: to, resourceId: idRef.UUID())
378        }
379
380        pub fun reassignMasterMinter(to: Address, newPath: PrivatePath) {
381            let newCap = FiatToken.linkMasterMinterExec(newPath)
382            let receiver = getAccount(to)
383                .getCapability<&MasterMinter{MasterMinterCapReceiver}>(FiatToken.MasterMinterCapReceiverPubPath)
384                .borrow() ?? panic("could not borrow the MasterMinterCapReceiver capability")
385            let idRef = getAccount(to)
386                .getCapability<&MasterMinter{ResourceId}>(FiatToken.MasterMinterUUIDPubPath)
387                .borrow() ?? panic("could not borrow the MasterMinter ResourceId capability")    
388            receiver.setMasterMinterCap(cap: newCap)
389            if self.masterMinterCapPath != nil {
390                FiatToken.unlinkPriv(self.masterMinterCapPath!)
391            }
392            self.masterMinterCapPath = newPath
393            emit MasterMinterChanged(address: to, resourceId: idRef.UUID())
394        }
395
396        pub fun reassignBlocklister(to: Address, newPath: PrivatePath) {
397            let newCap = FiatToken.linkBlocklistExec(newPath)
398            let receiver = getAccount(to)
399                .getCapability<&Blocklister{BlocklisterCapReceiver}>(FiatToken.BlocklisterCapReceiverPubPath)
400                .borrow() ?? panic("could not borrow the BlocklisterCapReceiver capability ")
401            let idRef = getAccount(to)
402                .getCapability<&Blocklister{ResourceId}>(FiatToken.BlocklisterUUIDPubPath)
403                .borrow() ?? panic("could not borrow the Blocklister ResourceId capability")  
404            receiver.setBlocklistCap(cap: newCap)
405            if self.blocklisterCapPath != nil {
406                FiatToken.unlinkPriv(self.blocklisterCapPath!)
407            }
408            self.blocklisterCapPath = newPath
409            emit BlocklisterChanged(address: to, resourceId: idRef.UUID())
410        }
411
412        pub fun reassignPauser(to: Address, newPath: PrivatePath) {
413            let newCap = FiatToken.linkPauserExec(newPath)
414            let receiver = getAccount(to)
415                .getCapability<&Pauser{PauseCapReceiver}>(FiatToken.PauserCapReceiverPubPath)
416                .borrow() ?? panic("could not borrow the PauseCapReceiver capability")
417            let idRef = getAccount(to)
418                .getCapability<&Pauser{ResourceId}>(FiatToken.PauserUUIDPubPath)
419                .borrow() ?? panic("could not borrow the Pauser ResourceId capability") 
420            receiver.setPauseCap(cap: newCap)
421            if self.pauserCapPath != nil {
422                FiatToken.unlinkPriv(self.pauserCapPath!)
423            }
424            self.pauserCapPath = newPath
425            emit PauserChanged(address: to, resourceId: idRef.UUID())
426        }
427
428        init() {
429            self.ownerCapPath = nil
430            self.masterMinterCapPath = nil
431            self.blocklisterCapPath = nil
432            self.pauserCapPath = nil
433        }
434
435    }
436
437    pub resource Owner: OnChainMultiSig.PublicSigner, ResourceId, OwnerCapReceiver {
438
439        access(self) let multiSigManager: @OnChainMultiSig.Manager
440        access(self) var ownerExecutorCapability: Capability<&OwnerExecutor>?
441
442        pub fun setOwnerCap(cap: Capability<&OwnerExecutor>) {
443            pre {
444                self.ownerExecutorCapability == nil: "Capability has already been set"
445                cap.borrow() != nil: "Invalid capability"
446            }
447            self.ownerExecutorCapability = cap
448        }
449
450        // ------- OnChainMultiSig.PublicSigner interfaces -------
451
452        pub fun addNewPayload(payload: @OnChainMultiSig.PayloadDetails, publicKey: String, sig: [UInt8]) {
453            self.multiSigManager.addNewPayload(resourceId: self.uuid, payload: <-payload, publicKey: publicKey, sig: sig)
454        }
455
456        pub fun addPayloadSignature (txIndex: UInt64, publicKey: String, sig: [UInt8]) {
457            self.multiSigManager.addPayloadSignature(resourceId: self.uuid, txIndex: txIndex, publicKey: publicKey, sig: sig)
458        }
459
460        pub fun executeTx(txIndex: UInt64): @AnyResource? {
461            let p <- self.multiSigManager.readyForExecution(txIndex: txIndex) ?? panic ("no ready transaction payload at given txIndex")
462            switch p.method {
463                case "configureKey":
464                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
465                    let weight = p.getArg(i: 1)! as? UFix64 ?? panic ("cannot downcast weight")
466                    let sa = p.getArg(i: 2)! as? UInt8 ?? panic ("cannot downcast sig algo")
467                    self.multiSigManager.configureKeys(pks: [pubKey], kws: [weight], sa: [sa])
468                case "removeKey":
469                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
470                    self.multiSigManager.removeKeys(pks: [pubKey])
471                case "reassignOwner":
472                    let to = p.getArg(i: 0)! as? Address ?? panic("cannot downcast receiver address")
473                    let path = p.getArg(i: 1)! as? PrivatePath ?? panic("cannot downcast new link path")
474                    let executor = self.ownerExecutorCapability!.borrow() ?? panic("cannot borrow OwnerExecutor capability")
475                    executor.reassignOwner(to: to, newPath: path)
476                case "reassignMasterMinter":
477                    let to = p.getArg(i: 0)! as? Address ?? panic("cannot downcast receiver address")
478                    let path = p.getArg(i: 1)! as? PrivatePath ?? panic("cannot downcast new link path")
479                    let executor = self.ownerExecutorCapability!.borrow() ?? panic("cannot borrow OwnerExecutor capability")
480                    executor.reassignMasterMinter(to: to, newPath: path)
481                case "reassignBlocklister":
482                    let to = p.getArg(i: 0)! as? Address ?? panic("cannot downcast receiver address")
483                    let path = p.getArg(i: 1)! as? PrivatePath ?? panic("cannot downcast new link path")
484                    let executor = self.ownerExecutorCapability!.borrow() ?? panic("cannot borrow OwnerExecutor capability")
485                    executor.reassignBlocklister(to: to, newPath: path)
486                case "reassignPauser":
487                    let to = p.getArg(i: 0)! as? Address ?? panic("cannot downcast receiver address")
488                    let path = p.getArg(i: 1)! as? PrivatePath ?? panic("cannot downcast new link path")
489                    let executor = self.ownerExecutorCapability!.borrow() ?? panic("cannot borrow OwnerExecutor capability")
490                    executor.reassignPauser(to: to, newPath: path)
491                default:
492                    panic("Unknown transaction method")
493            }
494            destroy (p)
495            return nil
496        }
497
498        pub fun UUID(): UInt64 {
499            return self.uuid
500        }
501
502        pub fun getTxIndex(): UInt64 {
503            return self.multiSigManager.txIndex
504        }
505
506        pub fun getSignerKeys(): [String] {
507            return self.multiSigManager.getSignerKeys()
508        }
509        pub fun getSignerKeyAttr(publicKey: String): OnChainMultiSig.PubKeyAttr? {
510            return self.multiSigManager.getSignerKeyAttr(publicKey: publicKey)
511        }
512
513        destroy() {
514            destroy self.multiSigManager
515        }
516
517        init(pk: [String], pka: [OnChainMultiSig.PubKeyAttr]) {
518            self.multiSigManager <-  OnChainMultiSig.createMultiSigManager(publicKeys: pk, pubKeyAttrs: pka)
519            self.ownerExecutorCapability = nil
520        }
521    }
522
523    pub resource MasterMinterExecutor {
524
525        pub fun configureMinterController(minter: UInt64, minterController: UInt64) {
526            // Overwrite the minter if the MinterController is already configured (a MinterController can only control 1 minter)
527            FiatToken.managedMinters.insert(key: minterController, minter)
528            emit ControllerConfigured(controller: minterController, minter: minter)
529        }
530
531        pub fun removeMinterController(minterController: UInt64){
532            pre {
533                FiatToken.managedMinters.containsKey(minterController): "cannot remove unknown MinterController"
534            }
535            FiatToken.managedMinters.remove(key: minterController)
536            emit ControllerRemoved(controller: minterController)
537        }
538    }
539
540    pub resource MasterMinter: ResourceId, OnChainMultiSig.PublicSigner, MasterMinterCapReceiver {
541
542        access(self) let multiSigManager: @OnChainMultiSig.Manager
543        access(self) var masterMinterExecutorCapability: Capability<&MasterMinterExecutor>?
544
545        pub fun setMasterMinterCap(cap: Capability<&MasterMinterExecutor>) {
546            pre {
547                self.masterMinterExecutorCapability == nil: "Capability has already been set"
548                cap.borrow() != nil: "Invalid capability"
549            }
550            self.masterMinterExecutorCapability = cap
551        }
552
553        // ------- OnChainMultiSig.PublicSigner interfaces -------
554
555        pub fun addNewPayload(payload: @OnChainMultiSig.PayloadDetails, publicKey: String, sig: [UInt8]) {
556            self.multiSigManager.addNewPayload(resourceId: self.uuid, payload: <-payload, publicKey: publicKey, sig: sig)
557        }
558
559        pub fun addPayloadSignature (txIndex: UInt64, publicKey: String, sig: [UInt8]) {
560            self.multiSigManager.addPayloadSignature(resourceId: self.uuid, txIndex: txIndex, publicKey: publicKey, sig: sig)
561        }
562
563        pub fun executeTx(txIndex: UInt64): @AnyResource? {
564            let p <- self.multiSigManager.readyForExecution(txIndex: txIndex) ?? panic ("no ready transaction payload at given txIndex")
565            switch p.method {
566                case "configureKey":
567                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
568                    let weight = p.getArg(i: 1)! as? UFix64 ?? panic ("cannot downcast weight")
569                    let sa = p.getArg(i: 2)! as? UInt8 ?? panic ("cannot downcast sig algo")
570                    self.multiSigManager.configureKeys(pks: [pubKey], kws: [weight], sa: [sa])
571                case "removeKey":
572                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
573                    self.multiSigManager.removeKeys(pks: [pubKey])
574                case "configureMinterController":
575                    let m = p.getArg(i: 0)! as? UInt64 ?? panic ("cannot downcast minter id")
576                    let mc = p.getArg(i: 1)! as? UInt64 ?? panic ("cannot downcast MinterController id")
577                    let executor = self.masterMinterExecutorCapability!.borrow() ?? panic("cannot borrow MasterMinterExecutor capability")
578                    executor.configureMinterController(minter: m, minterController: mc)
579                case "removeMinterController":
580                    let mc = p.getArg(i: 0)! as? UInt64 ?? panic ("cannot downcast MinterController id")
581                    let executor = self.masterMinterExecutorCapability!.borrow() ?? panic("cannot borrow MasterMinterExecutor capability")
582                    executor.removeMinterController(minterController: mc)
583                default:
584                    panic("Unknown transaction method")
585            }
586            destroy (p)
587            return nil
588        }
589
590        pub fun UUID(): UInt64 {
591            return self.uuid
592        }
593
594        pub fun getTxIndex(): UInt64 {
595            return self.multiSigManager.txIndex
596        }
597
598        pub fun getSignerKeys(): [String] {
599            return self.multiSigManager.getSignerKeys()
600        }
601        pub fun getSignerKeyAttr(publicKey: String): OnChainMultiSig.PubKeyAttr? {
602            return self.multiSigManager.getSignerKeyAttr(publicKey: publicKey)
603        }
604
605        destroy() {
606            destroy self.multiSigManager
607        }
608
609        init(pk: [String], pka: [OnChainMultiSig.PubKeyAttr]) {
610            self.multiSigManager <-  OnChainMultiSig.createMultiSigManager(publicKeys: pk, pubKeyAttrs: pka)
611            self.masterMinterExecutorCapability = nil
612        }
613    }
614
615    pub resource MinterController: ResourceId, OnChainMultiSig.PublicSigner  {
616
617        access(self) let multiSigManager: @OnChainMultiSig.Manager
618
619        pub fun UUID(): UInt64 {
620            return self.uuid
621        }
622
623        pub fun configureMinterAllowance(allowance: UFix64) {
624            let managedMinter = FiatToken.managedMinters[self.uuid] ?? panic("MinterController does not manage any minters")
625            FiatToken.minterAllowances[managedMinter] = allowance
626            emit MinterConfigured(controller: self.uuid, minter: managedMinter, allowance: allowance)
627        }
628
629        pub fun increaseMinterAllowance(increment: UFix64) {
630            let managedMinter = FiatToken.managedMinters[self.uuid] ?? panic("MinterController does not manage any minters")
631            let allowance = FiatToken.minterAllowances[managedMinter] ?? 0.0
632            let newAllowance = allowance.saturatingAdd(increment)
633            self.configureMinterAllowance(allowance: newAllowance)
634        }
635
636        pub fun decreaseMinterAllowance(decrement: UFix64) {
637            let managedMinter = FiatToken.managedMinters[self.uuid] ?? panic("MinterController does not manage any minters")
638            let allowance = FiatToken.minterAllowances[managedMinter] ?? panic("Cannot decrease nil MinterAllowance")
639            let newAllowance = allowance!.saturatingSubtract(decrement)
640            self.configureMinterAllowance(allowance: newAllowance)
641        }
642
643        pub fun removeMinter() {
644            let managedMinter = FiatToken.managedMinters[self.uuid] ?? panic("MinterController does not manage any minters")
645            assert(FiatToken.minterAllowances.containsKey(managedMinter), message: "cannot remove unknown Minter")
646            FiatToken.minterAllowances.remove(key: managedMinter)
647            emit MinterRemoved(controller: self.uuid, minter: managedMinter)
648        }
649
650        // ------- OnChainMultiSig.PublicSigner interfaces -------
651
652        pub fun addNewPayload(payload: @OnChainMultiSig.PayloadDetails, publicKey: String, sig: [UInt8]) {
653            self.multiSigManager.addNewPayload(resourceId: self.uuid, payload: <-payload, publicKey: publicKey, sig: sig)
654        }
655
656        pub fun addPayloadSignature (txIndex: UInt64, publicKey: String, sig: [UInt8]) {
657            self.multiSigManager.addPayloadSignature(resourceId: self.uuid, txIndex: txIndex, publicKey: publicKey, sig: sig)
658        }
659
660        pub fun executeTx(txIndex: UInt64): @AnyResource? {
661            let p <- self.multiSigManager.readyForExecution(txIndex: txIndex) ?? panic ("no ready transaction payload at given txIndex")
662            switch p.method {
663                case "configureKey":
664                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
665                    let weight = p.getArg(i: 1)! as? UFix64 ?? panic ("cannot downcast weight")
666                    let sa = p.getArg(i: 2)! as? UInt8 ?? panic ("cannot downcast sig algo")
667                    self.multiSigManager.configureKeys(pks: [pubKey], kws: [weight], sa: [sa])
668                case "removeKey":
669                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
670                    self.multiSigManager.removeKeys(pks: [pubKey])
671                case "configureMinterAllowance":
672                    let allowance = p.getArg(i: 0)! as? UFix64 ?? panic ("cannot downcast allowance amount")
673                    self.configureMinterAllowance(allowance: allowance)
674                case "increaseMinterAllowance":
675                    let increment = p.getArg(i: 0)! as? UFix64 ?? panic ("cannot downcast increment amount")
676                    self.increaseMinterAllowance(increment: increment)
677                case "decreaseMinterAllowance":
678                    let decrement = p.getArg(i: 0)! as? UFix64 ?? panic ("cannot downcast decrement amount")
679                    self.decreaseMinterAllowance(decrement: decrement)
680                case "removeMinter":
681                    self.removeMinter()
682                default:
683                    panic("Unknown transaction method")
684            }
685            destroy (p)
686            return nil
687        }
688
689        pub fun getTxIndex(): UInt64 {
690            return self.multiSigManager.txIndex
691        }
692
693        pub fun getSignerKeys(): [String] {
694            return self.multiSigManager.getSignerKeys()
695        }
696
697        pub fun getSignerKeyAttr(publicKey: String): OnChainMultiSig.PubKeyAttr? {
698            return self.multiSigManager.getSignerKeyAttr(publicKey: publicKey)
699        }
700
701        destroy() {
702            destroy self.multiSigManager
703        }
704
705        init(pk: [String], pka: [OnChainMultiSig.PubKeyAttr]) {
706            self.multiSigManager <-  OnChainMultiSig.createMultiSigManager(publicKeys: pk, pubKeyAttrs: pka)
707        }
708    }
709
710    pub resource Minter: ResourceId {
711
712        pub fun mint(amount: UFix64): @FungibleToken.Vault{
713            pre {
714                !FiatToken.paused: "FiatToken contract paused"
715                FiatToken.blocklist[self.uuid] == nil: "Minter Blocklisted"
716                FiatToken.minterAllowances.containsKey(self.uuid): "minter does not have allowance set"
717            }
718            let mintAllowance = FiatToken.minterAllowances[self.uuid]!
719            assert(mintAllowance >= amount, message: "insufficient mint allowance")
720            FiatToken.minterAllowances.insert(key: self.uuid, mintAllowance - amount)
721            let newTotalSupply = FiatToken.totalSupply + amount
722            FiatToken.totalSupply = newTotalSupply
723
724            emit Mint(minter: self.uuid, amount: amount)
725            return <-create Vault(balance: amount)
726        }
727
728        pub fun burn(vault: @FungibleToken.Vault) {
729            pre {
730                !FiatToken.paused: "FiatToken contract paused"
731                FiatToken.blocklist[self.uuid] == nil: "Minter Blocklisted"
732                FiatToken.minterAllowances.containsKey(self.uuid): "minter is not configured"
733            }
734            let toBurn <- vault as! @FiatToken.Vault
735            let amount = toBurn.balance
736
737            assert(FiatToken.totalSupply >= amount, message: "burning more than total supply")
738
739            // This function updates FiatToken.totalSupply and sets the Vault's value to 0.0
740            toBurn.burn()
741            // Destroys the now empty Vault
742            destroy toBurn
743            emit Burn(minter: self.uuid, amount: amount)
744        }
745
746        pub fun UUID(): UInt64 {
747            return self.uuid
748        }
749    }
750
751    pub resource BlocklistExecutor {
752        
753        pub fun blocklist(resourceId: UInt64){
754            let block = getCurrentBlock()
755            FiatToken.blocklist.insert(key: resourceId, block.height)
756            emit Blocklisted(resourceId: resourceId)
757        }
758
759        pub fun unblocklist(resourceId: UInt64){
760            FiatToken.blocklist.remove(key: resourceId)
761            emit Unblocklisted(resourceId: resourceId)
762        }
763    }
764
765    pub resource Blocklister: ResourceId, BlocklisterCapReceiver, OnChainMultiSig.PublicSigner {
766
767        access(self) var blocklistCap: Capability<&BlocklistExecutor>?
768        access(self) let multiSigManager: @OnChainMultiSig.Manager
769
770        pub fun blocklist(resourceId: UInt64){
771            post {
772                FiatToken.blocklist.containsKey(resourceId): "Resource not blocklisted"
773            }
774            self.blocklistCap!.borrow()!.blocklist(resourceId: resourceId)
775        }
776
777        pub fun unblocklist(resourceId: UInt64){
778            post {
779                !FiatToken.blocklist.containsKey(resourceId): "Resource still on blocklist"
780            }
781            self.blocklistCap!.borrow()!.unblocklist(resourceId: resourceId)
782        }
783
784        pub fun setBlocklistCap(cap: Capability<&BlocklistExecutor>){
785            pre {
786                self.blocklistCap == nil: "Capability has already been set"
787                cap.borrow() != nil: "Invalid BlocklistCap capability"
788            }
789            self.blocklistCap = cap
790        }
791
792        // ------- OnChainMultiSig.PublicSigner interfaces -------
793
794        pub fun addNewPayload(payload: @OnChainMultiSig.PayloadDetails, publicKey: String, sig: [UInt8]) {
795            self.multiSigManager.addNewPayload(resourceId: self.uuid, payload: <- payload, publicKey: publicKey, sig: sig)
796        }
797
798        pub fun addPayloadSignature (txIndex: UInt64, publicKey: String, sig: [UInt8]) {
799            self.multiSigManager.addPayloadSignature(resourceId: self.uuid, txIndex: txIndex, publicKey: publicKey, sig: sig)
800        }
801
802        pub fun executeTx(txIndex: UInt64): @AnyResource? {
803            let p <- self.multiSigManager.readyForExecution(txIndex: txIndex) ?? panic ("no ready transaction payload at given txIndex")
804            switch p.method {
805                case "configureKey":
806                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
807                    let weight = p.getArg(i: 1)! as? UFix64 ?? panic ("cannot downcast weight")
808                    let sa = p.getArg(i: 2)! as? UInt8 ?? panic ("cannot downcast sig algo")
809                    self.multiSigManager.configureKeys(pks: [pubKey], kws: [weight], sa: [sa])
810                case "removeKey":
811                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
812                    self.multiSigManager.removeKeys(pks: [pubKey])
813                case "blocklist":
814                    let resourceId = p.getArg(i: 0)! as? UInt64 ?? panic ("cannot downcast resourceId")
815                    self.blocklist(resourceId: resourceId)
816                case "unblocklist":
817                    let resourceId = p.getArg(i: 0)! as? UInt64 ?? panic ("cannot downcast resourceId")
818                    self.unblocklist(resourceId: resourceId)
819                default:
820                    panic("Unknown transaction method")
821            }
822            destroy(p)
823            return nil
824        }
825
826        pub fun UUID(): UInt64 {
827            return self.uuid
828        }
829
830        pub fun getTxIndex(): UInt64 {
831            return self.multiSigManager.txIndex
832        }
833
834        pub fun getSignerKeys(): [String] {
835            return self.multiSigManager.getSignerKeys()
836        }
837        pub fun getSignerKeyAttr(publicKey: String): OnChainMultiSig.PubKeyAttr? {
838            return self.multiSigManager.getSignerKeyAttr(publicKey: publicKey)
839        }
840
841        destroy() {
842            destroy self.multiSigManager
843        }
844
845        init(pk: [String], pka: [OnChainMultiSig.PubKeyAttr]) {
846            self.blocklistCap = nil
847            self.multiSigManager <-  OnChainMultiSig.createMultiSigManager(publicKeys: pk, pubKeyAttrs: pka)
848        }
849    }
850
851    pub resource PauseExecutor {
852
853        pub fun pause() {
854            FiatToken.paused = true
855            emit Paused()
856        }
857
858        pub fun unpause() {
859            FiatToken.paused = false
860            emit Unpaused()
861        }
862    }
863
864    pub resource Pauser: ResourceId, PauseCapReceiver, OnChainMultiSig.PublicSigner {
865        
866        access(self) var pauseCap:  Capability<&PauseExecutor>?
867        access(self) let multiSigManager: @OnChainMultiSig.Manager
868
869        pub fun setPauseCap(cap: Capability<&PauseExecutor>) {
870            pre {
871                self.pauseCap == nil: "Capability has already been set"
872                cap.borrow() != nil: "Invalid PauseCap capability"
873            }
874            self.pauseCap = cap
875        }
876
877        pub fun pause(){
878            let cap = self.pauseCap!.borrow()!
879            cap.pause()
880        }
881
882        pub fun unpause(){
883            let cap = self.pauseCap!.borrow()!
884            cap.unpause()
885        }
886
887        // ------- OnChainMultiSig.PublicSigner interfaces -------
888
889        pub fun addNewPayload(payload: @OnChainMultiSig.PayloadDetails, publicKey: String, sig: [UInt8]) {
890            self.multiSigManager.addNewPayload(resourceId: self.uuid, payload: <- payload, publicKey: publicKey, sig: sig)
891        }
892
893        pub fun addPayloadSignature (txIndex: UInt64, publicKey: String, sig: [UInt8]) {
894            self.multiSigManager.addPayloadSignature(resourceId: self.uuid, txIndex: txIndex, publicKey: publicKey, sig: sig)
895        }
896
897        pub fun executeTx(txIndex: UInt64): @AnyResource? {
898            let p <- self.multiSigManager.readyForExecution(txIndex: txIndex) ?? panic ("no ready transaction payload at given txIndex")
899            switch p.method {
900                case "configureKey":
901                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
902                    let weight = p.getArg(i: 1)! as? UFix64 ?? panic ("cannot downcast weight")
903                    let sa = p.getArg(i: 2)! as? UInt8 ?? panic ("cannot downcast sig algo")
904                    self.multiSigManager.configureKeys(pks: [pubKey], kws: [weight], sa: [sa])
905                case "removeKey":
906                    let pubKey = p.getArg(i: 0)! as? String ?? panic ("cannot downcast public key")
907                    self.multiSigManager.removeKeys(pks: [pubKey])
908                case "pause":
909                    self.pause()
910                case "unpause":
911                    self.unpause()
912                default:
913                    panic("Unknown transaction method")
914            }
915            destroy(p)
916            return nil
917        }
918
919        pub fun UUID(): UInt64 {
920            return self.uuid
921        }
922
923        pub fun getTxIndex(): UInt64 {
924            return self.multiSigManager.txIndex
925        }
926
927        pub fun getSignerKeys(): [String] {
928            return self.multiSigManager.getSignerKeys()
929        }
930
931        pub fun getSignerKeyAttr(publicKey: String): OnChainMultiSig.PubKeyAttr? {
932            return self.multiSigManager.getSignerKeyAttr(publicKey: publicKey)
933        }
934
935        destroy() {
936            destroy self.multiSigManager
937        }
938
939        init(pk: [String], pka: [OnChainMultiSig.PubKeyAttr]) {
940            self.pauseCap = nil
941            self.multiSigManager <-  OnChainMultiSig.createMultiSigManager(publicKeys: pk, pubKeyAttrs: pka)
942        }
943    }
944
945    // ------- FiatToken functions -------
946
947    pub fun createEmptyVault(): @Vault {
948        let r <-create Vault(balance: 0.0)
949        emit NewVault(resourceId: r.uuid)
950        return <-r
951    }
952
953    pub fun createNewAdmin(publicKeys: [String], pubKeyAttrs: [OnChainMultiSig.PubKeyAttr]): @Admin{
954        let admin <-create Admin(pk: publicKeys, pka: pubKeyAttrs)
955        emit AdminCreated(resourceId: admin.uuid)
956        return <- admin
957    }
958
959    pub fun createNewOwner(publicKeys: [String], pubKeyAttrs: [OnChainMultiSig.PubKeyAttr]): @Owner{
960        let owner <-create Owner(pk: publicKeys, pka: pubKeyAttrs)
961        emit OwnerCreated(resourceId: owner.uuid)
962        return <- owner
963    }
964
965    pub fun createNewPauser(publicKeys: [String], pubKeyAttrs: [OnChainMultiSig.PubKeyAttr]): @Pauser{
966        let pauser <-create Pauser(pk: publicKeys, pka: pubKeyAttrs)
967        emit PauserCreated(resourceId: pauser.uuid)
968        return <- pauser
969    }
970
971    pub fun createNewMasterMinter(publicKeys: [String], pubKeyAttrs: [OnChainMultiSig.PubKeyAttr]): @MasterMinter{
972        let masterMinter <- create MasterMinter(pk: publicKeys, pka: pubKeyAttrs)
973        emit MasterMinterCreated(resourceId: masterMinter.uuid)
974        return <- masterMinter
975    }
976
977    pub fun createNewMinterController(publicKeys: [String], pubKeyAttrs: [OnChainMultiSig.PubKeyAttr]): @MinterController{
978        let minterController <- create MinterController(pk: publicKeys, pka: pubKeyAttrs)
979        emit MinterControllerCreated(resourceId: minterController.uuid)
980        return <- minterController
981    }
982
983    pub fun createNewMinter(): @Minter{
984        let minter <- create Minter()
985        emit MinterCreated(resourceId: minter.uuid)
986        return <- minter
987    }
988
989    pub fun createNewBlocklister(publicKeys: [String], pubKeyAttrs: [OnChainMultiSig.PubKeyAttr]): @Blocklister{
990        let blocklister <-create Blocklister(pk: publicKeys, pka: pubKeyAttrs)
991        emit BlocklisterCreated(resourceId: blocklister.uuid)
992        return <-blocklister
993    }
994
995    pub fun getBlocklist(resourceId: UInt64): UInt64?{
996        return FiatToken.blocklist[resourceId]
997    }
998
999    pub fun getManagedMinter(resourceId: UInt64): UInt64?{
1000        return FiatToken.managedMinters[resourceId]
1001    }
1002
1003    pub fun getMinterAllowance(resourceId: UInt64): UFix64?{
1004        return FiatToken.minterAllowances[resourceId]
1005    }
1006
1007    access(self) fun upgradeContract( name: String, code: [UInt8], version: String,) {
1008        self.account.contracts.update__experimental(name: name, code: code)
1009        self.version = version
1010    }
1011
1012    // ------- FiatToken Initializer -------
1013    init(
1014        contractAccount: AuthAccount,
1015        VaultStoragePath: StoragePath,
1016        VaultBalancePubPath: PublicPath,
1017        VaultUUIDPubPath: PublicPath,
1018        VaultReceiverPubPath: PublicPath,
1019        BlocklistExecutorStoragePath: StoragePath,
1020        BlocklisterStoragePath: StoragePath,
1021        BlocklisterCapReceiverPubPath: PublicPath,
1022        BlocklisterUUIDPubPath: PublicPath,
1023        BlocklisterPubSigner: PublicPath,
1024        PauseExecutorStoragePath: StoragePath,
1025        PauserStoragePath: StoragePath,
1026        PauserCapReceiverPubPath: PublicPath,
1027        PauserUUIDPubPath: PublicPath,
1028        PauserPubSigner: PublicPath,
1029        AdminExecutorStoragePath: StoragePath,
1030        AdminStoragePath: StoragePath,
1031        AdminCapReceiverPubPath: PublicPath,
1032        AdminUUIDPubPath: PublicPath,
1033        AdminPubSigner: PublicPath,
1034        OwnerExecutorStoragePath: StoragePath,
1035        OwnerStoragePath: StoragePath,
1036        OwnerCapReceiverPubPath: PublicPath,
1037        OwnerUUIDPubPath: PublicPath,
1038        OwnerPubSigner: PublicPath,
1039        MasterMinterExecutorStoragePath: StoragePath,
1040        MasterMinterStoragePath: StoragePath,
1041        MasterMinterCapReceiverPubPath: PublicPath,
1042        MasterMinterPubSigner: PublicPath,
1043        MasterMinterUUIDPubPath: PublicPath,
1044        MinterControllerStoragePath: StoragePath,
1045        MinterControllerUUIDPubPath: PublicPath,
1046        MinterControllerPubSigner: PublicPath,
1047        MinterStoragePath: StoragePath,
1048        MinterUUIDPubPath: PublicPath,
1049        initialAdminCapabilityPrivPath: PrivatePath,
1050        initialOwnerCapabilityPrivPath: PrivatePath,
1051        initialMasterMinterCapabilityPrivPath: PrivatePath,
1052        initialPauserCapabilityPrivPath: PrivatePath,
1053        initialBlocklisterCapabilityPrivPath: PrivatePath,
1054        tokenName: String,
1055        version: String,
1056        initTotalSupply: UFix64,
1057        initPaused: Bool,
1058        adminPubKeys: [String],
1059        adminPubKeysWeights: [UFix64],
1060        adminPubKeysAlgos: [UInt8],
1061        ownerPubKeys: [String],
1062        ownerPubKeysWeights: [UFix64],
1063        ownerPubKeysAlgos: [UInt8],
1064        masterMinterPubKeys: [String],
1065        masterMinterPubKeysWeights: [UFix64],
1066        masterMinterPubKeysAlgos: [UInt8],
1067        blocklisterPubKeys: [String],
1068        blocklisterPubKeysWeights: [UFix64],
1069        blocklisterPubKeysAlgos: [UInt8],
1070        pauserPubKeys: [String],
1071        pauserPubKeysWeights: [UFix64],
1072        pauserPubKeysAlgos: [UInt8],
1073    ) {
1074
1075        // Validate the keys
1076        assert(adminPubKeys.length == adminPubKeysWeights.length, message: "Admin pub keys length and weights mismatched")
1077        assert(ownerPubKeys.length == ownerPubKeysWeights.length, message: "Owner pub keys length and weights mismatched")
1078        assert(masterMinterPubKeys.length == masterMinterPubKeysWeights.length, message: "MasterMinter pub keys length and weights mismatched")
1079        assert(blocklisterPubKeys.length == blocklisterPubKeysWeights.length, message: "Blocklister pub keys length and weights mismatched")
1080        assert(pauserPubKeys.length == pauserPubKeysWeights.length, message: "Pauser pub keys length and weights mismatched")
1081
1082        // Set the State
1083        self.name = tokenName
1084        self.version = version
1085        self.paused = initPaused
1086        self.totalSupply = initTotalSupply
1087        self.blocklist = {}
1088        self.minterAllowances = {}
1089        self.managedMinters = {}
1090
1091        self.VaultStoragePath = VaultStoragePath
1092        self.VaultBalancePubPath = VaultBalancePubPath
1093        self.VaultUUIDPubPath = VaultUUIDPubPath
1094        self.VaultReceiverPubPath = VaultReceiverPubPath
1095
1096        self.BlocklistExecutorStoragePath =  BlocklistExecutorStoragePath
1097
1098        self.BlocklisterStoragePath =  BlocklisterStoragePath
1099        self.BlocklisterCapReceiverPubPath = BlocklisterCapReceiverPubPath
1100        self.BlocklisterUUIDPubPath = BlocklisterUUIDPubPath
1101        self.BlocklisterPubSigner = BlocklisterPubSigner
1102
1103        self.PauseExecutorStoragePath = PauseExecutorStoragePath
1104
1105        self.PauserStoragePath = PauserStoragePath
1106        self.PauserCapReceiverPubPath = PauserCapReceiverPubPath
1107        self.PauserUUIDPubPath = PauserUUIDPubPath
1108        self.PauserPubSigner = PauserPubSigner
1109
1110        self.AdminExecutorStoragePath = AdminExecutorStoragePath
1111
1112        self.AdminStoragePath = AdminStoragePath
1113        self.AdminCapReceiverPubPath = AdminCapReceiverPubPath
1114        self.AdminUUIDPubPath = AdminUUIDPubPath
1115        self.AdminPubSigner = AdminPubSigner
1116
1117        self.OwnerExecutorStoragePath = OwnerExecutorStoragePath
1118
1119        self.OwnerStoragePath = OwnerStoragePath
1120        self.OwnerCapReceiverPubPath = OwnerCapReceiverPubPath
1121        self.OwnerUUIDPubPath = OwnerUUIDPubPath
1122        self.OwnerPubSigner = OwnerPubSigner
1123
1124        self.MasterMinterExecutorStoragePath = MasterMinterExecutorStoragePath
1125
1126        self.MasterMinterStoragePath = MasterMinterStoragePath
1127        self.MasterMinterCapReceiverPubPath = MasterMinterCapReceiverPubPath
1128        self.MasterMinterPubSigner = MasterMinterPubSigner
1129        self.MasterMinterUUIDPubPath = MasterMinterUUIDPubPath
1130
1131        self.MinterControllerStoragePath = MinterControllerStoragePath
1132        self.MinterControllerUUIDPubPath = MinterControllerUUIDPubPath
1133        self.MinterControllerPubSigner = MinterControllerPubSigner
1134
1135        self.MinterStoragePath = MinterStoragePath
1136        self.MinterUUIDPubPath = MinterUUIDPubPath
1137
1138        // Create admin accounts
1139        let adminAccount = AuthAccount(payer: contractAccount)
1140        let ownerAccount = AuthAccount(payer: contractAccount)
1141        let masterMinterAccount = AuthAccount(payer: contractAccount)
1142        let blocklisterAccount = AuthAccount(payer: contractAccount)
1143        let pauserAccount = AuthAccount(payer: contractAccount)
1144        
1145        // Create the Executors
1146        contractAccount.save(<- create AdminExecutor(), to: self.AdminExecutorStoragePath)
1147        contractAccount.save(<- create OwnerExecutor(), to: self.OwnerExecutorStoragePath)
1148        contractAccount.save(<- create MasterMinterExecutor(), to: self.MasterMinterExecutorStoragePath)
1149        contractAccount.save(<- create BlocklistExecutor(), to: self.BlocklistExecutorStoragePath)
1150        contractAccount.save(<- create PauseExecutor(), to: self.PauseExecutorStoragePath)
1151
1152        // Setup the Admin
1153        var pubKeyAttrs: [OnChainMultiSig.PubKeyAttr] = []
1154        var i = 0
1155        while i < adminPubKeys.length {
1156            let pka = OnChainMultiSig.PubKeyAttr(sa: adminPubKeysAlgos[i], w: adminPubKeysWeights[i])
1157            pubKeyAttrs.append(pka)
1158            let key = PublicKey(
1159                publicKey: adminPubKeys[i].decodeHex(), 
1160                signatureAlgorithm: SignatureAlgorithm(rawValue: adminPubKeysAlgos[i]) ?? panic ("Invalid signature algo")
1161            )
1162            adminAccount.keys.add(
1163                publicKey: key,
1164                hashAlgorithm: HashAlgorithm.SHA3_256,
1165                weight: adminPubKeysWeights[i]
1166            )
1167            i = i + 1
1168        }
1169        adminAccount.save(<- self.createNewAdmin(publicKeys: adminPubKeys, pubKeyAttrs: pubKeyAttrs), to: self.AdminStoragePath)
1170        adminAccount.link<&Admin{OnChainMultiSig.PublicSigner}>(self.AdminPubSigner, target: self.AdminStoragePath)
1171        adminAccount.link<&Admin{ResourceId}>(self.AdminUUIDPubPath, target: self.AdminStoragePath)
1172        adminAccount.link<&Admin{AdminCapReceiver}>(self.AdminCapReceiverPubPath, target: self.AdminStoragePath)
1173
1174        // Setup the Owner
1175        pubKeyAttrs = []
1176        i = 0
1177        while i < ownerPubKeys.length {
1178            let pka = OnChainMultiSig.PubKeyAttr(sa: ownerPubKeysAlgos[i], w: ownerPubKeysWeights[i])
1179            pubKeyAttrs.append(pka)
1180            let key = PublicKey(
1181                publicKey: ownerPubKeys[i].decodeHex(), 
1182                signatureAlgorithm: SignatureAlgorithm(rawValue: ownerPubKeysAlgos[i]) ?? panic ("Invalid signature algo")
1183            )
1184            ownerAccount.keys.add(
1185                publicKey: key,
1186                hashAlgorithm: HashAlgorithm.SHA3_256,
1187                weight: ownerPubKeysWeights[i]
1188            )
1189            i = i + 1
1190        }
1191        ownerAccount.save(<- self.createNewOwner(publicKeys: ownerPubKeys, pubKeyAttrs: pubKeyAttrs), to: self.OwnerStoragePath)
1192        ownerAccount.link<&Owner{OnChainMultiSig.PublicSigner}>(self.OwnerPubSigner, target: self.OwnerStoragePath)
1193        ownerAccount.link<&Owner{ResourceId}>(self.OwnerUUIDPubPath, target: self.OwnerStoragePath)
1194        ownerAccount.link<&Owner{OwnerCapReceiver}>(self.OwnerCapReceiverPubPath, target: self.OwnerStoragePath)
1195
1196        // Setup the MasterMinter
1197        pubKeyAttrs = []
1198        i = 0
1199        while i < masterMinterPubKeys.length {
1200            let pka = OnChainMultiSig.PubKeyAttr(sa: masterMinterPubKeysAlgos[i], w: masterMinterPubKeysWeights[i])
1201            pubKeyAttrs.append(pka)
1202            let key = PublicKey(
1203                publicKey: masterMinterPubKeys[i].decodeHex(), 
1204                signatureAlgorithm: SignatureAlgorithm(rawValue: masterMinterPubKeysAlgos[i]) ?? panic ("Invalid signature algo")
1205            )
1206            masterMinterAccount.keys.add(
1207                publicKey: key,
1208                hashAlgorithm: HashAlgorithm.SHA3_256,
1209                weight: masterMinterPubKeysWeights[i]
1210            )
1211            i = i + 1
1212        }
1213        masterMinterAccount.save(<- self.createNewMasterMinter(publicKeys: masterMinterPubKeys, pubKeyAttrs: pubKeyAttrs), to: self.MasterMinterStoragePath)
1214        masterMinterAccount.link<&MasterMinter{OnChainMultiSig.PublicSigner}>(self.MasterMinterPubSigner, target: self.MasterMinterStoragePath)
1215        masterMinterAccount.link<&MasterMinter{ResourceId}>(self.MasterMinterUUIDPubPath, target: self.MasterMinterStoragePath)
1216        masterMinterAccount.link<&MasterMinter{MasterMinterCapReceiver}>(self.MasterMinterCapReceiverPubPath, target: self.MasterMinterStoragePath)
1217
1218        // Setup the Blocklister 
1219        pubKeyAttrs = []
1220        i = 0
1221        while i < blocklisterPubKeys.length {
1222            let pka = OnChainMultiSig.PubKeyAttr(sa: blocklisterPubKeysAlgos[i], w: blocklisterPubKeysWeights[i])
1223            pubKeyAttrs.append(pka)
1224            let key = PublicKey(
1225                publicKey: blocklisterPubKeys[i].decodeHex(), 
1226                signatureAlgorithm: SignatureAlgorithm(rawValue: blocklisterPubKeysAlgos[i]) ?? panic ("Invalid signature algo")
1227            )
1228            blocklisterAccount.keys.add(
1229                publicKey: key,
1230                hashAlgorithm: HashAlgorithm.SHA3_256,
1231                weight: blocklisterPubKeysWeights[i]
1232            )
1233            i = i + 1
1234        }
1235        blocklisterAccount.save(<- self.createNewBlocklister(publicKeys: blocklisterPubKeys, pubKeyAttrs: pubKeyAttrs), to: self.BlocklisterStoragePath)
1236        blocklisterAccount.link<&Blocklister{OnChainMultiSig.PublicSigner}>(self.BlocklisterPubSigner, target: self.BlocklisterStoragePath)
1237        blocklisterAccount.link<&Blocklister{ResourceId}>(self.BlocklisterUUIDPubPath, target: self.BlocklisterStoragePath)
1238        blocklisterAccount.link<&Blocklister{BlocklisterCapReceiver}>(self.BlocklisterCapReceiverPubPath, target: self.BlocklisterStoragePath)
1239
1240        // Setup the Pauser
1241        pubKeyAttrs = []
1242        i = 0
1243        while i < pauserPubKeys.length {
1244            let pka = OnChainMultiSig.PubKeyAttr(sa: pauserPubKeysAlgos[i], w: pauserPubKeysWeights[i])
1245            pubKeyAttrs.append(pka)
1246            let key = PublicKey(
1247                publicKey: pauserPubKeys[i].decodeHex(), 
1248                signatureAlgorithm: SignatureAlgorithm(rawValue: pauserPubKeysAlgos[i]) ?? panic ("Invalid signature algo")
1249            )
1250            pauserAccount.keys.add(
1251                publicKey: key,
1252                hashAlgorithm: HashAlgorithm.SHA3_256,
1253                weight: pauserPubKeysWeights[i]
1254            )
1255            i = i + 1
1256        }
1257        pauserAccount.save(<- self.createNewPauser(publicKeys: pauserPubKeys, pubKeyAttrs: pubKeyAttrs), to: self.PauserStoragePath)
1258        pauserAccount.link<&Pauser{OnChainMultiSig.PublicSigner}>(self.PauserPubSigner, target: self.PauserStoragePath)
1259        pauserAccount.link<&Pauser{ResourceId}>(self.PauserUUIDPubPath, target: self.PauserStoragePath)
1260        pauserAccount.link<&Pauser{PauseCapReceiver}>(self.PauserCapReceiverPubPath, target: self.PauserStoragePath)
1261
1262        // Assign the admin capabilities
1263        let adminExecutorRef = contractAccount.borrow<&FiatToken.AdminExecutor>(from: self.AdminExecutorStoragePath)
1264            ?? panic("cannot borrow AdminExecutor from storage")
1265        let ownerExecutorRef = contractAccount.borrow<&FiatToken.OwnerExecutor>(from: self.OwnerExecutorStoragePath)
1266            ?? panic("cannot borrow OwnerExecutor from storage")
1267        adminExecutorRef.changeAdmin(to: adminAccount.address, newPath: initialAdminCapabilityPrivPath)
1268        ownerExecutorRef.reassignOwner(to: ownerAccount.address, newPath: initialOwnerCapabilityPrivPath)
1269        ownerExecutorRef.reassignMasterMinter(to: masterMinterAccount.address, newPath: initialMasterMinterCapabilityPrivPath)
1270        ownerExecutorRef.reassignBlocklister(to: blocklisterAccount.address, newPath: initialBlocklisterCapabilityPrivPath)
1271        ownerExecutorRef.reassignPauser(to: pauserAccount.address, newPath: initialPauserCapabilityPrivPath) 
1272
1273        // Create a Vault with the initial totalSupply
1274        let vault <- create Vault(balance: self.totalSupply)
1275        self.account.save(<-vault, to: self.VaultStoragePath)
1276
1277        // Create public capabilities to the vault
1278        contractAccount.link<&FiatToken.Vault{FungibleToken.Receiver}>(self.VaultReceiverPubPath, target: self.VaultStoragePath)
1279        contractAccount.link<&FiatToken.Vault{FungibleToken.Balance}>(self.VaultBalancePubPath, target: self.VaultStoragePath)
1280        contractAccount.link<&FiatToken.Vault{FiatToken.ResourceId}>(self.VaultUUIDPubPath, target: self.VaultStoragePath)
1281
1282        // Emit the TokensInitialized event
1283        emit TokensInitialized(initialSupply: self.totalSupply)
1284
1285    }
1286
1287}
1288