Skip to content

Commit

Permalink
remove custom destructor
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuahannan committed Dec 12, 2023
1 parent a95f9ec commit a2802ba
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 195 deletions.
18 changes: 2 additions & 16 deletions contracts/FungibleToken-v2.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,6 @@ access(all) contract FungibleToken {
/// The event that is emitted when tokens are deposited to a Vault
access(all) event Deposit(amount: UFix64, to: Address?, type: String)

/// Event emitted when tokens are destroyed
access(all) event Burn(amount: UFix64, type: String)

access(self) fun emitBurnEvent(amount: UFix64, type: String): Bool {
if amount >= 0.0 {
emit Burn(amount: amount, type: type)
}
return true
}

/// Provider
///
/// The interface that enforces the requirements for withdrawing
Expand Down Expand Up @@ -132,6 +122,8 @@ access(all) contract FungibleToken {
///
access(all) resource interface Vault: Receiver, Provider, ViewResolver.Resolver {

//access(all) event ResourceDestroyed(balance: UFix64 = self.getBalance(), type: Type = self.getType().identifier)
/// Get the balance of the vault
access(all) view fun getBalance(): UFix64

Expand Down Expand Up @@ -205,11 +197,5 @@ access(all) contract FungibleToken {
result.getBalance() == 0.0: "The newly created Vault must have zero balance"
}
}

destroy() {
// pre {
// FungibleToken.emitBurnEvent(amount: self.getBalance(), type: self.getType().identifier)
// }
}
}
}
221 changes: 49 additions & 172 deletions contracts/utility/NonFungibleToken.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -48,92 +48,70 @@ import ViewResolver from "ViewResolver"
///
access(all) contract NonFungibleToken {

// An entitlement for allowing the withdrawal of tokens from a Vault
/// An entitlement for allowing the withdrawal of tokens from a Vault
access(all) entitlement Withdrawable

/// An entitlement for allowing updates and update events for an NFT
access(all) entitlement Updatable

/// Event that contracts should emit when the metadata of an NFT is updated
/// It can only be emitted by calling the `emitNFTUpdated` function
/// with an `Updatable` entitled reference to the NFT that was updated
/// The entitlement prevents spammers from calling this from other users' collections
/// because only code within a collection or that has special entitled access
/// to the collections methods will be able to get the entitled reference
///
/// The event makes it so that third-party indexers can monitor the events
/// and query the updated metadata from the owners' collections.
///
access(all) event Updated(id: UInt64, uuid: UInt64, owner: Address?, type: String)
access(all) view fun emitNFTUpdated(_ nftRef: auth(Updatable) &{NonFungibleToken.NFT})
{
emit Updated(id: nftRef.getID(), uuid: nftRef.uuid, owner: nftRef.owner?.address, type: nftRef.getType().identifier)
}


/// Event that is emitted when a token is withdrawn,
/// indicating the owner of the collection that it was withdrawn from.
///
/// If the collection is not in an account's storage, `from` will be `nil`.
///
access(all) event Withdraw(id: UInt64, uuid: UInt64, from: Address?, type: String)

access(self) view fun emitNFTWithdraw(id: UInt64, uuid: UInt64, from: Address?, type: String): Bool
{
emit Withdraw(id: id, uuid: uuid, from: from, type: type)
return true
}

/// Event that emitted when a token is deposited to a collection.
///
/// It indicates the owner of the collection that it was deposited to.
///
access(all) event Deposit(id: UInt64, uuid: UInt64, to: Address?, type: String)

access(self) view fun emitNFTDeposit(id: UInt64, uuid: UInt64, to: Address?, type: String): Bool
{
emit Deposit(id: id, uuid: uuid, to: to, type: type)
return true
}

/// Transfer
///
/// The event that should be emitted when tokens are transferred from one account to another
///
access(all) event Transfer(id: UInt64, uuid: UInt64, from: Address?, to: Address?, type: String)

access(self) view fun emitNFTTransfer(id: UInt64, uuid: UInt64?, from: Address?, to: Address?, type: String?): Bool
{
// The transfer method can return false even if it didn't do a transfer
// in which case we don't want the event to be emitted
if uuid != nil && type != nil {
emit Transfer(id: id, uuid: uuid!, from: from, to: to, type: type!)
return true
} else {
return true
}
}

/// Destroy
///
/// The event that should be emitted when an NFT is destroyed
access(all) event Destroy(id: UInt64, uuid: UInt64, type: String)

access(self) view fun emitNFTDestroy(id: UInt64, uuid: UInt64, type: String): Bool
{
emit Destroy(id: id, uuid: uuid, type: type)
return true
}

/// Interface that the NFTs must conform to
///
access(all) resource interface NFT: ViewResolver.Resolver {
/// The unique ID that each NFT has
access(all) view fun getID(): UInt64 {
return self.uuid
}
access(all) view fun getID(): UInt64

// access(all) view fun getViews(): [Type] {
// return []
// }
// access(all) fun resolveView(_ view: Type): AnyStruct? {
// return nil
// }
// access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid, type: Type = self.getType().identifier)
destroy() {
pre {
NonFungibleToken.emitNFTDestroy(id: self.getID(), uuid: self.uuid, type: self.getType().identifier)
}
/// Get a reference to an NFT that this NFT owns
/// Both arguments are optional to allow the NFT to choose
/// how it returns sub NFTs depending on what arguments are provided
/// For example, if `type` has a value, but `id` doesn't, the NFT
/// can choose which NFT of that type to return if there is a "default"
/// If both are `nil`, then NFTs that only store a single NFT can just return
/// that. This helps callers who aren't sure what they are looking for
///
/// @param type: The Type of the desired NFT
/// @param id: The id of the NFT to borrow
///
/// @return A structure representing the requested view.
access(all) fun getSubNFT(type: Type, id: UInt64) : &{NonFungibleToken.NFT}? {
return nil
}
}

/// Interface to mediate withdraws from the Collection
///
access(all) resource interface Provider {
/// Function for projects to indicate if they are using UUID or not
access(all) view fun usesUUID(): Bool {
return false
}

// We emit withdraw events from the provider interface because conficting withdraw
// events aren't as confusing to event listeners as conflicting deposit events
Expand All @@ -143,53 +121,9 @@ access(all) contract NonFungibleToken {
access(Withdrawable) fun withdraw(withdrawID: UInt64): @{NFT} {
post {
result.getID() == withdrawID: "The ID of the withdrawn token must be the same as the requested ID"
NonFungibleToken.emitNFTWithdraw(id: result.getID(), uuid: result.uuid, from: self.owner?.address, type: result.getType().identifier)
}
}

/// Alternate withdraw methods
/// The next three withdraw methods allow projects to have more flexibility
/// to indicate how their NFTs are meant to be used
/// With the v2 upgrade, some projects will be using UUID and others
/// will be using custom IDs, so projects can pick and choose which
/// of these withdraw methods applies to them
/// TODO: These will eventually have optional return types, but don't right now
/// because of a bug in Cadence
/// withdrawWithUUID removes an NFT from the collection, using its UUID, and moves it to the caller
access(Withdrawable) fun withdrawWithUUID(_ uuid: UInt64): @{NFT} {
post {
result == nil || result!.uuid == uuid: "The ID of the withdrawn token must be the same as the requested ID"
NonFungibleToken.emitNFTWithdraw(id: result.getID(), uuid: result.uuid, from: self.owner?.address, type: result.getType().identifier)
emit Withdraw(id: result.getID(), uuid: result.uuid, from: self.owner?.address, type: result.getType().identifier)
}
}

/// withdrawWithType removes an NFT from the collection, using its Type and ID and moves it to the caller
/// This would be used by a collection that can store multiple NFT types
access(Withdrawable) fun withdrawWithType(type: Type, withdrawID: UInt64): @{NFT} {
post {
result == nil || result.getID() == withdrawID: "The ID of the withdrawn token must be the same as the requested ID"
NonFungibleToken.emitNFTWithdraw(id: result.getID(), uuid: result.uuid, from: self.owner?.address, type: result.getType().identifier)
}
}

/// withdrawWithTypeAndUUID removes an NFT from the collection using its type and uuid and moves it to the caller
/// This would be used by a collection that can store multiple NFT types
access(Withdrawable) fun withdrawWithTypeAndUUID(type: Type, uuid: UInt64): @{NFT} {
post {
result == nil || result!.uuid == uuid: "The ID of the withdrawn token must be the same as the requested ID"
NonFungibleToken.emitNFTWithdraw(id: result.getID(), uuid: result.uuid, from: self.owner?.address, type: result.getType().identifier)
}
}
}

/// Interface to mediate transfers between Collections
///
access(all) resource interface Transferor {
/// transfer removes an NFT from the callers collection
/// and moves it to the collection specified by `receiver`
access(Withdrawable) fun transfer(id: UInt64, receiver: Capability<&{Receiver}>): Bool
}

/// Interface to mediate deposits to the Collection
Expand All @@ -200,64 +134,37 @@ access(all) contract NonFungibleToken {
///
access(all) fun deposit(token: @{NFT})

// /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
// access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
// return {}
// }
/// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
access(all) view fun getSupportedNFTTypes(): {Type: Bool}

// /// Returns whether or not the given type is accepted by the collection
// /// A collection that can accept any type should just return true by default
// access(all) view fun isSupportedNFTType(type: Type): Bool {
// return false
// }
/// Returns whether or not the given type is accepted by the collection
/// A collection that can accept any type should just return true by default
access(all) view fun isSupportedNFTType(type: Type): Bool
}

/// Requirement for the concrete resource type
/// to be declared in the implementing contract
///
access(all) resource interface Collection: Provider, Receiver, Transferor, ViewResolver.ResolverCollection {
access(all) resource interface Collection: Provider, Receiver, ViewResolver.ResolverCollection {

/// Return the default storage path for the collection
access(all) view fun getDefaultStoragePath(): StoragePath? {
return nil
}
access(all) view fun getDefaultStoragePath(): StoragePath?

/// Return the default public path for the collection
access(all) view fun getDefaultPublicPath(): PublicPath? {
return nil
}
access(all) view fun getDefaultPublicPath(): PublicPath?

/// Normally we would require that the collection specify
/// a specific dictionary to store the NFTs, but this isn't necessary any more
/// as long as all the other functions are there
/// Returns the NFT types that this collection can store
/// If the collection can accept any NFT type, it should return
/// a one element dictionary with the key type as `@{NonFungibleToken.NFT}`
access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
pre { true: "dummy" }
}

/// Returns whether or not the given type is accepted by the collection
access(all) view fun isSupportedNFTType(type: Type): Bool {
pre { true: "dummy" }
}

/// createEmptyCollection creates an empty Collection
/// and returns it to the caller so that they can own NFTs
access(all) fun createEmptyCollection(): @{Collection} {
post {
result.getIDs().length == 0: "The created collection must be empty!"
result.getLength() == 0: "The created collection must be empty!"
}
}

// access(all) view fun usesUUID(): Bool {
// return false
// }
/// withdraw removes an NFT from the collection and moves it to the caller
access(Withdrawable) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT}

/// deposit takes a NFT and adds it to the collections dictionary
/// and adds the ID to the id array
access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
Expand All @@ -266,44 +173,14 @@ access(all) contract NonFungibleToken {
// because the `Collection` interface is almost always the final destination
// of tokens and deposit emissions from custom receivers could be confusing
// and hard to reconcile to event listeners
NonFungibleToken.emitNFTDeposit(id: token.getID(), uuid: token.uuid, to: self.owner?.address, type: token.getType().identifier)
emit Deposit(id: token.getID(), uuid: token.uuid, to: self.owner?.address, type: token.getType().identifier)
}
}

/// Function for a direct transfer instead of having to do a deposit and withdrawal
/// This can and should return false if the transfer doesn't succeed and true if it does succeed
///
access(Withdrawable) fun transfer(id: UInt64, receiver: Capability<&{NonFungibleToken.Receiver}>): Bool {
pre {
receiver.check(): "Could not borrow a reference to the NFT receiver"
self.getIDs().contains(id): "The collection does not contain the specified ID"
NonFungibleToken.emitNFTTransfer(id: id, uuid: self.borrowNFTSafe(id: id)?.uuid, from: self.owner?.address, to: receiver.borrow()?.owner?.address, type: self.borrowNFT(id).getType().identifier)
}
}

/// getIDs returns an array of the IDs that are in the collection
access(all) view fun getIDs(): [UInt64]

/// Gets the amount of NFTs stored in the collection
access(all) view fun getLength(): Int

/// getIDsWithTypes returns a list of IDs that are in the collection, keyed by type
/// Should only be used by collections that can store multiple NFT types
access(all) view fun getIDsWithTypes(): {Type: [UInt64]}

/// Returns a borrowed reference to an NFT in the collection
/// so that the caller can read data and call methods from it
access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT} {
pre { true: "dummy" }
}

/// From the ViewResolver Contract
/// borrows a reference to get metadata views for the NFTs that the contract contains
access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
pre { true: "dummy" }
}

access(all) view fun borrowNFTSafe(id: UInt64): &{NonFungibleToken.NFT}? {
access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
post {
(result == nil) || (result?.getID() == id):
"Cannot borrow NFT reference: The ID of the returned reference does not match the ID that was specified"
Expand Down
Loading

0 comments on commit a2802ba

Please sign in to comment.