Skip to content

Commit

Permalink
Improving on proposal system, execution
Browse files Browse the repository at this point in the history
  • Loading branch information
nalnir committed Sep 26, 2023
1 parent 8599b31 commit da3c3f6
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 83 deletions.
57 changes: 53 additions & 4 deletions dao/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,6 1,8 @@
use crate::proposal::{
add_abstain_votes, add_against_votes, add_for_votes, add_proposal, check_min_duration,
check_min_vote_power, check_voted, get_proposal, set_min_vote_power, Proposal,
check_min_vote_power, check_voted, executed, for_votes_win, get_proposal, get_voted,
min_quorum_met, set_executed, set_min_vote_power, set_voted, votes_counts, Proposal,
VotesCount,
};
use crate::storage::core::CoreState;

Expand All @@ -11,6 13,7 @@ use soroban_sdk::{
IntoVal, Map, String, Symbol, Val, Vec,
};

use crate::errors::ExecutionError;
use crate::errors::VoteError;

pub trait DaoContractTrait {
Expand All @@ -26,6 29,9 @@ pub trait DaoContractTrait {
) -> Address;
fn create_proposal(env: Env, from: Address, proposal: Proposal) -> u32;
fn vote(env: Env, from: Address, prop_id: u32, power: u32, vote: u32);
fn get_votes(env: Env, prop_id: u32) -> VotesCount;
fn have_voted(env: Env, prop_id: u32, vote: Address) -> bool;
fn execute(env: Env, prop_id: u32) -> Vec<Val>;
}

#[contract]
Expand Down Expand Up @@ -107,22 113,65 @@ impl DaoContractTrait for DaoContract {
if !core_state.shareholders.contains(from.clone()) {
panic_with_error!(env, VoteError::NotAMember)
}

// 2. Check if already voted
check_voted(&env, prop_id, from.clone());

// 3. Check if has enough voting power to vote
check_min_vote_power(&env, power);

// 4. Check deadline
let proposal = get_proposal(&env, prop_id);
check_min_duration(&env, &proposal);

// 5. Vote
if vote == 0 {
add_against_votes(&env, prop_id, 1)
add_against_votes(&env, prop_id, 1);
set_voted(&env, prop_id, from);
} else if vote == 1 {
add_for_votes(&env, prop_id, 1)
add_for_votes(&env, prop_id, 1);
set_voted(&env, prop_id, from);
} else if vote == 2 {
add_abstain_votes(&env, prop_id, 1)
add_abstain_votes(&env, prop_id, 1);
set_voted(&env, prop_id, from);
} else {
panic_with_error!(env, VoteError::WrongVoteParam)
}
}

fn execute(env: Env, prop_id: u32) -> Vec<Val> {
let proposal = get_proposal(&env, prop_id);
// 1. Check deadline
check_min_duration(&env, &proposal);

// 2. Check if min quorum is met
min_quorum_met(&env, prop_id);

// 3. Check if "for" votes beat "against" votes
for_votes_win(&env, prop_id);

// 4. Check if executed
executed(&env, prop_id);

// 5. Execute
let mut exec_results: Vec<Val> = Vec::new(&env);
for instruct in proposal.instr {
let res: Val = env.invoke_contract(&instruct.c_id, &instruct.fun_name, instruct.args);
exec_results.push_front(res);
}

// 6. Set executed to true
set_executed(&env, prop_id);

// 7. Return results
exec_results
}

fn get_votes(env: Env, prop_id: u32) -> VotesCount {
votes_counts(&env, prop_id)
}

fn have_voted(env: Env, prop_id: u32, voter: Address) -> bool {
get_voted(&env, prop_id, voter)
}
}
7 changes: 7 additions & 0 deletions dao/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 32,10 @@ pub enum VoteError {
ProposalExpired = 1,
WrongVoteParam = 2,
}

#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum ExecutionError {
MinParticipNotMet = 0,
ForProposalFail = 1,
}
23 changes: 22 additions & 1 deletion dao/src/proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,8 @@ use crate::{
storage::proposal_storage::ProposalStorageKey,
};

use crate::errors::ExecutionError;

