Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AIP-5][Discussion] Soulbound and Freezing Token Standard #18

Closed
JacobADevore opened this issue Dec 10, 2022 · 7 comments
Closed

[AIP-5][Discussion] Soulbound and Freezing Token Standard #18

JacobADevore opened this issue Dec 10, 2022 · 7 comments

Comments

@JacobADevore
Copy link

JacobADevore commented Dec 10, 2022

[AIP-5] Soulbound and Freezing Token Standard

This standard allows for the existence of soulbound NFTs and freezing tokens.

Motivation

Soulbound tokens have enormous potential in a wide variety of applications. However, with no standard, soulbound tokens are incompatible with the Aptos-Token standard. Consensus on a common standard is required to allow for broader ecosystem adoption, as well as to make it easier for application developers to build expressive applications on top of the standard.

This AIP (Aptos Improvement Proposal) envisions soulbound tokens as non-transferable NFTs that will unlock primitives such as robust proof of attendance, credentials, distributed governance rights, and much more. However, soulbound tokens must be distinguishable from Aptos-Tokens to provide this utility.

Benefits:

  • Consensus on a soulbound token standard
  • Monitoring a single event store for soulbound and non-soulbound tokens
  • Compatibility with the Aptos-Token standard.

Requirements

  • Tokens minted to an account cannot be transferred.
  • Work with all existing dApps (decentralized applications).
  • Ability to tell if a token is soul bound or not.

Approach

Extend property map to have framework reserved keys

Reserve all keys with “##” for framework usage.

When adding keys to property_map, we need to check if the key starts with “##” and disallow adding or creating property_map with these keys.

We add a token package friend function for adding framework-reserved control flags

// This function should only be called by framework modules
public(friend) fun add_framework_reserved_control_flag(map: &mut PropertyMap, key: String, value: PropertyValue)

Note: after this change, the property_map will become a dedicated data structure for the token package.

  • TODO: Verify property_map has not been widely used by the community and a similar data structure is provided in the framework package.
  • TODO: Validation of the framework key costs of the extra gas used for all the property map creation and inserting. Verify the gas cost.

Annotate the token as soul bound

  • Introduce a framework reserved token property “##freezing_type” of u8 type. When the freezing_type is 0, this value is reserved for the soulbound token.
  • Have new methods to create soulbound tokens by updating the property’s value to 1.
  • Don’t allow withdrawal if the token’s frozen.
// Mint soulbond tokens specifically
public entry create_mint_soulbound_token(creator: &signer, owner: address, collection_name: String, token_name: String){
    // Create token_data
    let token_data_id = create_token_data(...);
    // Mint a token from token_data_id
    let token = mint_token(token_data_id);

    // Offer token to owner
    token_transfers::offer(creator, owner, token_id, ..);
    // Annotate the token property #freezing_type to 0
    add_framework_reserved_control_flag(token.token_properties, "“##freezing_type", 1);
}

public fun is_soulbound_token(token_id: TokenId): bool {
    // Check the token properties
}

public fun withdraw_token(account: &signer, id: TokenId, amount: u64){
    let token_data_id = id.token_data_id;
    // Check the token's properties and validate if the ##freezing_type value is set
    ...
}

Extension

We can extend the approach to support general frozen tokens to token stores. For example, the token owner or creator wants to freeze the token to their token store after an expiration time. We can use ##freezing_type = 2 for the time-based freezing. we can introduce another system-reserved control flag to specify the timestamp ##freezing_expiration_time.

public fun freeze_token(owner: &signer, token_id: TokenId, expiration_time: u64){
    // annotate the token with two properties above
}

public withdraw(...){
    //check if the token is frozen and the expiration time.
}

Other Alternatives

  • Store tokens inside locker modules, the biggest downside being the onboarding of dApps (decentralized applications) to monitor the new locker standard.

Suggested Implementation Timeline

To be determined.

References

--

Special thanks to Bo Wu.

@sherry-x sherry-x changed the title [AIP-4][Discussion] Multi-Composable Token Standard [AIP-5][Discussion] Multi-Composable Token Standard Dec 13, 2022
@movekevin
Copy link
Contributor

