Let $\t{Bulla}$ be defined as in the section Bulla Commitments.
Let $ℙₚ, 𝔽ₚ, \mathcal{X}, \mathcal{Y}, \t{𝔹⁶⁴2𝔽ₚ}$ be defined as in the section Pallas and Vesta.
The DAO contains the main parameters that define DAO operation:
Define the DAO params $$ \begin{aligned} \t{Params}\t{DAO}.L &∈ ℕ₆₄ \ \t{Params}\t{DAO}.Q &∈ ℕ₆₄ \ \t{Params}\t{DAO}.EEQ &∈ ℕ₆₄ \ \t{Params}\t{DAO}.Aq &∈ ℕ₆₄ \ \t{Params}\t{DAO}.Ab &∈ ℕ₆₄ \ \t{Params}\t{DAO}.τ &∈ 𝔽ₚ \ \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} $$ 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₂}]$.
{{#include ../../../../../src/contract/dao/src/model.rs:dao}}
$$ \t{Bulla}\t{DAO} : \t{Params}\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_q), \ ℕ₆₄2𝔽ₚ(p.Ab), \ 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} $$
Let $\t{FuncId}$ be defined as in Function IDs.
Let $\t{BLAKE2b}$ be defined as in BLAKE2b Hash Function.
Define $\t{AuthCall} = (\t{ContractId}, \t{FuncCode}, 𝔹^*)$. Each authorization call represents a child call made by the DAO. The auth data field is used by the child invoked contract to enforce additional invariants.
{{#include ../../../../../src/contract/dao/src/model.rs:dao-auth-call}}
Define $\t{Commit}\t{Auth} : \t{AuthCall}^* → 𝔽ₚ$ by
$$ \t{Commit}{\t{Auth}^*}(c) = \t{𝔹⁶⁴2𝔽ₚ}(\t{BLAKE2b}_{64}(\t{Encode}(c))) $$
which commits to a Vec<DaoAuthCall>. The BLAKE2b hash is personalized
(justDAOthings) and the reduction to $𝔽ₚ$ is the uniform-bytes
conversion described in Pallas and Vesta.
Define the proposal params $$ \begin{aligned} \t{Params}\t{Proposal}.C &∈ \t{AuthCall}^* \ \t{Params}\t{Proposal}.t₀ &∈ ℕ₆₄ \ \t{Params}\t{Proposal}.D &∈ ℕ₆₄ \ \t{Params}\t{Proposal}.φ &∈ 𝔽ₚ \ \t{Params}\t{Proposal}.\t{DAO} &∈ 𝔽ₚ \ \end{aligned} $$ where $\t{Params}\t{Proposal}.\t{DAO}$ is a DAO bulla, $t₀$ is the creation blockwindow, $D$ is the duration in blockwindows, and $φ$ is arbitrary user data.
{{#include ../../../../../src/contract/dao/src/model.rs:dao-proposal}}
$$ \t{Bulla}\t{Proposal} : \t{Params}\t{Proposal} × 𝔽ₚ → 𝔽ₚ $$ $$ \t{Bulla}_\t{Proposal}(p, bp) = \t{Bulla}(\t{Commit}{\t{Auth}^*}(p.C), ℕ₆₄2𝔽ₚ(p.t₀), ℕ₆₄2𝔽ₚ(p.D), p.φ, p.\t{DAO}, b_p) $$
For proposals, we keep track of nullifiers for each token weighted vote cast on a proposal.
Let $\t{PoseidonHash}$ be defined as in the section PoseidonHash Function.
Let $\mathcal{C}$ be the coin params, and $C$ be the coin commitment as defined in Money Contract, with $x$ the secret key corresponding to $\mathcal{C}.\t{PK}$.
Let $P$ be a proposal bulla as in the section Proposal.
First the money nullifier is derived as in the Money contract: $$ N = \t{PoseidonHash}(x, C) $$
For proposing, the nullifier additionally binds the proposal bulla, defeating input reuse attacks between calls: $$ \t{Nullifier}_\t{Propose}(N, P) = \t{PoseidonHash}(N, P) $$
For voting, the nullifier additionally binds the proposal bulla and the coin secret key, defeating correlation attacks between calls: $$ \t{Nullifier}_\t{Vote}(N, x, P) = \t{PoseidonHash}(N, x, P) $$
Time limits on proposals are expressed in 4 hour windows. Since proofs cannot guarantee which block they get into, we therefore must modulo the block height a certain number which we use in the proofs.
{{#include ../../../../../src/contract/dao/src/lib.rs:dao-blockwindow}}
which can be used like this
{{#include ../../../../../src/contract/dao/src/entrypoint/propose.rs:dao-blockwindow-example-usage}}