#[contracttype]
#[derive(Clone, Debug)]
pub struct ProposalVoted {
Expand All @@ -16,7 18,7 @@ pub struct ProposalVoted {
#[derive(Clone, Debug)]
pub struct ProposalInstr {
//contract id
pub c_id: BytesN<32>,
pub c_id: Address,
pub fun_name: Symbol,
pub args: Vec<Val>,
}
Expand All @@ -27,6 29,8 @@ pub struct Proposal {
pub end_time: u64,
// instrunctions will be executed in sequence
pub url: String, // pub instr: Vec<ProposalInstr>,
pub min_quorum: i128,
pub instr: Vec<ProposalInstr>,
}

#[contracttype]
Expand Down Expand Up @@ -235,3 239,20 @@ pub fn executed(env: &Env, prop_id: u32) -> bool {
.get(&ProposalStorageKey::Executed(prop_id))
.unwrap_or(false)
}

pub fn min_quorum_met(env: &Env, prop_id: u32) {
let proposal = get_proposal(&env, prop_id);
let votes = votes_counts(&env, prop_id);
let t_votes = votes.v_abstain votes.v_against votes.v_for;
if t_votes >= proposal.min_quorum {
panic_with_error!(env, ExecutionError::MinParticipNotMet)
}
}

pub fn for_votes_win(env: &Env, prop_id: u32) {
let for_votes = get_for_votes(&env, prop_id);
let agains_votes = get_against_votes(&env, prop_id);
if for_votes >= agains_votes {
panic_with_error!(env, ExecutionError::ForProposalFail)
}
}
17 changes: 7 additions & 10 deletions deployer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
#![no_std]

use soroban_sdk::{contractimpl, contract, Address, BytesN, Env, Symbol, Vec, Val};
use soroban_sdk::{contract, contractimpl, Address, BytesN, Env, Symbol, Val, Vec};

#[contract]
pub struct Deployer;
Expand All @@ -18,10 18,7 @@ impl Deployer {
init_args: Vec<Val>,
) -> (Address, Val) {
// Deploy the contract using the installed WASM code with given hash.
let id = env
.deployer()
.with_current_contract(salt)
.deploy(wasm_hash);
let id = env.deployer().with_current_contract(salt).deploy(wasm_hash);
// Invoke the init function with the given arguments.
let res: Val = env.invoke_contract(&id, &init_fn, init_args);
// Return the contract ID of the deployed contract and the result of
Expand All @@ -33,25 30,25 @@ impl Deployer {
mod test;

// soroban contract install --wasm ../dao/target/wasm32-unknown-unknown/release/governance.wasm
// dao-wasm-hash -> 13e859532d9db5892e9743f57be8c054e43d101050598663ad5d51a17f8423b0
// dao-wasm-hash -> 5c286c5f20ad37ee8992ddaa99973dfe52063074facb4ae109bc7810ffe3a95c

// soroban contract install --wasm ../token/target/wasm32-unknown-unknown/release/soroban_token_contract.wasm
// token-wasm-hash -> da729cbad2913399edabfc09a8dba948df7b830a5b855fdb196c7a48c3c9fbc1
// token-wasm-hash -> d97bdb32454f36648f8e291d9995c0985879a8fb78519c8a8cb4143c7c51f3ff

// soroban contract deploy \
// --wasm target/wasm32-unknown-unknown/release/soroban_deployer_contract.wasm \
// --source juico \
// --network futurenet
// deployer_contract_id -> CB5WUJCGKOURLISFS2QW5OCDJGCNXXEWYVGZSFPHKCS6LQIPBHT5JB2M
// deployer_contract_id -> CBMFJGHFAGPVH2FXQQK7QDBLVFF3AQNZ5XRYSMOJKPHITV3GH4CPT6BX

// soroban contract deploy \
// --wasm target/wasm32-unknown-unknown/release/governance.wasm \
// --source juico \
// --network futurenet
// dao_contract_id -> CAH3OL4WGP25M75SI5DXSNRLNSDWFF5MHQ5CUEHLVFOERZ47ZDUYOMDI
// dao_contract_id -> CDJW6WIVGMEFASX3REG5PEIHLDHMAMDDYU72537LJJ57QZZ5WQKQS5GL

// soroban contract deploy \
// --wasm target/wasm32-unknown-unknown/release/soroban_token_contract.wasm \
// --source juico \
// --network futurenet
// token_contract_id -> CCFQHSCOX7XW3ANGET2M6VDIHQCBPF4MJFHOKEBKX2CEOCNVW24P6YPQ
// token_contract_id -> CB4NVEPGSB4XFDOJ2ONCIZVITWTGA4CBDBW6YA6QAG7JFH3QU5DRQPMJ
3 changes: 3 additions & 0 deletions token/src/allowance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 32,8 @@ pub fn write_allowance(
expiration_ledger,
};

let low_watermarks = expiration_ledger / 2;

if amount > 0 && expiration_ledger < e.ledger().sequence() {
panic!("expiration_ledger is less than ledger seq when amount > 0")
}
Expand All @@ -42,6 44,7 @@ pub fn write_allowance(
if amount > 0 {
e.storage().temporary().bump(
&key,
low_watermarks,
expiration_ledger
.checked_sub(e.ledger().sequence())
.unwrap(),
Expand Down
16 changes: 13 additions & 3 deletions token/src/balance.rs
Original file line number Diff line number Diff line change
@@ -1,10 1,16 @@
use crate::storage_types::{DataKey, BALANCE_BUMP_AMOUNT};
use crate::storage_types::{
DataKey, BALANCE_BUMP_AMOUNT_HIGH_WATERMARK, BALANCE_BUMP_AMOUNT_LOW_WATERMARK,
};
use soroban_sdk::{Address, Env};

pub fn read_balance(e: &Env, addr: Address) -> i128 {
let key = DataKey::Balance(addr);
if let Some(balance) = e.storage().persistent().get::<DataKey, i128>(&key) {
e.storage().persistent().bump(&key, BALANCE_BUMP_AMOUNT);
e.storage().persistent().bump(
&key,
BALANCE_BUMP_AMOUNT_LOW_WATERMARK,
BALANCE_BUMP_AMOUNT_HIGH_WATERMARK,
);
balance
} else {
0
Expand All @@ -14,7 20,11 @@ pub fn read_balance(e: &Env, addr: Address) -> i128 {
fn write_balance(e: &Env, addr: Address, amount: i128) {
let key = DataKey::Balance(addr);
e.storage().persistent().set(&key, &amount);
e.storage().persistent().bump(&key, BALANCE_BUMP_AMOUNT);
e.storage().persistent().bump(
&key,
BALANCE_BUMP_AMOUNT_LOW_WATERMARK,
BALANCE_BUMP_AMOUNT_HIGH_WATERMARK,
);
}

pub fn receive_balance(e: &Env, addr: Address, amount: i128) {
Expand Down
Loading

0 comments on commit da3c3f6

Please sign in to comment.