This is a really nice AIP writeup! I have one question about how soul bound tokens are supposed to work: When do they become soul bound? Is it when the tokens are minted?

@JacobADevore
Copy link
Author

This is a really nice AIP writeup! I have one question about how soul bound tokens are supposed to work: When do they become soul bound? Is it when the tokens are minted?

Thank you Kevin, I am currently working with @areshand on the exact implementation.

@JacobADevore JacobADevore changed the title [AIP-5][Discussion] Multi-Composable Token Standard [AIP-5][Discussion] Soulbound and Freezing Token Standard Dec 22, 2022
@ghost
Copy link

ghost commented Jan 9, 2023

0x3::token is really gas heavy enough, why we should keep change that?
I recommend an another approach: clone 0x3::token standard to be 0x3::soulbound_token, so you don't need do a verify for withdraw/deposit.
#16 (comment)

@ghost
Copy link

ghost commented Jan 9, 2023

0x3::token is really gas heavy enough, why we should keep change that?
I recommend an another approach: clone 0x3::token standard to be 0x3::soulbound_token, so you don't need do a verify for withdraw/deposit.
#16 (comment)

by doing separate module, you dont need to verify is it soulbound token or normal token, further to reduce the gas fee down. then we could simply to remove transfer function on soulbound token.

@alnoki
Copy link
Contributor

alnoki commented Jan 22, 2023

@JacobADevore I suggest renaming "Soulbound" to either "SignerBound" or "KeyBound" for the following reasons:

  1. Distances a useful blockchain primitive from quasi-religious nomenclature, which could prove exclusionary for individuals with (a)religious/philosophical attitudes that reject unfalsifiable metaphysical claims about souls or consider it blasphemous that blockchain tokens could be bound to a soul. Notably the notion of a soul has historically been abused, most frequently in the service of denying that certain classes of sentient beings lack them (slaves, women, heathens, non-human animals) such that these classes can be subjected to harmful treatment without reproach. Consider that GitHub has changed the default branch name from master to main to avoid references to similarly violent historical institutions.
  2. Clarifies that the token is indeed bound to a key/signer, not the individual person behind the signature, which will (a) avoid confusion in the instance that an account is compromised and (b) serves to increase a security-minded mindset around not losing a private key (as opposed to assuming that someone can "recover" their SingerBound token through appeal to a central Web2 authority, for instance).
  3. Avoids confusion that may arise with having a token affiliated with a multisignature wallet. Here, the term "KeyBound" may be more appropriate than "SignerBound", since there are multiple signers on a multisig wallet, though notably the account is itself treated as having a single conglomerate signature. Either option, however, provides more clarity than the initial name in this proposal, which raises the question of whose soul the token belongs to from the collection of signatories.
  4. Provides more appropriate description within the context of Aptos' key rotation schema, which can theoretically support the transfer of such a token from one person to another: here, someone just has to rotate their authentication key to someone else's public key. And actually, now that I think about it, I suspect that Aptos' key rotation schema might actually prohibit the kind of bound token originally put forth here. If I have some special token in my account, what is to stop someone from paying me paper fiat to rotate the authentication key for the account to a public key that they specify?

Understandably such a renaming may be met with some resistance given that the term "soulbound" has already achieved some amount of prominence, but it is still early enough to alter the trajectory of this norm into a more inclusive and contextually-meaningful term. To this end, I'd especially like to hear your thoughts on reason 1. Also, is it correct that the discussion in reason 4 raises a potentially-insuperable technical challenge?

@davidiw
Copy link
Contributor

davidiw commented Mar 19, 2023

Take a look at proposed AIP-11 and 20. This moves to an object model that allows for seamless soul bound and other functionality without core modifications to the framework. Curious if it is advantageous to continue down this path or to focus on putting our energy behind those. https://github.com/aptos-foundation/AIPs/pull/92/files

@davidiw
Copy link
Contributor

davidiw commented Jul 23, 2023

Closing out as this is addressed by TokenV2 / Token Objects / Digital Assets.

@davidiw davidiw closed this as completed Jul 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants