dao: all documentation updated

This commit is contained in:
skoupidi
2024-12-30 18:36:30 +02:00
parent 005abff8ca
commit c96fb2a0d8
10 changed files with 389 additions and 197 deletions

View File

@@ -5,29 +5,29 @@
-- $ drk dao create_dao \ -- $ drk dao create_dao \
-- PROPOSER_LIMIT \ -- PROPOSER_LIMIT \
-- QUORUM \ -- QUORUM \
-- APPROVAL_RATIO_BASE \ -- EARLY_EXEC_QUORUM \
-- APPROVAL_RATIO_QUOTIENT \ -- APPROVAL_RATIO \
-- GOV_TOKEN_ID > dao.dat -- GOV_TOKEN_ID > dao.toml
-- --
-- dat.dat contains: -- dat.toml contains:
-- --
-- * DAO parameters as listed above -- * DAO parameters as listed above
-- * secret key for the DAO -- * Secret keys for the DAO
-- * bulla blind -- * Bulla blind
-- --
-- We can view the data like so: -- We can view the data like so:
-- --
-- $ drk dao view < dao.dat -- $ drk dao view < dao.toml
-- --
-- Now everyone inside the DAO exchanges dao.dat out of band will import -- Now everyone inside the DAO exchanges dao.toml out of band,
-- it into their wallets. -- will import it into their wallets.
-- --
-- $ drk dao import DAO_NAME < dao.dat -- $ drk dao import DAO_NAME < dao.toml
-- Imported DAO ccb8XXX8af6 -- Imported DAO ccb8XXX8af6
-- --
-- Where ccb8XXX8af6 is the DAO's name. -- Where ccb8XXX8af6 is the DAO's name.
-- --
-- Next one person will mint it on chain -- Next someone that holds all the keys will mint it on chain
-- --
-- $ drk dao mint DAO_NAME > dao_mint_tx -- $ drk dao mint DAO_NAME > dao_mint_tx
-- $ drk broadcast < dao_mint_tx -- $ drk broadcast < dao_mint_tx
@@ -56,8 +56,9 @@
-- RECV_PUBKEY -- RECV_PUBKEY
-- --
-- If we don't have enough tokens to meet the proposer_limit threshold -- If we don't have enough tokens to meet the proposer_limit threshold
-- then this call will simply fail with an error message. Nothing will -- or don't hold the proposer key, then this call will simply fail with
-- be added to the database or sent to the network. -- an error message. Nothing will be added to the database or sent to the
-- network.
-- --
-- Once a proposal has been generated, it can be exported and shared -- Once a proposal has been generated, it can be exported and shared
-- to other participants. -- to other participants.
@@ -73,6 +74,7 @@
-- # DAO::vote() -- # DAO::vote()
-- --
-- You have received a proposal which is active. You can now vote on it. -- You have received a proposal which is active. You can now vote on it.
-- You will see other votes only if you hold the DAO votes view key.
-- --
-- $ drk dao proposals DAO_NAME -- $ drk dao proposals DAO_NAME
-- 0. f6cae63ced53d02b372206a8d3ed5ac03fde18da306a520285fd56e8d031f6cf -- 0. f6cae63ced53d02b372206a8d3ed5ac03fde18da306a520285fd56e8d031f6cf

View File

@@ -2758,11 +2758,6 @@ impl Drk {
))) )))
} }
// Check we know the plaintext data
if proposal.data.is_none() {
return Err(Error::Custom("[dao_vote] Proposal plainext data is empty".to_string()))
}
// Fetch DAO and check its deployed // Fetch DAO and check its deployed
let Ok(dao) = self.get_dao_by_bulla(&proposal.proposal.dao_bulla).await else { let Ok(dao) = self.get_dao_by_bulla(&proposal.proposal.dao_bulla).await else {
return Err(Error::Custom(format!( return Err(Error::Custom(format!(

View File

@@ -35,45 +35,46 @@ testnet user guide.
Note: List is not exhaustive. Missing functionalities that are not part Note: List is not exhaustive. Missing functionalities that are not part
of the guide can be added for future regressions. of the guide can be added for future regressions.
| # | Description | Command | Status | | # | Description | Command | Status |
|----|---------------------------|----------------------------------------------------------|--------------------| |----|------------------------------|-----------------------------------------------------------------|--------|
| 0 | Initialization | wallet --initialize | Pass | | 0 | Initialization | wallet --initialize | Pass |
| 1 | Key generation | wallet --keygen | Pass | | 1 | Key generation | wallet --keygen | Pass |
| 2 | Set default wallet | wallet --default-address {ADDR_ID} | Pass | | 2 | Set default wallet | wallet --default-address {ADDR_ID} | Pass |
| 3 | Default address retrieval | wallet --address | Pass | | 3 | Default address retrieval | wallet --address | Pass |
| 4 | Block scanning | scan | Pass | | 4 | Block scanning | scan | Pass |
| 5 | Block subscribing | subscribe | Pass | | 5 | Block subscribing | subscribe | Pass |
| 6 | Balance retrieval | wallet --balance | Pass | | 6 | Balance retrieval | wallet --balance | Pass |
| 7 | Aliases retrieval | alias show | Pass | | 7 | Aliases retrieval | alias show | Pass |
| 8 | Mint auth generation | token generate-mint | Pass | | 8 | Mint auth generation | token generate-mint | Pass |
| 9 | Mint auths retrieval | token list | Pass | | 9 | Mint auths retrieval | token list | Pass |
| 10 | Alias add | alias add {ALIAS} {TOKEN} | Pass | | 10 | Alias add | alias add {ALIAS} {TOKEN} | Pass |
| 11 | Aliases retrieval | alias show | Pass | | 11 | Aliases retrieval | alias show | Pass |
| 12 | Mint generation | token mint {ALIAS} {AMOUNT} {ADDR} | Pass | | 12 | Mint generation | token mint {ALIAS} {AMOUNT} {ADDR} | Pass |
| 13 | Token freeze | token freeze {ALIAS} | Pass | | 13 | Token freeze | token freeze {ALIAS} | Pass |
| 14 | Transfer | transfer {AMOUNT} {ALIAS} {ADDR} | Pass | | 14 | Transfer | transfer {AMOUNT} {ALIAS} {ADDR} | Pass |
| 15 | Coins retrieval | wallet --coins | Pass | | 15 | Coins retrieval | wallet --coins | Pass |
| 16 | OTC initialization | otc init -v {AMOUNT}:{AMOUNT} -t {ALIAS}:{ALIAS} | Pass | | 16 | OTC initialization | otc init -v {AMOUNT}:{AMOUNT} -t {ALIAS}:{ALIAS} | Pass |
| 17 | OTC join | otc join | Pass | | 17 | OTC join | otc join | Pass |
| 18 | OTC sign | otc sign | Pass | | 18 | OTC sign | otc sign | Pass |
| 19 | DAO create | dao create {LIMIT} {QUORUM} {RATIO} {TOKEN} | Pass | | 19 | DAO create | dao create {LIMIT} {QUORUM} {EARLY_EXEC_QUORUM} {RATIO} {TOKEN} | Pass |
| 20 | DAO view | dao view | Pass | | 20 | DAO view | dao view | Pass |
| 21 | DAO import | dao import | Pass | | 21 | DAO import | dao import | Pass |
| 22 | DAO list | dao list | Pass | | 22 | DAO update keys | dao update-keys | Pass |
| 23 | DAO mint | dao mint {DAO} | Pass | | 23 | DAO list | dao list | Pass |
| 24 | DAO balance | dao balance {DAO} | Pass | | 24 | DAO mint | dao mint {DAO} | Pass |
| 25 | DAO proposals retrieval | dao proposals {DAO} | Pass | | 25 | DAO balance | dao balance {DAO} | Pass |
| 26 | DAO propose a transfer | dao propose-transfer {DAO} {DUR} {AMOUNT} {TOKEN} {ADDR} | Pass | | 26 | DAO proposals retrieval | dao proposals {DAO} | Pass |
| 27 | DAO proposals retrieval | dao proposals {DAO} | Pass | | 27 | DAO propose a transfer | dao propose-transfer {DAO} {DUR} {AMOUNT} {TOKEN} {ADDR} | Pass |
| 28 | DAO proposal retrieval | dao proposal {PROPOSAL_BULLA} | Pass | | 28 | DAO propose generic | dao propose-generic {DAO} {DUR} {AMOUNT} {TOKEN} {ADDR} | Pass |
| 29 | DAO proposal export | dao proposal {PROPOSAL_BULLA} --export | Pass | | 29 | DAO proposal retrieval | dao proposal {PROPOSAL_BULLA} | Pass |
| 30 | DAO proposal import | dao proposal-import | Pass | | 30 | DAO proposal export | dao proposal {PROPOSAL_BULLA} --export | Pass |
| 31 | DAO proposal mint | dao proposal {PROPOSAL_BULLA} --mint-proposal | Pass | | 31 | DAO proposal import | dao proposal-import | Pass |
| 32 | DAO vote | dao vote {PROPOSAL_BULLA} {VOTE} {WEIGHT} | Pass | | 32 | DAO proposal mint | dao proposal {PROPOSAL_BULLA} --mint-proposal | Pass |
| 33 | DAO proposal execution | dao exec {PROPOSAL_BULLA} | Pass | | 33 | DAO vote | dao vote {PROPOSAL_BULLA} {VOTE} {WEIGHT} | Pass |
| 34 | Coins unspend | unspend {COIN} | Pass | | 34 | DAO proposal execution | dao exec {PROPOSAL_BULLA} | Pass |
| 35 | Transaction inspect | inspect | Pass | | 35 | DAO proposal early execution | dao exec --early {PROPOSAL_BULLA} | Pass |
| 36 | Transaction simulate | explorer simulate-tx | Pass | | 36 | Coins unspend | unspend {COIN} | Pass |
| 37 | Transaction broadcast | broadcast | Pass | | 37 | Transaction inspect | inspect | Pass |
| 38 | Transaction attach fee | attach-fee | Pass | | 38 | Transaction simulate | explorer simulate-tx | Pass |
| 39 | Transaction broadcast | broadcast | Pass |
| 40 | Transaction attach fee | attach-fee | Pass |

View File

@@ -5,12 +5,14 @@ set -x
# Path to `drk` binary # Path to `drk` binary
DRK="../../../drk -c drk.toml" DRK="../../../drk -c drk.toml"
# First run the consensus node and the faucet: # First run the darkfid node and the miner:
# #
# ./clean.sh # ./clean.sh
# ./init-wallet.sh
# ./tmux_sessions.sh -vv # ./tmux_sessions.sh -vv
# #
# In another term run the wallet syncing: # In another term run the wallet syncing,
# and wait until some blocks are mined:
# #
# ./sync-wallet.sh # ./sync-wallet.sh
# #
@@ -61,8 +63,8 @@ wait_tokens() {
} }
mint_dao() { mint_dao() {
$DRK dao create 20 10 0.67 MLDY > /tmp/dao.dat $DRK dao create 20 10 10 0.67 MLDY > /tmp/dao.toml
$DRK dao import MiladyMakerDAO < /tmp/dao.dat $DRK dao import MiladyMakerDAO < /tmp/dao.toml
$DRK dao list $DRK dao list
$DRK dao list MiladyMakerDAO $DRK dao list MiladyMakerDAO
@@ -70,19 +72,20 @@ mint_dao() {
} }
wait_dao_mint() { wait_dao_mint() {
while [ "$($DRK dao list MiladyMakerDAO | grep '^Tx hash: ' | awk '{print $3}')" = None ]; do while [ "$($DRK dao list MiladyMakerDAO | grep '^Transaction hash: ' | awk '{print $3}')" = None ]; do
sleep 1 sleep 1
done done
} }
fill_treasury() { fill_treasury() {
PUBKEY="$($DRK dao list 1 | grep '^Public key: ' | cut -d ' ' -f3)" PUBKEY="$($DRK dao list MiladyMakerDAO | grep '^Notes Public key: ' | cut -d ' ' -f4)"
BULLA="$($DRK dao list 1 | grep '^Bulla: ' | cut -d' ' -f2)" SPEND_HOOK="$($DRK dao spend-hook)"
$DRK transfer 20 WCKD "$PUBKEY" --dao "$BULLA" | tee /tmp/xfer.tx | $DRK broadcast BULLA="$($DRK dao list MiladyMakerDAO | grep '^Bulla: ' | cut -d' ' -f2)"
$DRK transfer 20 WCKD "$PUBKEY" "$SPEND_HOOK" "$BULLA" | tee /tmp/xfer.tx | $DRK broadcast
} }
dao_balance() { dao_balance() {
BALANCE=$($DRK dao balance 1 2>/dev/null) BALANCE=$($DRK dao balance MiladyMakerDAO 2>/dev/null)
# No tokens received at all yet # No tokens received at all yet
if echo "$BALANCE" | grep -q "No unspent balances found"; then if echo "$BALANCE" | grep -q "No unspent balances found"; then
echo 0 echo 0
@@ -108,51 +111,44 @@ wait_dao_treasury() {
propose() { propose() {
MY_ADDR=$($DRK wallet --address) MY_ADDR=$($DRK wallet --address)
$DRK dao balance MiladyMakerDAO PROPOSAL="$($DRK dao propose-transfer MiladyMakerDAO 1 5 WCKD "$MY_ADDR" | cut -d' ' -f3)"
$DRK dao propose MiladyMakerDAO "$MY_ADDR" 0.1 WCKD > /tmp/propose.tx $DRK dao proposal "$PROPOSAL" --mint-proposal > /tmp/propose.tx
$DRK broadcast < /tmp/propose.tx $DRK broadcast < /tmp/propose.tx
} }
proposal_status() {
PROPOSALS_LEN=$($DRK dao proposals MiladyMakerDAO | wc -l)
if [ "$PROPOSALS_LEN" = 0 ]; then
echo 0
else
echo 1
fi
}
wait_proposal() { wait_proposal() {
while [ "$(proposal_status)" = 0 ]; do PROPOSAL="$($DRK dao proposals MiladyMakerDAO | cut -d' ' -f2)"
while [ "$($DRK dao proposal $PROPOSAL | grep '^Proposal transaction hash: ' | awk '{print $4}')" = None ]; do
sleep 1 sleep 1
done done
} }
vote() { vote() {
PROPOSAL_ID=1 PROPOSAL="$($DRK dao proposals MiladyMakerDAO | cut -d' ' -f2)"
$DRK dao vote MiladyMakerDAO "$PROPOSAL_ID" 1 20 > /tmp/dao-vote.tx $DRK dao vote "$PROPOSAL" 1 > /tmp/dao-vote.tx
$DRK broadcast < /tmp/dao-vote.tx $DRK broadcast < /tmp/dao-vote.tx
} }
vote_status() {
PROPOSAL_ID=1
$DRK dao proposal MiladyMakerDAO "$PROPOSAL_ID" | grep -q yes
echo $?
}
wait_vote() { wait_vote() {
while [ "$(vote_status)" != 0 ]; do PROPOSAL="$($DRK dao proposals MiladyMakerDAO | cut -d' ' -f2)"
while [ "$($DRK dao proposal $PROPOSAL | grep '^Current proposal outcome: ' | awk '{print $4}')" != "Approved" ]; do
sleep 1 sleep 1
done done
} }
do_exec() { do_exec() {
PROPOSAL_ID=1 PROPOSAL="$($DRK dao proposals MiladyMakerDAO | cut -d' ' -f2)"
$DRK dao exec MiladyMakerDAO "$PROPOSAL_ID" > /tmp/dao-exec.tx $DRK dao exec --early $PROPOSAL > /tmp/dao-exec.tx
$DRK broadcast < /tmp/dao-exec.tx $DRK broadcast < /tmp/dao-exec.tx
} }
$DRK wallet --keygen wait_exec() {
PROPOSAL="$($DRK dao proposals MiladyMakerDAO | cut -d' ' -f2)"
while [ "$($DRK dao proposal $PROPOSAL | grep '^Proposal was executed on transaction: ' | awk '{print $6}')" = None ]; do
sleep 1
done
}
mint_tokens mint_tokens
wait_tokens wait_tokens
mint_dao mint_dao
@@ -164,3 +160,4 @@ wait_proposal
vote vote
wait_vote wait_vote
do_exec do_exec
wait_exec

View File

@@ -3,7 +3,7 @@ set -e
set -x set -x
# Path to `drk` binary # Path to `drk` binary
DRK="../../../drk -vv -c drk.toml" DRK="../../../drk -c drk.toml"
while true; do while true; do
if $DRK ping 2> /dev/null; then if $DRK ping 2> /dev/null; then

View File

@@ -14,49 +14,70 @@ these bullas.
## `DAO::mint()`: Establishing the DAO ## `DAO::mint()`: Establishing the DAO
From `darkfi/src/contract/dao/proof/dao-mint.zk`: From `darkfi/src/contract/dao/proof/mint.zk`:
```zkas ```zkas
bulla = poseidon_hash( bulla = poseidon_hash(
dao_proposer_limit, proposer_limit,
dao_quorum, quorum,
dao_approval_ratio_quot, early_exec_quorum,
dao_approval_ratio_base, approval_ratio_quot,
approval_ratio_base,
gov_token_id, gov_token_id,
dao_public_x, notes_public_x,
dao_public_y, notes_public_y,
dao_bulla_blind, proposer_public_x,
); proposer_public_y,
proposals_public_x,
proposals_public_y,
votes_public_x,
votes_public_y,
exec_public_x,
exec_public_y,
early_exec_public_x,
early_exec_public_y,
bulla_blind,
);
``` ```
Brief description of the DAO bulla params: Brief description of the DAO bulla params:
* **proposer_limit**: minimum deposit required for proposals to become valid. * **proposer_limit**: the minimum amount of governance tokens needed to open a proposal.
TODO: rename to `min_deposit`. * **quorum**: minimal threshold of participating total tokens needed for a proposal to pass.
* **quorum**: minimum threshold of votes before it's allowed to pass.
Normally this is implemented as min % of voting power, but we do this in Normally this is implemented as min % of voting power, but we do this in
absolute value absolute value
* **approval_ratio**: proportion of winners to losers for a proposal to pass. * **early_exec_quorum**: minimal threshold of participating total tokens needed for a proposal
to be considered as strongly supported, enabling early execution. Must be greater or equal
to normal quorum.
* **approval_ratio**: the ratio of winning/total votes needed for a proposal to pass.
* **gov_token_id**: DAO's governance token ID.
* **notes_public_key**: notes(coins) decryption public key
* **proposer_public_key**: proposals creator public key
* **proposals_public_key**: proposals viewer public key
* **votes_public_key**: votes viewer public key
* **exec_public_key**: proposals executor public key
* **early_exec_public_key**: strongly supported proposals executor public key
* **bulla_blind**: bulla blind
Currently there is no notion of veto although it could be trivially added DAO creators/founders have full control on how they want to configure and share
if desired. the actions keys, giving them the ability to veto if needed.
## `DAO::propose()`: Propose the Vote ## `DAO::propose()`: Propose the Vote
From `darkfi/src/contract/dao/proof/dao-propose-main.zk`: From `darkfi/src/contract/dao/proof/propose-main.zk`:
```zkas ```zkas
proposal_bulla = poseidon_hash( proposal_bulla = poseidon_hash(
proposal_dest_x, proposal_auth_calls_commit,
proposal_dest_y, proposal_creation_blockwindow,
proposal_amount, proposal_duration_blockwindows,
proposal_token_id, proposal_user_data,
dao_bulla, dao_bulla,
proposal_blind, proposal_blind,
); );
``` ```
We create a proposal which will send tokens to the dest provided. Proposals are committed to a specific calls set, therefore they
This will soon be changed to be generic. Proposals will commit to are generic and we can attach various calls to it. We will use a
calling params or code instead. money transfer as the example for rest sections.
## `DAO::vote()`: Vote on a Proposal ## `DAO::vote()`: Vote on a Proposal
@@ -366,37 +387,52 @@ be executed early. We should add this option to DarkFi DAO params.
## Suggested Changes ## Suggested Changes
DAO params: ~~DAO params:~~
* Voting period (currently called duration) should be moved from proposals to * ~~Voting period (currently called duration) should be moved from proposals to
DAO params. DAO params.~~
* upgrayedd: we should just have minimum allowed period in the DAO, but keep * ~~upgrayedd: we should just have minimum allowed period in the DAO, but keep
this param in the proposal. this param in the proposal.~~
* Window (currently set at 4 hours of blocks) should be customizable. We need a * ~~Window (currently set at 4 hours of blocks) should be customizable. We need a
terminology for the unit of time. Maybe `time_units`. terminology for the unit of time. Maybe `time_units`.~~
* This should be switched from block index to using timestamps. * ~~This should be switched from block index to using timestamps.
See the quoted paragraph in the OpenZeppelin section above for the See the quoted paragraph in the OpenZeppelin section above for the
reasoning. reasoning.~~
* upgrayedd: stick with block index. * ~~upgrayedd: stick with block index.~~
* Early execution bool flag. If true, then passed proposals can be `exec()`uted * ~~Early execution bool flag. If true, then passed proposals can be `exec()`uted
asap, otherwise the entire voting period must pass. asap, otherwise the entire voting period must pass.~~
No changes to proposals, except moving duration to DAO params. ~~No changes to proposals, except moving duration to DAO params.~~
Currently the DAO public key is used for: > Resolution:
> The full voting period must pass in order to be able to execute a proposal.
> A new configuration parameter was introduced, called early exec quorum,
> where we can define the quorum for a proposal to be considered as strongly
> supported/voted on, which should always be greater or equal to normal quorum.
> With this addition, we can execute proposals before the voting period has
> passed, if they were accepted.
* Encrypting votes. ~~Currently the DAO public key is used for:~~
* Calling exec.
We should introduce a new key: * ~~Encrypting votes.~~
* ~~Calling exec.~~
* Proposer role, which is needed to make proposals. This can be shared openly ~~We should introduce a new key:~~
* ~~Proposer role, which is needed to make proposals. This can be shared openly
amongst DAO members if they wish to remove the restriction on who can make amongst DAO members if they wish to remove the restriction on who can make
proposals. proposals.~~
* OZ does this with a canceller role that has the ability to cancel * ~~OZ does this with a canceller role that has the ability to cancel
proposals. proposals.~~
* In the future allow multiple keys for this so you can see who makes * ~~In the future allow multiple keys for this so you can see who makes
proposals. proposals.~~
> Resolution:
> DAO public key was split into six other keys, providing maximum control over
> each DAO action. Now the DAO creator can define who can view the coin notes,
> create proposals, view proposals, view votes, execute proposals and early
> execute proposals. They can configure the keys however they like like reusing
> keys if they want some actions to have same key.
Optional: many DAOs these days implement Abstain, which increases the quorum Optional: many DAOs these days implement Abstain, which increases the quorum
without voting yes. This is for when you want to weak support a measure, without voting yes. This is for when you want to weak support a measure,

View File

@@ -7,12 +7,16 @@ The governance process is divided in a few steps that are outlined below:
* **Exec:** if the proposal passes within the time limit then the proposal is * **Exec:** if the proposal passes within the time limit then the proposal is
executed. executed.
> Note:
> There is a special case where a proposal can be executed before voting period
> passes, if its strongly supported, based on the configured early execution quorum.
## Propose ## Propose
To prevent spam, proposals must be submitted by holders with a certain number To prevent spam, proposals must be submitted by holders with a certain number
of governance tokens. Several members of the DAO can add inputs separately to of governance tokens and the DAO proposers key. Several members of the DAO can
a proposal before it is posted on chain so that their combined inputs meet the add inputs separately to a proposal before it is posted on chain so that their
proposal governance token limit. combined inputs meet the proposal governance token limit.
Once proposals are posted on chain, they are immediately active. Once proposals are posted on chain, they are immediately active.
@@ -46,8 +50,14 @@ no longer vote on the proposal, and it is considered *expired*.
### Quorum ### Quorum
Quorum is defined as the minimum absolute number of governance tokens voting Quorum is defined as the minimal threshold of participating total governance tokens need for
yes required for a proposal to become accepted. a proposal to pass. Normally this is implemented as min % of voting power, but we do this in
absolute value.
### Early Execution Quorum
Early execytuib quorum is defined as the minimal threshold of participating total tokens needed
for a proposal to be considered as strongly supported, enabling early execution. Must be greater
or equal to normal quorum.
### Approval Ratio ### Approval Ratio

View File

@@ -13,20 +13,31 @@ The DAO contains the main parameters that define DAO operation:
come from multiple token holders. come from multiple token holders.
* Quorum $Q$ specifies the absolute minimum number of tokens required for * Quorum $Q$ specifies the absolute minimum number of tokens required for
before a proposal can be accepted. before a proposal can be accepted.
* Early exec quorum $EEQ$ specifies the absolute minimum number of tokens
required for before a proposal can be considered as strongly accepted.
* The approval ratio $A^\%$ is a tuple that specifies the minimum theshold * The approval ratio $A^\%$ is a tuple that specifies the minimum theshold
of affirmative yes votes for a proposal to become accepted. of affirmative yes votes for a proposal to become accepted.
* The public key $PK$ serves a dual role for both encrypted notes, and as * Notes public key $NPK$ controls who can view encrypted notes.
a key to authorize accepted proposals to be executed. * Proposer public key $pPK$ controls who can mint proposals.
This key may be shared widely with all DAO members or within a privileged * Proposals public key $PPK$ controls who can view the proposals.
group. * Votes public key $VPK$ controls who can view votes.
* Executor public key $EPK$ controls who can execute proposals.
* Early executor public key $EEPK$ controls who can execute proposals that
are strongly accepted.
Define the DAO params Define the DAO params
$$ \begin{aligned} $$ \begin{aligned}
\t{Params}_\t{DAO}.L &∈ ℕ₆₄ \\ \t{Params}_\t{DAO}.L &∈ ℕ₆₄ \\
\t{Params}_\t{DAO}.Q &∈ ℕ₆₄ \\ \t{Params}_\t{DAO}.Q &∈ ℕ₆₄ \\
\t{Params}_\t{DAO}.EEQ &∈ ℕ₆₄ \\
\t{Params}_\t{DAO}.A^\% &∈ ℕ₆₄ × ℕ₆₄ \\ \t{Params}_\t{DAO}.A^\% &∈ ℕ₆₄ × ℕ₆₄ \\
\t{Params}_\t{DAO}.τ &∈ 𝔽ₚ \\ \t{Params}_\t{DAO}.τ &∈ 𝔽ₚ \\
\t{Params}_\t{DAO}.\t{PK} &∈ ℙₚ \t{Params}_\t{DAO}.\t{NPK} &∈ ℙₚ \\
\t{Params}_\t{DAO}.\t{pPK} &∈ ℙₚ \\
\t{Params}_\t{DAO}.\t{PPK} &∈ ℙₚ \\
\t{Params}_\t{DAO}.\t{VPK} &∈ ℙₚ \\
\t{Params}_\t{DAO}.\t{EPK} &∈ ℙₚ \\
\t{Params}_\t{DAO}.\t{EEPK} &∈ ℙₚ
\end{aligned} $$ \end{aligned} $$
where the approval ratio $\t{Approval}^\% = (q, d)$ defines the equivalence where the approval ratio $\t{Approval}^\% = (q, d)$ defines the equivalence
class $[\frac{q}{d}]$ of fractions defined by $q₁d₂ = q₂d₁ ⟺ [\frac{q₁}{d₁}] \~ [\frac{q₂}{d₂}]$. class $[\frac{q}{d}]$ of fractions defined by $q₁d₂ = q₂d₁ ⟺ [\frac{q₁}{d₁}] \~ [\frac{q₂}{d₂}]$.
@@ -36,7 +47,22 @@ class $[\frac{q}{d}]$ of fractions defined by $q₁d₂ = q₂d₁ ⟺ [\frac{q
``` ```
$$ \t{Bulla}_\t{DAO} : \t{Params}_\t{DAO} × 𝔽ₚ → 𝔽ₚ $$ $$ \t{Bulla}_\t{DAO} : \t{Params}_\t{DAO} × 𝔽ₚ → 𝔽ₚ $$
$$ \t{Bulla}_\t{DAO}(p, b_\t{DAO}) = \t{Bulla}(₆₄2𝔽ₚ(p.L), ₆₄2𝔽ₚ(p.Q), ₆₄2𝔽ₚ(p.A^\%), p.τ, \mathcal{X}(p.\t{PK}), \mathcal{Y}(p.\t{PK}), b_\t{DAO}) $$ $$ \begin{aligned}
\t{Bulla}_\t{DAO}(p, b_\t{DAO}) = \t{Bulla}( \\
₆₄2𝔽ₚ(p.L), \\
₆₄2𝔽ₚ(p.Q), \\
₆₄2𝔽ₚ(p.EEQ), \\
₆₄2𝔽ₚ(p.A^\%), \\
p.τ, \\
\mathcal{X}(p.\t{NPK}), \mathcal{Y}(p.\t{NPK}), \\
\mathcal{X}(p.\t{pPK}), \mathcal{Y}(p.\t{pPK}), \\
\mathcal{X}(p.\t{PPK}), \mathcal{Y}(p.\t{PPK}), \\
\mathcal{X}(p.\t{VPK}), \mathcal{Y}(p.\t{VPK}), \\
\mathcal{X}(p.\t{EPK}), \mathcal{Y}(p.\t{EPK}), \\
\mathcal{X}(p.\t{EEPK}), \mathcal{Y}(p.\t{EEPK}), \\
b_\t{DAO} \\
)
\end{aligned} $$
## Proposals ## Proposals

View File

@@ -23,7 +23,7 @@ the DAO params and then add the bulla to the set.
* Wallet builder: `src/contract/dao/src/client/mint.rs` * Wallet builder: `src/contract/dao/src/client/mint.rs`
* WASM VM code: `src/contract/dao/src/entrypoint/mint.rs` * WASM VM code: `src/contract/dao/src/entrypoint/mint.rs`
* ZK proof: `src/contract/dao/proof/dao-mint.zk` * ZK proof: `src/contract/dao/proof/mint.zk`
### Function Params ### Function Params
@@ -45,22 +45,41 @@ Let there be a prover auxiliary witness inputs:
$$ \begin{aligned} $$ \begin{aligned}
L &∈ ℕ₆₄ \\ L &∈ ℕ₆₄ \\
Q &∈ ℕ₆₄ \\ Q &∈ ℕ₆₄ \\
EEQ &∈ ℕ₆₄ \\
A^\% &∈ ℕ₆₄ × ℕ₆₄ \\ A^\% &∈ ℕ₆₄ × ℕ₆₄ \\
τ &∈ 𝔽ₚ \\ τ &∈ 𝔽ₚ \\
x &∈ 𝔽ₚ \\ Nx &∈ 𝔽ₚ \\
px &∈ 𝔽ₚ \\
Px &∈ 𝔽ₚ \\
Vx &∈ 𝔽ₚ \\
Ex &∈ 𝔽ₚ \\
EEx &∈ 𝔽ₚ \\
b_\t{DAO} &∈ 𝔽ₚ b_\t{DAO} &∈ 𝔽ₚ
\end{aligned} $$ \end{aligned} $$
Attach a proof $π$ such that the following relations hold: Attach a proof $π$ such that the following relations hold:
**Proof of public key ownership** &emsp; $\t{PK} = \t{DerivePubKey}(x)$. **Proof of notes public key ownership** &emsp; $\t{NPK} = \t{DerivePubKey}(Nx)$.
**DAO bulla integrity** &emsp; $ = \t{Bulla}_\t{DAO}((L, Q, A^\%, τ, \t{PK}), b_\t{DAO})$ **Proof of proposer public key ownership** &emsp; $\t{pPK} = \t{DerivePubKey}(px)$.
**Proof of proposals public key ownership** &emsp; $\t{PPK} = \t{DerivePubKey}(Px)$.
**Proof of votes public key ownership** &emsp; $\t{VPK} = \t{DerivePubKey}(Vx)$.
**Proof of executor public key ownership** &emsp; $\t{EPK} = \t{DerivePubKey}(Ex)$.
**Proof of early executor public key ownership** &emsp; $\t{EEPK} = \t{DerivePubKey}(EEx)$.
**Proof that early execution quorum is greater than normal quorum** &emsp; $Q <= EEQ1$.
**DAO bulla integrity** &emsp; $ = \t{Bulla}_\t{DAO}((L, Q, EEQ, A^\%, τ,
\t{NPK}, \t{pPK}, \t{PPK}, \t{VPK}, \t{EPK}, \t{EEPK}), b_\t{DAO})$
### Signatures ### Signatures
There should be a single signature attached, which uses There should be a single signature attached, which uses
$\t{PK}$ as the signature public key. $\t{NPK}$ as the signature public key.
## Propose ## Propose
@@ -89,8 +108,8 @@ A proposal contains a list of auth calls as specified in [Auth Calls](model.md#a
* Wallet builder: `src/contract/dao/src/client/propose.rs` * Wallet builder: `src/contract/dao/src/client/propose.rs`
* WASM VM code: `src/contract/dao/src/entrypoint/propose.rs` * WASM VM code: `src/contract/dao/src/entrypoint/propose.rs`
* ZK proofs: * ZK proofs:
* `src/contract/dao/proof/dao-propose-main.zk` * `src/contract/dao/proof/propose-main.zk`
* `src/contract/dao/proof/dao-propose-input.zk` * `src/contract/dao/proof/propose-input.zk`
### Function Params ### Function Params
@@ -146,6 +165,8 @@ Attach a proof $π_𝒫 $ such that the following relations hold:
**Governance token commit** &emsp; export the DAO token ID as an encrypted pedersen **Governance token commit** &emsp; export the DAO token ID as an encrypted pedersen
commit $T = \t{PedersenCommit}(d.τ, b_τ)$ where $T = ∑_{i ∈ 𝐢} Tᵢ$. commit $T = \t{PedersenCommit}(d.τ, b_τ)$ where $T = ∑_{i ∈ 𝐢} Tᵢ$.
**Proof of proposer public key ownership** &emsp; $\t{pPK} = \t{DerivePubKey}(px)$.
**DAO bulla integrity** &emsp; $𝒟 = \t{Bulla}_\t{DAO}(d, b_d)$ **DAO bulla integrity** &emsp; $𝒟 = \t{Bulla}_\t{DAO}(d, b_d)$
**DAO existence** &emsp; $R_\t{DAO} = \t{MerkleRoot}(ψ, Π, 𝒟 )$ **DAO existence** &emsp; $R_\t{DAO} = \t{MerkleRoot}(ψ, Π, 𝒟 )$
@@ -200,8 +221,8 @@ public key $i.\t{PK}_σ$.
After `DAO::propose()` is called, DAO members can then call this contract After `DAO::propose()` is called, DAO members can then call this contract
function. Using a similar method as before, they attach inputs proving ownership function. Using a similar method as before, they attach inputs proving ownership
of a certain value of governance tokens. This is how we achieve token weighted of a certain value of governance tokens. This is how we achieve token weighted
voting. The result of the vote is communicated to other DAO members through the voting. The result of the vote is communicated to DAO members that can view votes
encrypted note $\t{note}$. through the encrypted note $\t{note}$.
Each nullifier $𝒩 $ is stored uniquely per proposal. Additionally as before, Each nullifier $𝒩 $ is stored uniquely per proposal. Additionally as before,
there is a leakage here connecting the coins when spent. However prodigious there is a leakage here connecting the coins when spent. However prodigious
@@ -220,8 +241,8 @@ and the yes votes by $V_\t{yes}$.
* Wallet builder: `src/contract/dao/src/client/vote.rs` * Wallet builder: `src/contract/dao/src/client/vote.rs`
* WASM VM code: `src/contract/dao/src/entrypoint/vote.rs` * WASM VM code: `src/contract/dao/src/entrypoint/vote.rs`
* ZK proofs: * ZK proofs:
* `src/contract/dao/proof/dao-vote-main.zk` * `src/contract/dao/proof/vote-main.zk`
* `src/contract/dao/proof/dao-vote-input.zk` * `src/contract/dao/proof/vote-input.zk`
### Function Params ### Function Params
@@ -247,8 +268,9 @@ selected such that their sum is a valid field element in $𝔽ₚ$ so the blind
for $∑ V$ can be verifiably encrypted. Likewise we do the same for the blind for $∑ V$ can be verifiably encrypted. Likewise we do the same for the blind
used to calculate $V_\t{yes}$. used to calculate $V_\t{yes}$.
This allows DAO members to securely receive all secrets for votes on a proposal. This allows DAO members that hold the votes key to securely receive all secrets
This is then used in the Exec phase when we work on the sum of DAO votes. for votes on a proposal. This is then used in the Exec phase when we work on the
sum of DAO votes.
```rust ```rust
{{#include ../../../../../src/contract/dao/src/model.rs:dao-vote-params}} {{#include ../../../../../src/contract/dao/src/model.rs:dao-vote-params}}
@@ -300,7 +322,7 @@ and then check $t_\t{now} < t_\t{end}$.
**Verifiable encryption of vote commit secrets** &emsp; **Verifiable encryption of vote commit secrets** &emsp;
let $𝐧 = (o, b_y, v, bᵥ)$, and verify let $𝐧 = (o, b_y, v, bᵥ)$, and verify
$\t{enc\_vote} = \t{ElGamal}.\t{Encrypt}(𝐧, \t{esk}, d.\t{PK})$. $\t{enc\_vote} = \t{ElGamal}.\t{Encrypt}(𝐧, \t{esk}, d.\t{VPK})$.
For each input $i ∈ 𝐢$, perform the following checks: For each input $i ∈ 𝐢$, perform the following checks:
@@ -343,8 +365,8 @@ public key $i.\t{PK}_σ$.
Exec is the final stage after voting is [Accepted](concepts.md#proposal-states). Exec is the final stage after voting is [Accepted](concepts.md#proposal-states).
It checks the correct voting conditions have been met in accordance with the It checks that voting has passed, and correct conditions have been met, in accordance
[DAO params](model.md#dao) such as quorum and approval ratio. with the [DAO params](model.md#dao) such as quorum and approval ratio.
$V_\t{yes}$ and $V_\t{all}$ are pedersen commits to $v_\t{yes}$ and $v_\t{all}$ respectively. $V_\t{yes}$ and $V_\t{all}$ are pedersen commits to $v_\t{yes}$ and $v_\t{all}$ respectively.
It also checks that child calls have been attached in accordance with the auth It also checks that child calls have been attached in accordance with the auth
@@ -354,7 +376,9 @@ function. Currently the DAO provides a single preset for executing
* Wallet builder: `src/contract/dao/src/client/exec.rs` * Wallet builder: `src/contract/dao/src/client/exec.rs`
* WASM VM code: `src/contract/dao/src/entrypoint/exec.rs` * WASM VM code: `src/contract/dao/src/entrypoint/exec.rs`
* ZK proof: `src/contract/dao/proof/dao-exec.zk` * ZK proofs:
* `src/contract/dao/proof/exec.zk`
* `src/contract/dao/proof/early-exec.zk`
### Function Params ### Function Params
@@ -402,11 +426,16 @@ $$ \begin{aligned}
\end{aligned} $$ \end{aligned} $$
Attach a proof $π$ such that the following relations hold: Attach a proof $π$ such that the following relations hold:
**Proof of executor public key ownership** &emsp; $\t{EPK} = \t{DerivePubKey}(Ex)$.
**DAO bulla integrity** &emsp; $𝒟 = \t{Bulla}_\t{DAO}(d, b_d)$ **DAO bulla integrity** &emsp; $𝒟 = \t{Bulla}_\t{DAO}(d, b_d)$
**Proposal bulla integrity** &emsp; $𝒫 = \t{Bulla}_\t{Proposal}(p, b_p)$ **Proposal bulla integrity** &emsp; $𝒫 = \t{Bulla}_\t{Proposal}(p, b_p)$
where $p.𝒜 = 𝒜 $. where $p.𝒜 = 𝒜 $.
**Proposal has expired** &emsp; let $t_\t{end} = ₆₄2𝔽ₚ(p.t₀) + ₆₄2𝔽ₚ(p.D)$,
and then check $t_\t{end} <= t_\t{now}$.
**Yes vote commit** &emsp; $V_\t{yes} = \t{PedersenCommit}(v_y, b_y)$ **Yes vote commit** &emsp; $V_\t{yes} = \t{PedersenCommit}(v_y, b_y)$
**All vote commit** &emsp; $V_\t{all} = \t{PedersenCommit}(v_a, b_a)$ **All vote commit** &emsp; $V_\t{all} = \t{PedersenCommit}(v_a, b_a)$
@@ -417,6 +446,46 @@ where $p.𝒜 = 𝒜 $.
$\frac{A^\%_q}{A^\%_b} ≤ \frac{v_y}{v_a}$. Instead we perform the $\frac{A^\%_q}{A^\%_b} ≤ \frac{v_y}{v_a}$. Instead we perform the
equivalent check that $v_a A^\%_q ≤ v_y A^\%_b$. equivalent check that $v_a A^\%_q ≤ v_y A^\%_b$.
### EarlyExec
This is a special case of Exec for when we want to execute a strongly accepted proposal
before voting period has passed. A different proof statement is used in this case.
Let there be prover auxiliary witness inputs:
$$ \begin{aligned}
p &∈ \t{Params}_\t{Proposal} \\
b_p &∈ 𝔽ₚ \\
d &∈ \t{Params}_\t{DAO} \\
b_d &∈ 𝔽ₚ \\
v_y &∈ 𝔽ₚ \\
v_a &∈ 𝔽ₚ \\
b_y &∈ 𝔽ᵥ \\
b_a &∈ 𝔽ᵥ \\
\end{aligned} $$
Attach a proof $π$ such that the following relations hold:
**Proof of executor public key ownership** &emsp; $\t{EPK} = \t{DerivePubKey}(Ex)$.
**Proof of early executor public key ownership** &emsp; $\t{EEPK} = \t{DerivePubKey}(EEx)$.
**DAO bulla integrity** &emsp; $𝒟 = \t{Bulla}_\t{DAO}(d, b_d)$
**Proposal bulla integrity** &emsp; $𝒫 = \t{Bulla}_\t{Proposal}(p, b_p)$
where $p.𝒜 = 𝒜 $.
**Proposal has not expired** &emsp; let $t_\t{end} = ₆₄2𝔽ₚ(p.t₀) + ₆₄2𝔽ₚ(p.D)$,
and then check $t_\t{now} < t_\t{end}$.
**Yes vote commit** &emsp; $V_\t{yes} = \t{PedersenCommit}(v_y, b_y)$
**All vote commit** &emsp; $V_\t{all} = \t{PedersenCommit}(v_a, b_a)$
**All votes pass early execution quorum** &emsp; $EEQ ≤ v_a$
**Approval ratio satisfied** &emsp; we wish to check that
$\frac{A^\%_q}{A^\%_b} ≤ \frac{v_y}{v_a}$. Instead we perform the
equivalent check that $v_a A^\%_q ≤ v_y A^\%_b$.
### Signatures ### Signatures
No signatures are attached. No signatures are attached.
@@ -437,8 +506,8 @@ DAO treasury but be unspendable.
* Wallet builder: `src/contract/dao/src/client/auth_xfer.rs` * Wallet builder: `src/contract/dao/src/client/auth_xfer.rs`
* WASM VM code: `src/contract/dao/src/entrypoint/auth_xfer.rs` * WASM VM code: `src/contract/dao/src/entrypoint/auth_xfer.rs`
* ZK proofs: * ZK proofs:
* `src/contract/dao/proof/dao-auth-money-transfer.zk` * `src/contract/dao/proof/auth-money-transfer.zk`
* `src/contract/dao/proof/dao-auth-money-transfer-enc-coin.zk` * `src/contract/dao/proof/auth-money-transfer-enc-coin.zk`
### Function Params ### Function Params

View File

@@ -8,6 +8,7 @@ Let's create a DAO with the following parameters:
* Proposer limit: `20` * Proposer limit: `20`
* Quorum: `10` * Quorum: `10`
* Early execution quorum: `10`
* Approval ratio: `0.67` * Approval ratio: `0.67`
* Governance token: `MLDY` * Governance token: `MLDY`
@@ -20,17 +21,21 @@ $ ./drk help dao create
Let's create our DAO. Let's create our DAO.
``` ```
$ ./drk dao create 20 10 0.67 MLDY > dao_mldy.dat $ ./drk dao create 20 10 10 0.67 MLDY > dao_mldy.toml
$ ./drk dao view < dao_mldy.dat $ ./drk dao view < dao_mldy.toml
``` ```
Now this file can be shared amongst all dao members, so they Since its a normal `toml` file, you may open it with you favourite
hold the generated DAO information and keys. The view command editor, modify they keys configuration and/or keep different versions
will show us the parameters. If everything looks fine, we can for different members. By default all keys are different, so its up
now import it into our wallet: to the DAO founders to chose what configuration they are going to use.
After configuring the file(s) properly, it can be shared amonst the
dao members, so they hold the generated DAO information and keys.
The view command will show us the parameters. If everything looks fine,
we can now import it into our wallet:
``` ```
$ ./drk dao import MiladyMakerDAO < dao_mldy.dat $ ./drk dao import MiladyMakerDAO < dao_mldy.toml
$ ./drk dao list $ ./drk dao list
$ ./drk dao list MiladyMakerDAO $ ./drk dao list MiladyMakerDAO
``` ```
@@ -39,7 +44,8 @@ $ ./drk dao list MiladyMakerDAO
If parameters are shown, this means the DAO was successfully imported If parameters are shown, this means the DAO was successfully imported
into our wallet. We use the DAO name to reference it. Now we can create into our wallet. We use the DAO name to reference it. Now we can create
a transaction that will mint the DAO on-chain, and broadcast it: a transaction that will mint the DAO on-chain, if we hold all its keys,
and broadcast it:
``` ```
$ ./drk dao mint MiladyMakerDAO > dao_mldy_mint_tx $ ./drk dao mint MiladyMakerDAO > dao_mldy_mint_tx
@@ -55,19 +61,19 @@ should see a leaf position and a transaction hash when running
Let's send some tokens to the DAO's treasury so we're able to make Let's send some tokens to the DAO's treasury so we're able to make
a proposal to send those somewhere. First, find the DAO bulla, the a proposal to send those somewhere. First, find the DAO bulla, the
dao contract spend hook and the DAO public key a d then create a dao contract spend hook and the DAO notes public key and then create
transfer transaction: a transfer transaction:
``` ```
$ ./drk dao spend-hook $ ./drk dao spend-hook
$ ./drk dao list MiladyMakerDAO $ ./drk dao list MiladyMakerDAO
$ ./drk transfer 10 WCKD {DAO_PUBLIC_KEY} \ $ ./drk transfer 10 WCKD {DAO_NOTES_PUBLIC_KEY} \
{DAO_CONTRACT_SPEND_HOOK} {DAO_BULLA} > dao_mldy_transfer_tx {DAO_CONTRACT_SPEND_HOOK} {DAO_BULLA} > dao_mldy_transfer_tx
$ ./drk broadcast < dao_mldy_transfer_tx $ ./drk broadcast < dao_mldy_transfer_tx
``` ```
Wait for it to confirm, and if subscribed, you should see the DAO Wait for it to confirm, and if subscribed, you should see the DAO
receive the funds: receive the funds, if you hold the DAO notes key:
``` ```
$ ./drk dao balance MiladyMakerDAO $ ./drk dao balance MiladyMakerDAO
@@ -77,23 +83,24 @@ $ ./drk dao balance MiladyMakerDAO
Now that the DAO has something in its treasury, we can generate a Now that the DAO has something in its treasury, we can generate a
transfer proposal to send it somewhere, that will be up to vote transfer proposal to send it somewhere, that will be up to vote
for 1 block period. Let's propose to send 5 of the 10 tokens to for 1 block period, if we hold the DAO proposer key. Let's propose
our address (we can find that with `drk wallet --address`): to send 5 of the 10 tokens to our address (we can find that with
`drk wallet --address`):
``` ```
$ ./drk dao propose-transfer MiladyMakerDAO 1 5 WCKD {YOUR_ADDRESS} $ ./drk dao propose-transfer MiladyMakerDAO 1 5 WCKD {YOUR_ADDRESS}
``` ```
After command was executed, it will output the generated proposal After command was executed, it will output the generated proposal
bulla, which we will use to full the proposal information: bulla, which we will use to view the proposal full information:
``` ```
$ ./drk dao proposal {PROPOSAL_BULLA} $ ./drk dao proposal {PROPOSAL_BULLA}
``` ```
We can export this proposal, to share with rest DAO members. We can export this proposal, to share with rest DAO members.
The exported file will be encrypted using the DAO keys, so only The exported file will be encrypted using the DAO proposals view key,
its members can decrypt and import it. so only its members can decrypt and import it.
``` ```
$ ./drk dao proposal {PROPOSAL_BULLA} --export > dao_mldy_transfer_proposal.dat $ ./drk dao proposal {PROPOSAL_BULLA} --export > dao_mldy_transfer_proposal.dat
@@ -142,32 +149,74 @@ $ ./drk broadcast < dao_mldy_transfer_proposal_vote_tx
``` ```
Once confirmed and scanned, you should see votes information and Once confirmed and scanned, you should see votes information and
current status when running `dao proposal {PROPOSAL_BULLA}`. current status when running `dao proposal {PROPOSAL_BULLA}`,
assuming you hold the votes view key.
## Executing the proposal ## Executing the proposal
Once the block period has passed and enough votes have been cast that Once the block period has passed(~4h) and enough votes have been cast that
meet the required minimum (quorum), and assuming the yes:no votes ratio meet the required minimum (quorum), and assuming the yes:no votes ratio
ratio is bigger than the approval ratio, then we are ready to confirm ratio is bigger than the approval ratio, then we are ready to confirm
the vote. Any DAO member can perform this action. the vote. Only DAO members with the executor key can perform this action.
Since in our tutorial the `MLDY` governance tokens we used surpass the
quorum, we can execute the proposal right away:
``` ```
$ ./drk dao exec {PROPOSAL_BULLA} > dao_mldy_transfer_proposal_exec_tx $ ./drk dao exec {PROPOSAL_BULLA} > dao_mldy_transfer_proposal_exec_tx
$ ./drk broadcast < dao_mldy_transfer_proposal_exec_tx $ ./drk broadcast < dao_mldy_transfer_proposal_exec_tx
``` ```
Since in our tutorial the `MLDY` governance tokens we used surpass the
early execution quorum, we can execute the proposal right away, if we hold
both the DAO executor and early executor keys:
```
$ ./drk dao exec --early {PROPOSAL_BULLA} > dao_mldy_transfer_proposal_exec_tx
$ ./drk broadcast < dao_mldy_transfer_proposal_exec_tx
```
After the proposal has been executed on chain, we will see that After the proposal has been executed on chain, we will see that
the DAO balance has been reduced by 5 `WCKD`, while our own balance the DAO balance has been reduced by 5 `WCKD`, if we hold the DAO notes key,
has been increased by the same amount: while our own balance has been increased by the same amount:
``` ```
$ ./drk dao balance MiladyMakerDAO $ ./drk dao balance MiladyMakerDAO
$ ./drk wallet --balance $ ./drk wallet --balance
``` ```
## Generic proposal
DAOs can vote on off-chain operations by creating what is known as generic
proposals, meaning that no on-chain action is tied to it:
```
$ ./drk dao propose-generic MiladyMakerDAO 1
$ ./drk dao proposal {PROPOSAL_BULLA} --mint-proposal > dao_mldy_generic_proposal_mint_tx
$ ./drk broadcast < dao_mldy_generic_proposal_mint_tx
```
Vote on the proposal:
```
$ ./drk dao vote {PROPOSAL_BULLA} 1 > dao_mldy_generic_proposal_vote_tx
$ ./drk broadcast < dao_mldy_generic_proposal_vote_tx
```
And execute it, after the vote period(1 block period) has passed:
```
$ ./drk dao exec {PROPOSAL_BULLA} > dao_mldy_generic_proposal_exec_tx
$ ./drk broadcast < dao_mldy_generic_proposal_exec_tx
```
Or right away, since the early execution quorum has been reached:
```
$ ./drk dao exec --early {PROPOSAL_BULLA} > dao_mldy_generic_proposal_exec_tx
$ ./drk broadcast < dao_mldy_generic_proposal_exec_tx
```
Executing the proposal will just confirm it on-chain, without any
other actions taken.
## DAO->DAO ## DAO->DAO
Let's now try some more exotic operations! Let's now try some more exotic operations!
@@ -192,8 +241,8 @@ $ ./drk dao balance MiladyMakerDAO
Now we will create a second dao: Now we will create a second dao:
``` ```
$ ./drk dao create 20 10 0.67 WCKD > dao_wckd.dat $ ./drk dao create 20 10 10 0.67 WCKD > dao_wckd.toml
$ ./drk dao import WickedDAO < dao_wckd.dat $ ./drk dao import WickedDAO < dao_wckd.toml
$ ./drk dao mint WickedDAO > dao_wckd_mint_tx $ ./drk dao mint WickedDAO > dao_wckd_mint_tx
$ ./drk broadcast < dao_wckd_mint_tx $ ./drk broadcast < dao_wckd_mint_tx
``` ```
@@ -223,6 +272,13 @@ $ ./drk dao exec {PROPOSAL_BULLA} > dao_mldy_transfer_proposal_wckd_exec_tx
$ ./drk broadcast < dao_mldy_transfer_proposal_wckd_exec_tx $ ./drk broadcast < dao_mldy_transfer_proposal_wckd_exec_tx
``` ```
Or right away, since the early execution quorum has been reached:
```
$ ./drk dao exec --early {PROPOSAL_BULLA} > dao_mldy_transfer_proposal_wckd_exec_tx
$ ./drk broadcast < dao_mldy_transfer_proposal_wckd_exec_tx
```
After the proposal has been executed on chain, we will see that After the proposal has been executed on chain, we will see that
the DAO governance token balance has been reduced by 6.9 `MLDY`, the DAO governance token balance has been reduced by 6.9 `MLDY`,
while the new DAO balance has been increased by the same amount: while the new DAO balance has been increased by the same amount: