aip | title | author | discussions-to (*optional) | Status | last-call-end-date (*optional) | type | created | updated (*optional) | requires (*optional) |
---|---|---|---|---|---|---|---|---|---|
109 |
Hide Unwanted Soulbound Objects |
gregnazario ([email protected]) |
Draft |
12/18/2024 |
Framework |
12/11/2024 |
12/11/2024 |
AIP-99 |
Safe burn was originally described in AIP-45, which allowed users to tombstone their objects and remove direct linkage of an undeletable, also known as soulbound, object to an account. AIP-99 that functionality was disabled due to complexities around moving objects to the burn address on those implementing owner based allowlists. This AIP seeks to add back the ability to TombStone objects, but purely for the purposes of hiding objects from view. It was the main goal behind AIP-45, and this AIP will bring back that functionality.
As a result of this AIP, users will be able to burn objects by adding a TombStone to their object. This will allow users to hide spam, or unwanted items from their account. Then, all indexers, wallets, explorers, etc. will not show it to the user, unless they specifically request to see it. This will allow users to have a cleaner UX for users and allow them to hide unwanted items in a decentralized persistent way.
If we delay enacting this, users may have their wallets full of soulbound junk NFTs or fungible assets that they do not choose to see.
Users and products that choose not to implement or use an indexer that implements the TombStone as a way to hide objects will not change their UX. Since this is fully decentralized, if it's not adopted by them, they will not see the benefits.
The purpose here is to provide the original intent of AIP-45, which was to allow users to hide unwanted items from their wallets. This will allow users to have a cleaner UX, and not have to see unwanted items.
If we do not accept this proposal, users will not be able to hide unwanted items across all of their interfaces at once and instead would have to do it on every single wallet or interface they use.
This impacts the following parties:
- Builders who built products that want to allow users to hide unwanted items
- Indexers that index objects or NFTs and show them to users
- Users who plan to burn owned soulbound objects
- Smart contract developers who use the
burn
orunburn
functionality
This does not impact the following parties:
- Users who have already burnt owned soulbound objects. They still can unburn them.
The alternative solution, would be to have a standard way to hide objects, but this would require likely each product to implement their own way of hiding objects. Each wallet e.g. Petra, Pontem and each marketplace e.g. Tradeport, Wapal, would need to hide them individually.
Functionality for aptos_framework::object::burn
will be re-enabled, but only for the purposes of hiding objects. This
means it removes the final line to move the object to the burn address, and instead just adds a TombStone to the object.
module aptos_framework::object {
public entry fun burn<T: key>(owner: &signer, object: Object<T>) acquires ObjectCore {
let original_owner = signer::address_of(owner);
assert!(is_owner(object, original_owner), error::permission_denied(ENOT_OBJECT_OWNER));
let object_addr = object.inner;
move_to(&create_signer(object_addr), TombStone { original_owner });
}
}
Unburn will still be changed and allowed to be called by users on burnt objects of either the old way or the new way. As long as the user is the direct owner of the object, or the burn address is the direct owner.
module aptos_framework::object {
public entry fun unburn<T: key>(
original_owner: &signer,
object: Object<T>,
) acquires TombStone, ObjectCore {
let object_addr = object.inner;
assert!(exists<TombStone>(object_addr), error::invalid_argument(EOBJECT_NOT_BURNT));
// The new owner of the object can always unburn it, but if it's the burn address, we go to the old functionality
let object_core = borrow_global<ObjectCore>(object_addr);
if (object_core.owner == signer::address_of(original_owner)) {
let TombStone { original_owner: _ } = move_from<TombStone>(object_addr);
} else if (object_core.owner == BURN_ADDRESS) {
// The old functionality
let TombStone { original_owner: original_owner_addr } = move_from<TombStone>(object_addr);
assert!(
original_owner_addr == signer::address_of(original_owner),
error::permission_denied(ENOT_OBJECT_OWNER)
);
transfer_raw_inner(object_addr, original_owner_addr);
} else {
abort error::permission_denied(ENOT_OBJECT_OWNER);
};
}
}
The following new functions will be added to aptos_framework::object
:
module aptos_framework::object {
#[test_only]
public fun burn_object_with_transfer<T: key>(owner: &signer, object: Object<T>) {}
}
This will contain the previous implementation of aptos_framework::object::burn
for purposes of testing with burnt
objects.
TODO: Indexer specification
Full implementation is complete here, with Move Prover specifications aptos-labs/aptos-core#15095
All existing Move unit tests, with the new #[test_only]
function, to ensure unburn
still works properly, as well as
- Move Prover specification checking new burn behavior
- Move Prover specification checking test only behavior matches previous burn behavior
- Move unit test checking new burn behavior
The previous AIP-45 captured the main risks of having the AIP, including having unwanted soulbound
NFTs. Additionally, if any smart contracts built around the burn
function moving to the burn address, it is possible
they would stop working.
However, given that burn
is now just adding Tombstone, there should be
nearly no risk associated with adding this functionality.
This still allows users to unburn
already burnt objects, meaning that users will still have access to items they had
burnt previously.
The result of this AIP should ensure that always the owner can unburn the object. If the object is not at the burn address of 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, then the original owner forfeits their right to unburn the object. This should ensure that the object is always owned by the original owner, and that users cannot transfer unburned objects, and then get them back somehow. Given the soulbound objects are not transferable, even in a burn scenario, there should be no more security issues than there were before.
The expectation is that this should ship as part of the next release after being approved.
- Add back
burn
in any documentation on the aptos.dev website. And explain how the indexers must support it.
- None