From 93d88164277967716c54d7cefe5c6910f10c377b Mon Sep 17 00:00:00 2001 From: Austin Kline Date: Wed, 18 Sep 2024 17:30:41 -0700 Subject: [PATCH] add ManagerSaved event and onSave function to emit it (#39) --- contracts/ContractManager.cdc | 29 ++++++++++++++++ transactions/contract-manager/setup.cdc | 4 ++- .../factory/create_open_edition_contract.cdc | 34 ------------------- .../factory/create_open_edition_drop.cdc | 5 +-- 4 files changed, 35 insertions(+), 37 deletions(-) delete mode 100644 transactions/factory/create_open_edition_contract.cdc diff --git a/contracts/ContractManager.cdc b/contracts/ContractManager.cdc index 3ddf351..165805a 100644 --- a/contracts/ContractManager.cdc +++ b/contracts/ContractManager.cdc @@ -6,8 +6,13 @@ access(all) contract ContractManager { access(all) let StoragePath: StoragePath access(all) let PublicPath: PublicPath + access(all) let OwnerStoragePath: StoragePath + access(all) let OwnerPublicPath: PublicPath + access(all) entitlement Manage + access(all) event ManagerSaved(uuid: UInt64, contractAddress: Address, ownerAddress: Address) + access(all) resource Manager { access(self) let acct: Capability access(self) let routerCap: Capability @@ -36,6 +41,26 @@ access(all) contract ContractManager { return getAccount(self.acct.address) } + // Should be called after saving a ContractManager resource to signal that a new address stores (and therefore "owns") + // this manager resource's acct capability. Without this, it is not possible to track the original creator of a contract + // when using the ContractManager + access(Manage) fun onSave() { + let acct = self.acct.borrow()! + + acct.storage.load
(from: ContractManager.OwnerStoragePath) + acct.storage.save(self.owner!.address, to: ContractManager.OwnerStoragePath) + + if !acct.capabilities.get<&Address>(ContractManager.OwnerPublicPath).check() { + acct.capabilities.unpublish(ContractManager.OwnerPublicPath) + acct.capabilities.publish( + acct.capabilities.storage.issue<&Address>(ContractManager.OwnerStoragePath), + at: ContractManager.OwnerPublicPath + ) + } + + emit ManagerSaved(uuid: self.uuid, contractAddress: self.acct.address, ownerAddress: self.owner!.address) + } + init(tokens: @FlowToken.Vault, defaultRouterAddress: Address) { pre { tokens.balance >= 0.001: "minimum balance of 0.001 required for initialization" @@ -69,5 +94,9 @@ access(all) contract ContractManager { let identifier = "ContractManager_".concat(self.account.address.toString()) self.StoragePath = StoragePath(identifier: identifier)! self.PublicPath = PublicPath(identifier: identifier)! + + let ownerIdentifier = "ContractManager_Owner_".concat(self.account.address.toString()) + self.OwnerStoragePath = StoragePath(identifier: ownerIdentifier)! + self.OwnerPublicPath = PublicPath(identifier: ownerIdentifier)! } } \ No newline at end of file diff --git a/transactions/contract-manager/setup.cdc b/transactions/contract-manager/setup.cdc index 04fb697..2fe8cfd 100644 --- a/transactions/contract-manager/setup.cdc +++ b/transactions/contract-manager/setup.cdc @@ -7,6 +7,8 @@ transaction(flowTokenAmount: UFix64) { let v = acct.storage.borrow(from: /storage/flowTokenVault)! let tokens <- v.withdraw(amount: flowTokenAmount) as! @FlowToken.Vault - acct.storage.save(<- ContractManager.createManager(tokens: <-tokens), to: ContractManager.StoragePath) + acct.storage.save(<- ContractManager.createManager(tokens: <-tokens, defaultRouterAddress: acct.address), to: ContractManager.StoragePath) + + acct.storage.borrow(from: ContractManager.StoragePath)!.onSave() } } \ No newline at end of file diff --git a/transactions/factory/create_open_edition_contract.cdc b/transactions/factory/create_open_edition_contract.cdc deleted file mode 100644 index d3d7267..0000000 --- a/transactions/factory/create_open_edition_contract.cdc +++ /dev/null @@ -1,34 +0,0 @@ -import "ContractFactory" -import "ContractFactoryTemplate" -import "OpenEditionTemplate" -import "MetadataViews" -import "OpenEditionInitializer" -import "ContractManager" -import "FungibleToken" -import "FlowToken" - -transaction(name: String, params: {String: AnyStruct}, managerInitialTokenBalance: UFix64) { - prepare(acct: auth(Storage, Capabilities) &Account) { - if acct.storage.borrow<&AnyResource>(from: ContractManager.StoragePath) == nil { - let v = acct.storage.borrow(from: /storage/flowTokenVault)! - let tokens <- v.withdraw(amount: managerInitialTokenBalance) as! @FlowToken.Vault - - acct.storage.save(<- ContractManager.createManager(tokens: <-tokens), to: ContractManager.StoragePath) - - acct.capabilities.publish( - acct.capabilities.storage.issue<&ContractManager.Manager>(ContractManager.StoragePath), - at: ContractManager.PublicPath - ) - } - - let manager = acct.storage.borrow(from: ContractManager.StoragePath) - ?? panic("manager was not borrowed successfully") - - let sb = manager.getSwitchboard() - if !sb.isSupportedVaultType(type: Type<@FlowToken.Vault>()) { - manager.addFungibleTokenReceiver(acct.capabilities.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)) - } - - ContractFactory.createContract(templateType: Type(), acct: manager.borrowContractAccount(), name: name, params: params, initializeIdentifier: Type().identifier) - } -} \ No newline at end of file diff --git a/transactions/factory/create_open_edition_drop.cdc b/transactions/factory/create_open_edition_drop.cdc index e33c38c..bef9b14 100644 --- a/transactions/factory/create_open_edition_drop.cdc +++ b/transactions/factory/create_open_edition_drop.cdc @@ -14,11 +14,12 @@ import "FlowtyAddressVerifiers" transaction(contractName: String, managerInitialTokenBalance: UFix64, start: UInt64?, end: UInt64?, price: UFix64, paymentTokenType: String, phaseArgs: {String: String}, metadataArgs: {String: String}, collectionInfoArgs: {String: String}, dropDetailArgs: {String: String}) { prepare(acct: auth(Storage, Capabilities) &Account) { - if acct.storage.borrow<&AnyResource>(from: ContractManager.StoragePath) == nil { + if acct.storage.type(at: ContractManager.StoragePath) == nil { let v = acct.storage.borrow(from: /storage/flowTokenVault)! let tokens <- v.withdraw(amount: managerInitialTokenBalance) as! @FlowToken.Vault - acct.storage.save(<- ContractManager.createManager(tokens: <-tokens), to: ContractManager.StoragePath) + acct.storage.save(<- ContractManager.createManager(tokens: <-tokens, defaultRouterAddress: acct.address), to: ContractManager.StoragePath) + acct.storage.borrow(from: ContractManager.StoragePath)!.onSave() acct.capabilities.publish( acct.capabilities.storage.issue<&ContractManager.Manager>(ContractManager.StoragePath),