-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
314 additions
and
4 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
# DAO Contracts | ||
|
||
- `dao-dao-core` - the core module for DAOs. | ||
- `external` - contracts used by DAOs that are not part of a DAO | ||
module. | ||
- `delegation` - delegation modules. | ||
- `distribution` - token distribution modules. | ||
- `external` - contracts used by DAOs that are not part of a DAO module. | ||
- `pre-propose` - pre-propose modules. | ||
- `proposal` - proposal modules. | ||
- `staking` - cw20 staking functionality and a staking rewards system. | ||
- `voting` - voting modules. | ||
- `staking` - cw20 staking functionality and a staking rewards | ||
system. These contracts are used by [Wasmswap](https://github.com/Wasmswap) as well as DAO DAO. | ||
|
||
For a description of each module type, see [our wiki](https://github.com/DA0-DA0/dao-contracts/wiki/DAO-DAO-Contracts-Design). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
[package] | ||
name = "dao-vote-delegation" | ||
authors = ["Noah <[email protected]>"] | ||
description = "Manages delegation of voting power for DAOs." | ||
edition = { workspace = true } | ||
license = { workspace = true } | ||
repository = { workspace = true } | ||
version = { workspace = true } | ||
|
||
[lib] | ||
crate-type = ["cdylib", "rlib"] | ||
|
||
[features] | ||
backtraces = ["cosmwasm-std/backtraces"] | ||
# use library feature to disable all instantiate/execute/query exports | ||
library = [] | ||
|
||
[dependencies] | ||
cosmwasm-std = { workspace = true } | ||
cosmwasm-schema = { workspace = true } | ||
cw2 = { workspace = true } | ||
cw4 = { workspace = true } | ||
cw20 = { workspace = true } | ||
cw20-base = { workspace = true, features = ["library"] } | ||
cw-controllers = { workspace = true } | ||
cw-ownable = { workspace = true } | ||
cw-storage-plus = { workspace = true } | ||
cw-utils = { workspace = true } | ||
dao-hooks = { workspace = true } | ||
dao-interface = { workspace = true } | ||
dao-voting = { workspace = true } | ||
semver = { workspace = true } | ||
thiserror = { workspace = true } | ||
|
||
[dev-dependencies] | ||
cw-multi-test = { workspace = true } | ||
anyhow = { workspace = true } | ||
cw20-stake = { workspace = true, features = ["library"] } | ||
cw4-group = { workspace = true, features = ["library"] } | ||
cw721-base = { workspace = true, features = ["library"] } | ||
dao-voting-cw20-staked = { workspace = true, features = ["library"] } | ||
dao-voting-cw4 = { workspace = true, features = ["library"] } | ||
dao-voting-token-staked = { workspace = true, features = ["library"] } | ||
dao-voting-cw721-staked = { workspace = true, features = ["library"] } | ||
dao-testing = { workspace = true } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# DAO Vote Delegation | ||
|
||
[![dao-vote-delegation on | ||
crates.io](https://img.shields.io/crates/v/dao-vote-delegation.svg?logo=rust)](https://crates.io/crates/dao-vote-delegation) | ||
[![docs.rs](https://img.shields.io/docsrs/dao-vote-delegation?logo=docsdotrs)](https://docs.rs/dao-vote-delegation/latest/dao_vote_delegation/) | ||
|
||
The `dao-vote-delegation` contract allows members of a DAO to delegate their | ||
voting power to other members of the DAO who have registered as delegates. It | ||
works in conjunction with voting and proposal modules, as well as the rewards | ||
distributor, to offer a comprehensive delegation system for DAOs that supports | ||
the following features: | ||
|
||
- Fractional delegation of voting power on a per-proposal-module basis. | ||
- Overridable delegate votes that can be overridden on a per-proposal basis by | ||
the delegator | ||
- Delegate reward commission. | ||
|
||
## Instantiation and Setup | ||
|
||
This contract must be instantiated by the DAO. | ||
|
||
### Hooks | ||
|
||
After instantiating the contract, it is VITAL to set up the required hooks for | ||
it to work. To compute delegate voting power correctly, this contract needs to | ||
know about both voting power changes and votes cast on proposals as soon as they | ||
happen. | ||
|
||
This can be achieved using the `add_hook` method on voting/staking contracts | ||
that support voting power changes, such as: | ||
|
||
- `cw4-group` | ||
- `dao-voting-cw721-staked` | ||
- `dao-voting-token-staked` | ||
- `cw20-stake` | ||
|
||
For proposal modules, the corresponding hook is `add_vote_hook`: | ||
|
||
- `dao-proposal-single` | ||
- `dao-proposal-multiple` | ||
- `dao-proposal-condorcet` | ||
|
||
## Design Decisions | ||
|
||
### Fractional Delegation via Percentages | ||
|
||
In order to support fractional delegation, users assign a percentage of voting | ||
power to each delegate. Percentages are used instead of choosing an absolute | ||
amount of voting power (e.g. staked tokens) since voting power can change | ||
independently of delegation. If an absolute amount were used, and a user who had | ||
delegated all of their voting power to a few different delegates then unstaked | ||
half of their tokens, there is no clear way to resolve what their new | ||
delegations are. Using percentages instead allows voting power and delegation to | ||
be decided independently. |
11 changes: 11 additions & 0 deletions
11
contracts/delegation/dao-vote-delegation/examples/schema.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use cosmwasm_schema::write_api; | ||
use dao_vote_delegation::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; | ||
|
||
fn main() { | ||
write_api! { | ||
instantiate: InstantiateMsg, | ||
query: QueryMsg, | ||
execute: ExecuteMsg, | ||
migrate: MigrateMsg, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
use cosmwasm_std::{DivideByZeroError, OverflowError, StdError}; | ||
use cw_utils::PaymentError; | ||
use thiserror::Error; | ||
|
||
#[derive(Error, Debug, PartialEq)] | ||
pub enum ContractError { | ||
#[error(transparent)] | ||
Std(#[from] StdError), | ||
|
||
#[error(transparent)] | ||
Ownable(#[from] cw_ownable::OwnershipError), | ||
|
||
#[error(transparent)] | ||
Overflow(#[from] OverflowError), | ||
|
||
#[error(transparent)] | ||
DivideByZero(#[from] DivideByZeroError), | ||
|
||
#[error(transparent)] | ||
Payment(#[from] PaymentError), | ||
|
||
#[error("semver parsing error: {0}")] | ||
SemVer(String), | ||
} | ||
|
||
impl From<semver::Error> for ContractError { | ||
fn from(err: semver::Error) -> Self { | ||
Self::SemVer(err.to_string()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))] | ||
|
||
pub mod contract; | ||
mod error; | ||
pub mod msg; | ||
pub mod state; | ||
|
||
#[cfg(test)] | ||
mod testing; | ||
|
||
pub use crate::error::ContractError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
use cosmwasm_schema::{cw_serde, QueryResponses}; | ||
use cosmwasm_std::{Addr, Decimal}; | ||
use cw4::MemberChangedHookMsg; | ||
use cw_ownable::cw_ownable_execute; | ||
use cw_utils::Duration; | ||
use dao_hooks::{nft_stake::NftStakeChangedHookMsg, stake::StakeChangedHookMsg}; | ||
use dao_interface::voting::InfoResponse; | ||
|
||
pub use cw_ownable::Ownership; | ||
|
||
use crate::state::Delegation; | ||
|
||
#[cw_serde] | ||
pub struct InstantiateMsg { | ||
/// The DAO. If not provided, the instantiator is used. | ||
pub dao: Option<String>, | ||
/// the maximum percent of voting power that a single delegate can wield. | ||
/// they can be delegated any amount of voting power—this cap is only | ||
/// applied when casting votes. | ||
pub vp_cap_percent: Option<Decimal>, | ||
/// the duration a delegation is valid for, after which it must be renewed | ||
/// by the delegator. | ||
pub delegation_validity: Option<Duration>, | ||
} | ||
|
||
#[cw_ownable_execute] | ||
#[cw_serde] | ||
pub enum ExecuteMsg { | ||
/// Called when a member is added or removed | ||
/// to a cw4-groups or cw721-roles contract. | ||
MemberChangedHook(MemberChangedHookMsg), | ||
/// Called when NFTs are staked or unstaked. | ||
NftStakeChangeHook(NftStakeChangedHookMsg), | ||
/// Called when tokens are staked or unstaked. | ||
StakeChangeHook(StakeChangedHookMsg), | ||
/// updates the configuration of the delegation system | ||
UpdateConfig { | ||
/// the maximum percent of voting power that a single delegate can | ||
/// wield. they can be delegated any amount of voting power—this cap is | ||
/// only applied when casting votes. | ||
vp_cap_percent: Option<Decimal>, | ||
/// the duration a delegation is valid for, after which it must be | ||
/// renewed by the delegator. | ||
delegation_validity: Option<Duration>, | ||
}, | ||
} | ||
|
||
#[cw_serde] | ||
#[derive(QueryResponses)] | ||
pub enum QueryMsg { | ||
/// Returns contract version info | ||
#[returns(InfoResponse)] | ||
Info {}, | ||
/// Returns information about the ownership of this contract. | ||
#[returns(Ownership<Addr>)] | ||
Ownership {}, | ||
/// Returns the delegations by a delegator. | ||
#[returns(DelegationsResponse)] | ||
DelegatorDelegations { | ||
delegator: String, | ||
start_after: Option<u64>, | ||
limit: Option<u32>, | ||
}, | ||
/// Returns the delegations to a delegate. | ||
#[returns(DelegationsResponse)] | ||
DelegateDelegations { | ||
delegate: String, | ||
start_after: Option<u64>, | ||
limit: Option<u32>, | ||
}, | ||
} | ||
|
||
#[cw_serde] | ||
pub struct DelegationsResponse { | ||
pub delegations: Vec<Delegation>, | ||
} | ||
|
||
#[cw_serde] | ||
pub struct MigrateMsg {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use cosmwasm_schema::cw_serde; | ||
use cosmwasm_std::{Addr, Decimal, Uint128}; | ||
use cw20::Expiration; | ||
use cw_storage_plus::{Item, Map, SnapshotMap, Strategy}; | ||
use cw_utils::Duration; | ||
|
||
/// the configuration of the delegation system. | ||
pub const CONFIG: Item<Config> = Item::new("config"); | ||
|
||
/// the DAO this delegation system is connected to. | ||
pub const DAO: Item<Addr> = Item::new("dao"); | ||
|
||
/// the VP delegated to a delegate that has not yet been used in votes cast by | ||
/// delegators in a specific proposal. | ||
pub const UNVOTED_DELEGATED_VP: Map<(&Addr, u64), Uint128> = Map::new("udvp"); | ||
|
||
/// the VP delegated to a delegate by height. | ||
pub const DELEGATED_VP: SnapshotMap<&Addr, Uint128> = SnapshotMap::new( | ||
"dvp", | ||
"dvp__checkpoints", | ||
"dvp__changelog", | ||
Strategy::EveryBlock, | ||
); | ||
|
||
#[cw_serde] | ||
pub struct Config { | ||
/// the maximum percent of voting power that a single delegate can wield. | ||
/// they can be delegated any amount of voting power—this cap is only | ||
/// applied when casting votes. | ||
pub vp_cap_percent: Option<Decimal>, | ||
/// the duration a delegation is valid for, after which it must be renewed | ||
/// by the delegator. | ||
pub delegation_validity: Option<Duration>, | ||
} | ||
|
||
#[cw_serde] | ||
pub struct Delegation { | ||
/// the delegator. | ||
pub delegator: Addr, | ||
/// the delegate that can vote on behalf of the delegator. | ||
pub delegate: Addr, | ||
/// the percent of the delegator's voting power that is delegated to the | ||
/// delegate. | ||
pub percent: Decimal, | ||
/// when the delegation expires. | ||
pub expiration: Expiration, | ||
} |