Community DAOs
Replaceable DAOs

Replaceable DAOs

Sophia contracts are immutable once deployed, and Superhero's contracts have no proxy, no admin key and no migration hook. A community that wants different governance rules cannot patch DAO.aes. What it can do is deploy a different DAO contract and vote to hand over control. ReplaceableDAO.aes defines the interface that makes that possible, and ChangeDAO is the vote that performs it.

What survives a migration: the AEX-9 token keeps its address, its supply and its holders; the bonding curve keeps its reserve and its price; the community keeps its name and its posts. Only the contract that owns the sale and holds the treasury is replaced.

The interface

A contract that implements all three entrypoints can be the target of a ChangeDAO vote:

EntrypointSignaturePurpose
is_dao() : boolMust return true. Blocks transfers to non-DAO addresses.
get_community_management() : option(CommunityManagement)The linked community management contract, or None.
record_sale_transaction(address, int) : unit, stateful, payableReceive sale proceeds with the buyer and buy price as arguments.

The stock DAO.aes implements all three, so a community's DAO can be replaced by another instance of the same implementation as well as by a custom one.

record_sale_transaction

stateful payable entrypoint record_sale_transaction(buyer: address, buy_price: int) : unit

The AE arrives with the call; the buyer and the buy price arrive as arguments. A replacement DAO can therefore act on income the moment it lands: split it between a treasury and a rewards pool, credit it per buyer, forward a share to a partner contract. The token sale calls it with protected = true, so an aborting DAO does not block a trade, and calls it with zero value as a probe on set_beneficiary, so the entrypoint must accept zero-value calls.

is_dao

ChangeDAO transfers ownership of the token sale, the beneficiary rights to all future proceeds, and the accumulated treasury, in one call. is_dao() returning true is a type check that the target is at least a DAO-shaped contract: an account address, the token address or an unrelated contract does not answer the call. It is not a trust check, since any contract can implement is_dao() = true.

Build a replacement DAO

  1. Write the contract in Sophia. Implement is_dao, get_community_management and record_sale_transaction with exactly the signatures above. Sophia type-checks the interface, so a mismatched arity or a missing payable fails at the call site.
  2. Decide what it does with authority. The replacement becomes the owner and beneficiary of the existing AffiliationBondingCurveTokenSale, and the owner of the existing CommunityManagement. If it does not expose equivalents of add_vote and apply_vote_subject, the community loses the ability to appoint moderators or change its write threshold, because those actions can only be reached by the sale's owner.
  3. Point it at the existing CommunityManagement. apply_vote_subject asserts get_community_management() == new_dao.get_community_management() and aborts the whole migration with NEW_DAO_HAS_TO_REFERENCE_SAME_COMMUNITY_MANAGEMENT if they differ. The stock DAO derives it by asking its factory (factory.get_community_management(token_sale)), so a replacement built the same way needs the factory address and the sale address at deployment.
  4. Deploy it to the same network, and check that is_dao() answers true from an external call before proposing anything.
  5. Fund nothing. The treasury transfers with the migration; the target should start empty.
  6. Publish the source and the bytecode hash so voters can verify that the deployed contract at the proposed address is the code they are being asked to approve.

The migration

A ChangeDAO proposal is an ordinary DAO vote:

  1. A holder at or above the community threshold calls DAO.add_vote(metadata) with subject = ChangeDAO(ct_new_dao...), paying 555 AE.
  2. The vote is open for two weeks.
  3. It needs at least 55% of the voted stake in favour and at least 10% of total supply participating.
  4. Within roughly two days of closing, somebody calls DAO.apply_vote_subject(vote_seq_id).
  5. The old DAO verifies is_dao() on the target, then transfers the treasury, the sale's beneficiary and owner, and ownership of CommunityManagement. On the way it checks that the target references the same community management contract.

If nobody applies it inside the window, the vote expires and nothing moves. The 555 AE is spent and the proposal has to be reopened.

What the migration transfers

ThingTransferred?How
The AE treasuryYes, in fullChain.spend(new_dao_address, Contract.balance)
Token sale beneficiaryYesget_token_sale().set_beneficiary(new_dao_address)
Token sale ownershipYesget_token_sale().set_owner(new_dao_address)
CommunityManagement ownershipYescommunity_management.set_owner(new_dao_address)
The moderator roster, mute list, threshold and metadataUntouchedThey live in CommunityManagement, which is not redeployed
The AEX-9 token, its supply and its holdersUntouchedNot owned by the DAO
The bonding curve and its reserveUntouchedHeld by the sale contract, which is not replaced
The vote historyNot transferredDAO.votes stays on the old contract, which keeps answering votes()

Because CommunityManagement.set_owner is called in the same transaction, the AddModerator, DeleteModerator, ChangeMinimumTokenThreshold and ChangeMetaInfo subjects keep working after a migration, provided the replacement DAO implements equivalents of add_vote and apply_vote_subject to reach them.

A community's governance history after a migration is split across two contracts, and the new DAO's vote ids restart at zero.

What a ChangeDAO vote commits to

  • It is irreversible by the old DAO. Reversing a migration requires the new DAO to offer a ChangeDAO equivalent.
  • is_dao() proves nothing about intent. Any contract can pass the check.
  • The vote approves an address. Unless the source is published and the deployed bytecode matches it, holders are approving the proposer's word.
  • Governance is whatever the replacement implements, and that could be a single owner key.
  • The treasury moves in the same transaction. There is no staged handover, trial period or clawback.

Before voting, check that the source is published, that the bytecode at the proposed address matches it, that the replacement implements proposals and voting, and who controls it.

Related