Uruk Docs

DAO governance

Propose, vote, and execute protocol changes through the Uruk DAO and its multi-sig.

DAO governance

The Uruk DAO (dao-governance contract) controls every protocol parameter: market deployment, pool creation, collateral whitelists, partner registration, oracle and KYC providers, and contract upgrades.

Who can govern

  • Governance runs through a multi-sig wallet (wallet id 0, created at deploy).
  • Only signers of that wallet may propose and vote. Governance is deliberately KYC-free. Membership is the access control.
  • One signer = one vote. Passing threshold = the wallet's multi-sig threshold.
  • Voting period is 48h; execution has an additional 24h timelock (execute_after = end_time + 24h).

Check membership with is_governance_signer(addr). The webapp uses it to gate the Vote / Propose UI.

Lifecycle

propose(proposer, title, description, call_data)   → proposal id
vote(voter, proposal_id, support)                  → one vote per signer
finalise(proposal_id)                              → status Passed once yes ≥ threshold
execute(executor, proposal_id)                     → runs call_data after timelock
cancel(proposer, proposal_id)                      → proposer only, while Active
  • get_proposal_count() returns the next proposal id. Call it before propose().
  • execute() routes call_data to cross-contract calls (see actions below).
  • has_voted(id, voter) and get_proposal(id) back the dashboard.

Privileged actions need multi-sig

A bitmask decides which action types also require on-chain multi-sig approval even after the vote passes: signer management, oracle providers, KYC verifiers, deploy/activate assets, and contract upgrades.

propose_and_queue_multisig(...) → (proposal_id, multisig_tx_id)
approve_multisig_tx(signer, tx_id, approve)
execute_multisig_tx(executor, tx_id)   → runs the queued call_data

Useful views: get_pending_multisig_txs(wallet_id), get_multisig_tx_approvals(tx_id), get_multisig_tx_summary(tx_id), get_signers(wallet_id).

Proposal actions

call_data is packed as [action_type: u32 LE][payload…]. Action types:

ActionWhat it does
deploy_asset (0)Register a synthetic market + whitelist its collateral in one execution
deactivate (1)Deactivate a partner on PartnerRegistry
adjust_earnings (3)Change a partner's revenue share
adjust_ratio (4)Update global min collateral ratio / liquidation penalty
create_pool (5)Create a liquidity pool (pool_id, token_a, token_b, fee_tier)
add_signer (6) / remove_signer (7)Multi-sig signer management
oracle_add_provider (8) / oracle_remove_provider (9) / oracle_set_min_providers (10)Oracle-twap provider + quorum management
kyc_add_verifier (11) / kyc_remove_verifier (12)Compliance-registry verifier management
set_collateral_allowed (13)Whitelist / de-whitelist a collateral token
register_partner (14)Approve a partner join application
activate_partner_asset (15)Make a partner-submitted synth live
upgrade_contract (16)Replace a protocol contract's Wasm (storage preserved)
generic (99)Legacy param update (ParamCR / ParamBorrowFee / ParamLiqPenalty)

REST API

Governance state is indexed and mirrored by the backend:

MethodPathDescription
GET/api/proposalsList proposals (?status=&type=)
GET/api/proposals/:idSingle proposal (db uuid or on-chain id)
POST/api/proposalsRecord a proposal created on-chain
PATCH/api/proposals/:idSync status/votes after vote() / execute()
GET/api/proposals/:id/votesPer-voter audit trail
POST/api/proposals/:id/votesRecord an on-chain vote
GET/api/multisig/configMulti-sig wallets config
GET/api/multisig/wallets / /wallets/:idWallet list + detail
POST/api/multisig/walletsCreate a wallet (DAO only)
GET/api/multisig/transactions/pendingTxs awaiting signer approval
GET/api/multisig/transactions/readyTxs that reached threshold
POST/api/multisig/transactionsQueue a tx for approval

Keep state alive

Soroban state expires unless bumped. Keepers (or anyone) may call the permissionless entrypoint to extend TTLs. No auth, no state change, only ledger lifetimes:

  • DAO: extend_ttl(proposal_id, threshold, extend_to) extends the instance plus one proposal's entries
  • Liquidity pool: extend_ttl(pool_id, provider?, threshold, extend_to)
  • Synthetic engine: extend_ttl(owner, synth, threshold, extend_to)

On this page