Skip to content

Commit

Permalink
fix migration issues
Browse files Browse the repository at this point in the history
  • Loading branch information
loic1 committed Aug 1, 2024
1 parent 1d44e3a commit 7a0ec1e
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 34 deletions.
2 changes: 1 addition & 1 deletion nft-provider-aggregator/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ removes all the resource's NFT provider capabilities and render child `Supplier`
The use of the `Supplier` resource allows:
- Explicitly keeping track of the NFT provider capabilities that are expected to be valid all in one place, the parent `Aggregator` resource, and emitting dedicated events when a capability is added or removed.
- Reversibly exposing NFT provider capabilities to the parent `Aggregator` resource without the capabilities being retrievable individually by the **manager**. This is made possible by the `Aggregator` resource’s `nftWithdrawCapabilities` dictionary being defined with `access(self)` access control and devoid of any getter function, though, if the `NFTProviderAggregator` contract is updatable, a contract update may potentially change that.
- Reversibly exposing NFT provider capabilities to the parent `Aggregator` resource without the capabilities being retrievable individually by the **manager**. This is made possible by the `Aggregator` resource’s `nftProviderCapabilities` dictionary being defined with `access(self)` access control and devoid of any getter function, though, if the `NFTProviderAggregator` contract is updatable, a contract update may potentially change that.

> Note: Another architecture to aggregate NFT providers exists where **suppliers** link NFT provider capabilities at custom private paths and directly publish them to the **manager** holding the `Aggregator` resource, thus bypassing the need for the `Supplier` resource. It should be noted that:
> - Off-chain records may be needed to keep track of each private path where a NFT provider capability was linked, even if it was then unlinked by the **supplier** to revoke **manager** access because it is important to be aware that the **manager** would regain access if it is linked at the same path again later.
Expand Down
56 changes: 28 additions & 28 deletions nft-provider-aggregator/contracts/NFTProviderAggregator.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ access(all) contract NFTProviderAggregator {
///
access(all) resource interface SupplierAccess {
access(Operate) fun addNFTWithdrawCapability(
_ cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>): UInt64
_ cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>): UInt64
access(Operate) fun removeNFTWithdrawCapability(collectionUUID: UInt64)
access(all) fun getIDs(): [UInt64]
access(all) view fun getCollectionUUIDs(): [UInt64]
Expand All @@ -114,17 +114,17 @@ access(all) contract NFTProviderAggregator {
access(self) let supplierAccessCapability: Capability<auth(Operate) &Aggregator>

/// Dictionary of supplied NFT provider capabilities
access(self) var nftWithdrawCapabilities: {UInt64: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>}
access(self) var nftProviderCapabilities: {UInt64: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>}

/// Add NFT provider capability (may be called by Supplier or directly by Aggregator)
access(Operate) fun addNFTWithdrawCapability(
_ cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>
_ cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>
): UInt64 {
pre {
self.isNFTWithdrawCapabilityValid(cap): "Invalid NFT provider capability!"
}
var collectionUUID = cap.borrow()!.uuid
self.nftWithdrawCapabilities.insert(
self.nftProviderCapabilities.insert(
key: collectionUUID,
cap
)
Expand All @@ -141,25 +141,25 @@ access(all) contract NFTProviderAggregator {
///
access(Operate) fun removeNFTWithdrawCapability(collectionUUID: UInt64) {
pre {
self.nftWithdrawCapabilities.containsKey(
self.nftProviderCapabilities.containsKey(
collectionUUID
): "NFT provider capability does not exist (not added yet or removed by Aggregator)!"
}
self.nftWithdrawCapabilities.remove(key: collectionUUID)
self.nftProviderCapabilities.remove(key: collectionUUID)
emit NFTWithdrawCapabilityRemoved(nftTypeIdentifier: self.nftTypeIdentifier, collectionUUID: collectionUUID)
}

/// Borrow the provider of an NFT located in one of multiple collections through iterating over each collection
///
access(NonFungibleToken.Withdraw) fun borrowNFTProvider(id: UInt64): auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection} {
for collectionUUID in self.nftWithdrawCapabilities.keys {
access(NonFungibleToken.Withdraw) fun borrowNFTProvider(id: UInt64): auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic} {
for collectionUUID in self.nftProviderCapabilities.keys {
// Check capabilities can still be borrowed since a NFT provider capability may pass the
// pre-condition checks at the time of being added with the addNFTWithdrawCapability method but
// may be unlinked later or the target collection be destroyed.
if self.nftWithdrawCapabilities[collectionUUID]!.check() {
if self.nftProviderCapabilities[collectionUUID]!.check() {
// Retrieve reference to the NFT provider
let nftProviderRef = self.nftWithdrawCapabilities[collectionUUID]!.borrow()!
// Check NFT provider UUID still matches that of the nftWithdrawCapabilities dictionary
let nftProviderRef = self.nftProviderCapabilities[collectionUUID]!.borrow()!
// Check NFT provider UUID still matches that of the nftProviderCapabilities dictionary
assert(
nftProviderRef.uuid == collectionUUID,
message: "NFT provider capability has invalid collection UUID! Must be removed."
Expand All @@ -180,15 +180,15 @@ access(all) contract NFTProviderAggregator {

/// Borrow the collection of an NFT located in one of multiple collections through iterating over each collection
///
access(all) view fun borrowNFTCollection(id: UInt64): &{NonFungibleToken.Collection} {
for collectionUUID in self.nftWithdrawCapabilities.keys {
access(all) view fun borrowNFTCollection(id: UInt64): &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic} {
for collectionUUID in self.nftProviderCapabilities.keys {
// Check capabilities can still be borrowed since a NFT provider capability may pass the
// pre-condition checks at the time of being added with the addNFTWithdrawCapability method but
// may be unlinked later or the target collection be destroyed.
if self.nftWithdrawCapabilities[collectionUUID]!.check() {
if self.nftProviderCapabilities[collectionUUID]!.check() {
// Retrieve reference to the NFT provider
let nftProviderRef = self.nftWithdrawCapabilities[collectionUUID]!.borrow()!
// Check NFT provider UUID still matches that of the nftWithdrawCapabilities dictionary
let nftProviderRef = self.nftProviderCapabilities[collectionUUID]!.borrow()!
// Check NFT provider UUID still matches that of the nftProviderCapabilities dictionary
assert(
nftProviderRef.uuid == collectionUUID,
message: "NFT provider capability has invalid collection UUID! Must be removed."
Expand Down Expand Up @@ -237,18 +237,18 @@ access(all) contract NFTProviderAggregator {
)
}

/// Return an array of the NFT IDs accessible through nftWithdrawCapabilities
/// Return an array of the NFT IDs accessible through nftProviderCapabilities
///
access(all) fun getIDs(): [UInt64] {
let ids: [UInt64] = []
for collectionUUID in self.nftWithdrawCapabilities.keys {
for collectionUUID in self.nftProviderCapabilities.keys {
// Check capability can still be borrowed since a NFT provider capability may pass the
// pre-condition checks at the time of being added with the addNFTWithdrawCapability method
// but may be unlinked later or the target collection be destroyed.
if self.nftWithdrawCapabilities[collectionUUID]!.check() {
let collectionRef = self.nftWithdrawCapabilities[
if self.nftProviderCapabilities[collectionUUID]!.check() {
let collectionRef = self.nftProviderCapabilities[
collectionUUID]!.borrow()!
// Check UUID still matches that of the nftWithdrawCapabilities dictionary
// Check UUID still matches that of the nftProviderCapabilities dictionary
assert(
collectionUUID == collectionRef.uuid,
message: "NFT provider capability has invalid collection UUID! Must be removed.!"
Expand All @@ -270,13 +270,13 @@ access(all) contract NFTProviderAggregator {
/// Return an array of all the collection UUIDs
///
access(all) view fun getCollectionUUIDs(): [UInt64] {
return self.nftWithdrawCapabilities.keys
return self.nftProviderCapabilities.keys
}

/// Check whether a given NFT provider capability is valid
///
access(self) view fun isNFTWithdrawCapabilityValid(
_ cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>
_ cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>
): Bool {
let nftProviderRef = cap.borrow()
?? panic("NFT provider couldn't be borrowed! Cannot be added.")
Expand All @@ -286,8 +286,8 @@ access(all) contract NFTProviderAggregator {
message: "Expected capability to target identifier: ".concat(self.nftTypeIdentifier).concat(" but got: ").concat(nftProviderRef.getType().identifier)
)
// Check NFT provider capability doesn't already exist
for collectionUUID in self.nftWithdrawCapabilities.keys {
let _nftProviderRef = self.nftWithdrawCapabilities[collectionUUID]!.borrow()
for collectionUUID in self.nftProviderCapabilities.keys {
let _nftProviderRef = self.nftProviderCapabilities[collectionUUID]!.borrow()
?? panic("NFT provider couldn't be borrowed! Must be removed.")
if _nftProviderRef.uuid == nftProviderRef.uuid {
panic("NFT provider capability already exists! Cannot be added.")
Expand All @@ -302,7 +302,7 @@ access(all) contract NFTProviderAggregator {
nftTypeIdentifier: String,
supplierAccessCapability: Capability<auth(Operate) &Aggregator>
) {
self.nftWithdrawCapabilities = {}
self.nftProviderCapabilities = {}
self.nftTypeIdentifier = nftTypeIdentifier
self.supplierAccessCapability = supplierAccessCapability
emit AggregatorResourceInitialized(nftTypeIdentifier: nftTypeIdentifier)
Expand Down Expand Up @@ -341,7 +341,7 @@ access(all) contract NFTProviderAggregator {
/// Add NFT provider capability to parent Aggregator resource
///
access(Operate) fun addNFTWithdrawCapability(
_ cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>
_ cap: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>
): UInt64 {

let collectionUUID = self.borrowAuthAggregator().addNFTWithdrawCapability(cap)
Expand Down Expand Up @@ -392,7 +392,7 @@ access(all) contract NFTProviderAggregator {
///
access(contract) fun burnCallback() {
for collectionUUID in self.supplierAddedCollectionUUIDs.keys {
// Check collectionUUID is present in the parent Aggregator resource's nftWithdrawCapabilities's
// Check collectionUUID is present in the parent Aggregator resource's nftProviderCapabilities's
// dictionary in case the manager already removed the capability
if self.getCollectionUUIDs().contains(collectionUUID) {
self.removeNFTWithdrawCapability(collectionUUID: collectionUUID)
Expand Down
2 changes: 1 addition & 1 deletion nft-provider-aggregator/lib/go/test/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func addNftWithdrawCapAsSupplier(
// Create transaction
tx := flow.NewTransaction().
SetScript(loadScript(contracts, AddNftWithdrawCapAsSupplierPath)).
SetComputeLimit(100).
SetComputeLimit(200).
SetProposalKey(b.ServiceKey().Address, b.ServiceKey().Index, b.ServiceKey().SequenceNumber).
SetPayer(b.ServiceKey().Address).
AddAuthorizer(senderAddress)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ transaction(
let nftWithdrawCapStoragePath: StoragePath
let nftCollectionStoragePath: StoragePath
let aggregatorRef: auth(NFTProviderAggregator.Operate) &NFTProviderAggregator.Aggregator
let nftWithdrawCapability: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>
let nftWithdrawCapability: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>

prepare(
manager: auth(CopyValue, BorrowValue, SaveValue, GetStorageCapabilityController, IssueStorageCapabilityController) &Account,
Expand All @@ -31,7 +31,7 @@ transaction(
?? panic("Provided NFT collection storage path has invalid format!")

// Retrieve or create NFT provider capability
if let retrievedCap = manager.storage.copy<Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>>(
if let retrievedCap = manager.storage.copy<Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>>(
from: self.nftWithdrawCapStoragePath) {
self.nftWithdrawCapability = retrievedCap
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ transaction(
let nftWithdrawCapStoragePath: StoragePath
let nftCollectionStoragePath: StoragePath
let supplierRef: auth(NFTProviderAggregator.Operate) &NFTProviderAggregator.Supplier
let nftWithdrawCapability: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>
let nftWithdrawCapability: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>

prepare(
supplier: auth(CopyValue, BorrowValue, SaveValue, GetStorageCapabilityController, IssueStorageCapabilityController) &Account,
Expand All @@ -31,7 +31,7 @@ transaction(
?? panic("Provided NFT collection storage path has invalid format!")

// Retrieve or create NFT provider capability
if let retrievedCap = supplier.storage.copy<Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>>(
if let retrievedCap = supplier.storage.copy<Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>>(
from: self.nftWithdrawCapStoragePath) {
self.nftWithdrawCapability = retrievedCap
} else {
Expand Down

0 comments on commit 7a0ec1e

Please sign in to comment.