aptos-move/move-examples/dao/nft_dao/README.md
PR: https://github.com/aptos-labs/aptos-core/pull/5918
Quoted from product specification
Currently there are no easy ways for projects in the ecosystem to engage with their communities post mint. A key part of building a vibrant NFT community (as well as community of other web3 verticals) is to empower holders and supporters to be included in the decision making process of a project via a DAO. To do this, we must provide easy to use DAO management tooling for projects on Aptos to build a DAO where entry is gated by the ownership of a token in a NFT collection.
With the NFT DAO, token holders can
There are multiple roles:
[DAO](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/move-examples/dao/nft_dao/sources/nft_dao.move#L103): this contains all the DAO’s key data fields including DAO resource account signer capability. This data is stored in the DAO resource account.
[Proposal](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/move-examples/dao/nft_dao/sources/nft_dao.move#L139): this contains the proposal info including the functions and their arguments to be executed. The state change of proposal is as below:
[Proposals](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/move-examples/dao/nft_dao/sources/nft_dao.move#L134): this contains all the proposals of each DAO. It maps the proposal id to the Proposal. This is stored in the DAO resource account
[ProposalVotingStatistics](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/move-examples/dao/nft_dao/sources/nft_dao.move#L158): this maps the proposal id to its voting statistics. The voting statistics contain the yes and no counts and the vote of each token_id.
[GovernanceToken](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/move-examples/dao/nft_dao/sources/nft_dao.move#L126): the NFT collection that forms a DAO.
public entry fun create_dao(
admin: &signer,
name: String,
threshold: u64,
voting_duration: u64,
voting_token_collection_creator: address,
collection_name: String,
min_required_proposer_voting_power: u64,
required_proposer_voting_power: u64,
)
Proposer can combine any number of supported functions in one proposal. During resolving, the list of functions will be executed in sequence.
create_proposal(
account: &signer,
nft_dao: address,// resource account address of the nft dao
name: String,// name of the proposal
description: String,// description of the proposal
function_names: vector<String>,// 3 types of functions are supported: (1) "no_op", (2) "transfer_fund" and (3) "offer_nft"
arg_names: vector<vector<String>>,// name of the arguments of the function to be called. The arg here should be the same as the argument used in the function
arg_values: vector<vector<vector<u8>>>,// bcs serailized values of argument values
arg_types:vector<vector<String>>,// types of arguments. currently, we only support string, u8, u64, u128, bool, address.
start_time_sec: u64,// when the voting starts
token_names: vector<String>,// The name of the token, the proposer want to use for proposing
property_versions: vector<u64>,// the property versions of the corresponding tokens, the proposer want to use for proposing
) acquires DAO, Proposals
3 types of functions can be created:
no_op, no automatic execution happens on-chain. Only the proposal and its result is recorded on-chain for the DAO admin to take actions
transfer_fund, the fund will be automatically transferred from DAO resource account to the destination account.
aptos-core/property_map_serde.ts at main · aptos-labs/aptos-core
vote(
account: &signer,
nft_dao: address,
proposal_id: u64,
vote: bool,
token_names: vector<String>,
property_versions: vector<u64>,
)
To generate the batch of token_ids, You need to provide corresponding token_names and property_versions: For example, token_names = (”monkey 1”, “monkey 2”), property_versions = (”1”, “0”)
public entry fun resolve<CoinType>(proposal_id: u64, nft_dao: address)
DAO admin can perform some special operations. This is to provide the NFT creator a way to manage their DAO before the DAO becomes mature. Once the DAO becomes mature, they can get rid of the admin address by updating the field. The functions below are some special DAO admin operations:
DAO Admin transfer
DAO admin can transfer his admin authority through an offer - claim two step process. He can also cancel an pending offer before anyone claims the offer.
offer_admin: offer the admin authority to another account. This offer is directly recorded in the DAO structclaim_admin: the receiver can claim this offer. The contract will set the admin of the DAO to this receiver and empty the pending claimcancel_admin_offer: the admin can also cancel an admin offer by making the pending claim field empty in the DAO struct.DAO admin privileges
admin_resolve: admin of a DAO can directly resolve an pending proposal regardless of voting results and time. After resolving, the contract will record the resolution of the proposal as proposal resolved by admin.admin_veto_proposal: admin can veto an pending proposal regardless of voting results or time. After vetoing, the contract will mark the resolution as vetoed by the admin[ProposalVotingStatistics](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/move-examples/dao/nft_dao/sources/nft_dao.move#L158) from [Proposal](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/move-examples/dao/nft_dao/sources/nft_dao.move#L139),
DAO upgrade upgrading DAO to support integration with creator resource account to gain creator authority to do mint more NFT, update the collection maximum, etc.
DAO migration Have smooth migration when DAO platform contracts have breaking changes
Goal:
Some possible step:
public fun migrate(admin: &signer, dao: address) {
// extract the old_dao's signer_cap
let signer_cap = destroy_dao_and_reclaim_signer_capability(admin, old_dao);
new_dao_platform::create_new_dao(signer_cap, old_dao);
}