From a724685c3c48b5d8de87190567e476362d95c3ff Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 24 Dec 2021 08:54:07 +0800 Subject: [PATCH 1/7] init --- Cargo.toml | 1 + referendum/Cargo.toml | 17 +++ referendum/build.sh | 7 ++ referendum/src/account.rs | 216 ++++++++++++++++++++++++++++++++++++++ referendum/src/lib.rs | 94 +++++++++++++++++ referendum/src/owner.rs | 108 +++++++++++++++++++ referendum/src/session.rs | 45 ++++++++ referendum/src/utils.rs | 29 +++++ res/referendum.wasm | Bin 0 -> 168486 bytes 9 files changed, 517 insertions(+) create mode 100644 referendum/Cargo.toml create mode 100644 referendum/build.sh create mode 100644 referendum/src/account.rs create mode 100644 referendum/src/lib.rs create mode 100644 referendum/src/owner.rs create mode 100644 referendum/src/session.rs create mode 100644 referendum/src/utils.rs create mode 100755 res/referendum.wasm diff --git a/Cargo.toml b/Cargo.toml index bf10d78..b98794d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "./ref-token", "./xref-token", + "./referendum", "./test-token" ] diff --git a/referendum/Cargo.toml b/referendum/Cargo.toml new file mode 100644 index 0000000..904340c --- /dev/null +++ b/referendum/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "referendum" +version = "1.0.0" +authors = ["Marco "] +edition = "2018" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +uint = { version = "0.9.0", default-features = false } +near-sdk = "3.1.0" +near-contract-standards = "3.1.0" + +[dev-dependencies] +near-sdk-sim = "3.1.0" +test-token = { path = "../test-token" } \ No newline at end of file diff --git a/referendum/build.sh b/referendum/build.sh new file mode 100644 index 0000000..226b0a1 --- /dev/null +++ b/referendum/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e +rustup target add wasm32-unknown-unknown +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release +cd .. +cp target/wasm32-unknown-unknown/release/referendum.wasm ./res/referendum.wasm +cd - \ No newline at end of file diff --git a/referendum/src/account.rs b/referendum/src/account.rs new file mode 100644 index 0000000..f8f03f8 --- /dev/null +++ b/referendum/src/account.rs @@ -0,0 +1,216 @@ +//! Account is information per user about their locking balances and ballots. +//! + +use crate::*; +use crate::utils::{ext_self, GAS_FOR_FT_TRANSFER, GAS_FOR_RESOLVE_TRANSFER, NO_DEPOSIT}; +use near_contract_standards::fungible_token::receiver::FungibleTokenReceiver; +use near_contract_standards::fungible_token::core_impl::ext_fungible_token; +use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::{Balance, AccountId, assert_one_yocto, PromiseOrValue, log, PromiseResult}; +use near_sdk::json_types::U128; + +#[derive(BorshDeserialize, BorshSerialize)] +pub enum VAccount { + Current(Account), +} + +impl VAccount { + /// Upgrades from other versions to the currently used version. + pub fn into_current(self) -> Account { + match self { + VAccount::Current(account) => account, + } + } +} + +impl From for VAccount { + fn from(account: Account) -> Self { + VAccount::Current(account) + } +} + +/// Account information. +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Account { + /// The amount of base token locked + pub locking_amount: Balance, + /// The amount of ballots the account holds + pub ballot_amount: Balance, + /// unlocking session id + pub unlocking_session_id: u32, + // TODO: record proposal voting info, when ballot_amount changes, should update this one and global proposal vote info + // pub proposals: HashMap, +} + +impl Account { + pub(crate) fn add_locking(&mut self, locking_amount: Balance, ballot_amount: Balance, unlocking_session_id: u32) { + self.locking_amount += locking_amount; + self.ballot_amount += ballot_amount; + self.unlocking_session_id = unlocking_session_id; + } + + pub(crate) fn unlock(&mut self, cur_session_id: u32) -> Balance { + if cur_session_id >= self.unlocking_session_id { + let amount = self.locking_amount; + self.locking_amount = 0; + self.ballot_amount = 0; + self.unlocking_session_id = 0; + amount + } else { + 0 + } + + } +} + + +impl Contract { + /// lasts = 0 means append + fn internal_lock(&mut self, account_id: &AccountId, locking_amount: Balance, lasts: u32) { + // TODO: + // calculate ballots + // locate end_session (array index) and end_session_id + // verify append has valid running locking + // vierify new lock has no running locking + let ballot_amount: Balance = 0; + let end_session: usize = 0; + let end_session_id: u32 = 0; + + // update the account + let mut account = self.data().accounts.get(account_id).map(|va| va.into_current()).expect("ERR_USER_NOT_REGISTER"); + account.add_locking(locking_amount, ballot_amount, end_session_id); + self.data_mut().accounts.insert(account_id, &account.into()); + // update the session + self.data_mut().sessions[end_session].expire_amount += ballot_amount; + // update the ballot + self.data_mut().cur_total_ballot += ballot_amount; + // TODO: add log + } + + fn internal_unlock(&mut self, account_id: &AccountId) -> Balance { + // TODO: get cur session id + let cur_session_id = 0; + let mut account = self.data().accounts.get(account_id).map(|va| va.into_current()).expect("ERR_USER_NOT_REGISTER"); + let amount = account.unlock(cur_session_id); + self.data_mut().accounts.insert(account_id, &account.into()); + // TODO: call withdraw to send unlock token back to user + amount + } +} + +#[near_bindgen] +impl Contract { + + /// unslock token and send assets back to the predecessor account. + /// Requirements: + /// * The predecessor account should be registered. + /// * Requires attached deposit of exactly 1 yoctoNEAR. + #[payable] + pub fn unlock(&mut self) -> PromiseOrValue { + + assert_one_yocto(); + // sync point + self.fresh_sessions(); + + let account_id = env::predecessor_account_id(); + + let unlocked = self.internal_unlock(&account_id); + + if unlocked > 0 { + log!("Unlock {} token back to {}", unlocked, account_id); + ext_fungible_token::ft_transfer( + account_id.clone(), + U128(unlocked), + None, + &self.data().locked_token, + 1, + GAS_FOR_FT_TRANSFER, + ) + .then(ext_self::callback_post_unlock( + account_id.clone(), + U128(unlocked), + &env::current_account_id(), + NO_DEPOSIT, + GAS_FOR_RESOLVE_TRANSFER, + )).into() + } else { + PromiseOrValue::Value(0) + } + } + + #[private] + pub fn callback_post_unlock( + &mut self, + sender_id: AccountId, + amount: U128, + ) { + assert_eq!( + env::promise_results_count(), + 1, + "Err: expected 1 promise result from unstake" + ); + match env::promise_result(0) { + PromiseResult::NotReady => unreachable!(), + PromiseResult::Successful(_) => {} + PromiseResult::Failed => { + // This reverts the changes from unlock function. + // If account doesn't exit, the unlock token stay in contract. + if self.data().accounts.contains_key(&sender_id) { + let mut account = self.data().accounts.get(&sender_id).map(|va| va.into_current()).unwrap(); + account.locking_amount += amount.0; + self.data_mut().accounts.insert(&sender_id, &account.into()); + + env::log( + format!( + "Account {} unlock failed and reverted.", + sender_id + ) + .as_bytes(), + ); + } else { + env::log( + format!( + "Account {} has unregisterd. unlocking token goes to contract.", + sender_id + ) + .as_bytes(), + ); + } + } + }; + } +} + +#[near_bindgen] +impl FungibleTokenReceiver for Contract { + /// Callback on receiving tokens by this contract. + fn ft_on_transfer( + &mut self, + sender_id: ValidAccountId, + amount: U128, + msg: String, + ) -> PromiseOrValue { + // sync point + self.fresh_sessions(); + + let token_in = env::predecessor_account_id(); + let amount: Balance = amount.into(); + assert_eq!(token_in, self.data().locked_token, "ERR_ILLEGAL_TOKEN"); + + if msg.is_empty() { + // user append locking + log!("append lock {} token", amount); + self.internal_lock(sender_id.as_ref(), amount, 0); + } else { + // new locking + let locking_period = msg.parse::().expect("ERR_ILLEGAL_MSG"); + assert!(locking_period > 0, "ERR_ILLEGAL_MSG"); + assert!((locking_period as usize) <= MAX_SESSIONS, "ERR_ILLEGAL_MSG"); + + log!("New lock {} token with {} sessions", amount, msg); + self.internal_lock(sender_id.as_ref(), amount, locking_period); + + } + PromiseOrValue::Value(U128(0)) + } +} \ No newline at end of file diff --git a/referendum/src/lib.rs b/referendum/src/lib.rs new file mode 100644 index 0000000..cc85a15 --- /dev/null +++ b/referendum/src/lib.rs @@ -0,0 +1,94 @@ +/*! +* REF referendum contract +* +*/ +use near_sdk::collections::{LookupMap, UnorderedMap}; +use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::json_types::{ValidAccountId}; +use near_sdk::{env, near_bindgen, AccountId, Balance, PanicOnDefault, PromiseOrValue, Timestamp, BorshStorageKey}; + +use crate::session::SessionInfo; +use crate::account::VAccount; +use crate::utils::*; + +mod session; +mod account; +mod utils; +mod owner; + +near_sdk::setup_alloc!(); + +#[derive(BorshStorageKey, BorshSerialize)] +pub enum StorageKeys { + Account, +} + +#[derive(BorshDeserialize, BorshSerialize)] +pub struct ContractData { + + // owner of this contract + owner_id: AccountId, + + // which token used for locking + locked_token: AccountId, + + // the genesis timestamp + genesis_timestamp: Timestamp, + + // maintains a global session circle array + sessions: [SessionInfo; MAX_SESSIONS], + + // current session idx in sessions array + cur_session: usize, + + // total ballot amount in current session + cur_total_ballot: Balance, + + accounts: LookupMap, +} + +#[derive(BorshSerialize, BorshDeserialize)] +pub enum VContractData { + Current(ContractData), +} + +impl VContractData {} + +#[near_bindgen] +#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)] +pub struct Contract { + data: VContractData, +} + +#[near_bindgen] +impl Contract { + #[init] + pub fn new(owner_id: ValidAccountId, token_id: ValidAccountId) -> Self { + assert!(!env::state_exists(), "Already initialized"); + Self { + data: VContractData::Current(ContractData { + owner_id: owner_id.into(), + locked_token: token_id.into(), + genesis_timestamp: env::block_timestamp() + DEFAULT_GENESIS_OFFSET, + sessions: [SessionInfo::default(); MAX_SESSIONS], + cur_session: 0, + cur_total_ballot: 0, + accounts: LookupMap::new(StorageKeys::Account), + }), + } + } +} + +impl Contract { + fn data(&self) -> &ContractData { + match &self.data { + VContractData::Current(data) => data, + } + } + + fn data_mut(&mut self) -> &mut ContractData { + match &mut self.data { + VContractData::Current(data) => data, + } + } +} diff --git a/referendum/src/owner.rs b/referendum/src/owner.rs new file mode 100644 index 0000000..898833c --- /dev/null +++ b/referendum/src/owner.rs @@ -0,0 +1,108 @@ +//! Implement all the relevant logic for owner of this contract. + +use crate::*; + +#[near_bindgen] +impl Contract { + /// Change owner. Only can be called by owner. + pub fn set_owner(&mut self, owner_id: ValidAccountId) { + self.assert_owner(); + self.data_mut().owner_id = owner_id.as_ref().clone(); + } + + /// Get the owner of this account. + pub fn get_owner(&self) -> AccountId { + self.data().owner_id.clone() + } + + pub fn modify_genesis_timestamp(&mut self, genesis_timestamp: u64) { + self.assert_owner(); + assert!( + env::block_timestamp() <= self.data().genesis_timestamp, + "ERR_HAS_LAUNCHED" + ); + self.data_mut().genesis_timestamp = genesis_timestamp; + } + + pub(crate) fn assert_owner(&self) { + assert_eq!( + env::predecessor_account_id(), + self.data().owner_id, + "ERR_NOT_ALLOWED" + ); + } + + pub(crate) fn assert_launch(&self) { + assert!( + env::block_timestamp() > self.data().genesis_timestamp, + "ERR_NOT_LAUNCHED" + ); + } + + /// Migration function. + /// For next version upgrades, change this function. + #[init(ignore_state)] + #[private] + pub fn migrate() -> Self { + let prev: Contract = env::state_read().expect("ERR_NOT_INITIALIZED"); + prev + } +} + + +#[cfg(target_arch = "wasm32")] +mod upgrade { + use near_sdk::env::BLOCKCHAIN_INTERFACE; + use near_sdk::Gas; + + use super::*; + + const BLOCKCHAIN_INTERFACE_NOT_SET_ERR: &str = "Blockchain interface not set."; + + /// Gas for calling migration call. + pub const GAS_FOR_MIGRATE_CALL: Gas = 5_000_000_000_000; + + /// Self upgrade and call migrate, optimizes gas by not loading into memory the code. + /// Takes as input non serialized set of bytes of the code. + #[no_mangle] + pub extern "C" fn upgrade() { + env::setup_panic_hook(); + env::set_blockchain_interface(Box::new(near_blockchain::NearBlockchain {})); + let contract: Contract = env::state_read().expect("ERR_CONTRACT_IS_NOT_INITIALIZED"); + contract.assert_owner(); + let current_id = env::current_account_id().into_bytes(); + let method_name = "migrate".as_bytes().to_vec(); + unsafe { + BLOCKCHAIN_INTERFACE.with(|b| { + // Load input into register 0. + b.borrow() + .as_ref() + .expect(BLOCKCHAIN_INTERFACE_NOT_SET_ERR) + .input(0); + let promise_id = b + .borrow() + .as_ref() + .expect(BLOCKCHAIN_INTERFACE_NOT_SET_ERR) + .promise_batch_create(current_id.len() as _, current_id.as_ptr() as _); + b.borrow() + .as_ref() + .expect(BLOCKCHAIN_INTERFACE_NOT_SET_ERR) + .promise_batch_action_deploy_contract(promise_id, u64::MAX as _, 0); + let attached_gas = env::prepaid_gas() - env::used_gas() - GAS_FOR_MIGRATE_CALL; + b.borrow() + .as_ref() + .expect(BLOCKCHAIN_INTERFACE_NOT_SET_ERR) + .promise_batch_action_function_call( + promise_id, + method_name.len() as _, + method_name.as_ptr() as _, + 0 as _, + 0 as _, + 0 as _, + attached_gas, + ); + }); + } + } + +} diff --git a/referendum/src/session.rs b/referendum/src/session.rs new file mode 100644 index 0000000..9b2065b --- /dev/null +++ b/referendum/src/session.rs @@ -0,0 +1,45 @@ +//! Session stores information per session + +use crate::*; + +use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::{Balance, Timestamp}; +use near_sdk::serde::{Deserialize, Serialize}; +use near_sdk::json_types::{U128}; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Copy, Default)] +pub struct SessionInfo { + pub session_id: u32, + // pub expire_time: Timestamp, + pub expire_amount: Balance, +} + +impl Contract { + /// update sessions. + pub(crate) fn fresh_sessions(&mut self) { + self.assert_launch(); + let cur_session_id = (env::block_timestamp() - self.data().genesis_timestamp) / SESSION_INTERMAL; + + let head = self.data().cur_session; + if self.data().sessions[1].session_id == 0 { + // TODO: need initiate all sessions according to genesis timestamp + } else { + // checkpoint logic + for i in 0..MAX_SESSIONS { + let idx = (i + head) % MAX_SESSIONS; + let session = self.data().sessions[idx].clone(); + if (session.session_id as u64) < cur_session_id { + // expire ballot + self.data_mut().cur_total_ballot -= session.expire_amount; + // prepare for new session + self.data_mut().sessions[idx].expire_amount = 0; + self.data_mut().sessions[idx].session_id = session.session_id + MAX_SESSIONS as u32; + } else { + // spin to the new head + self.data_mut().cur_session = idx; + break; + } + } + } + } +} \ No newline at end of file diff --git a/referendum/src/utils.rs b/referendum/src/utils.rs new file mode 100644 index 0000000..5369d00 --- /dev/null +++ b/referendum/src/utils.rs @@ -0,0 +1,29 @@ +//! Utils stores pub info + +use near_sdk::json_types::U128; +use near_sdk::{ext_contract, Gas}; + +/// Attach no deposit. +pub const NO_DEPOSIT: u128 = 0; + +pub const GAS_FOR_RESOLVE_TRANSFER: Gas = 10_000_000_000_000; + +pub const GAS_FOR_FT_TRANSFER: Gas = 20_000_000_000_000; + +/// meanwhile the max locking period +pub const MAX_SESSIONS: usize = 24; + +/// each session lasts 30 days +pub const SESSION_INTERMAL: u64 = 3600 * 24 * 30 * 1_000_000_000; + +/// make the default launch time to be 30 days after contract initiation +pub const DEFAULT_GENESIS_OFFSET: u64 = 3600 * 24 * 30 * 1_000_000_000; + +#[ext_contract(ext_self)] +pub trait Unlock { + fn callback_post_unlock( + &mut self, + sender_id: AccountId, + amount: U128, + ); +} \ No newline at end of file diff --git a/res/referendum.wasm b/res/referendum.wasm new file mode 100755 index 0000000000000000000000000000000000000000..4a48bec4aaecf4c208bf65079d02f63dfc9c1895 GIT binary patch literal 168486 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 Date: Mon, 27 Dec 2021 12:05:37 +0800 Subject: [PATCH 2/7] add proposal mod --- referendum/src/account.rs | 27 ++- referendum/src/lib.rs | 17 +- referendum/src/proposals.rs | 355 ++++++++++++++++++++++++++++++++++++ referendum/src/utils.rs | 37 +++- 4 files changed, 429 insertions(+), 7 deletions(-) create mode 100644 referendum/src/proposals.rs diff --git a/referendum/src/account.rs b/referendum/src/account.rs index f8f03f8..b6d0866 100644 --- a/referendum/src/account.rs +++ b/referendum/src/account.rs @@ -6,9 +6,12 @@ use crate::utils::{ext_self, GAS_FOR_FT_TRANSFER, GAS_FOR_RESOLVE_TRANSFER, NO_D use near_contract_standards::fungible_token::receiver::FungibleTokenReceiver; use near_contract_standards::fungible_token::core_impl::ext_fungible_token; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::collections::LookupMap; use near_sdk::{Balance, AccountId, assert_one_yocto, PromiseOrValue, log, PromiseResult}; use near_sdk::json_types::U128; +use crate::proposals::Vote; + #[derive(BorshDeserialize, BorshSerialize)] pub enum VAccount { Current(Account), @@ -29,6 +32,12 @@ impl From for VAccount { } } +#[derive(BorshSerialize, BorshDeserialize)] +pub struct AccountVote { + pub vote: Vote, + pub amount: Balance, +} + /// Account information. #[derive(BorshSerialize, BorshDeserialize)] pub struct Account { @@ -38,8 +47,8 @@ pub struct Account { pub ballot_amount: Balance, /// unlocking session id pub unlocking_session_id: u32, - // TODO: record proposal voting info, when ballot_amount changes, should update this one and global proposal vote info - // pub proposals: HashMap, + /// Record proposal voting info, when ballot_amount changes, should update this one and global proposal vote info + pub proposals: LookupMap, } impl Account { @@ -59,7 +68,6 @@ impl Account { } else { 0 } - } } @@ -93,9 +101,20 @@ impl Contract { let mut account = self.data().accounts.get(account_id).map(|va| va.into_current()).expect("ERR_USER_NOT_REGISTER"); let amount = account.unlock(cur_session_id); self.data_mut().accounts.insert(account_id, &account.into()); - // TODO: call withdraw to send unlock token back to user amount } + + pub(crate) fn internal_vote(&mut self, account_id: &AccountId, proposal_id: u64, vote: &Vote) -> Balance { + let mut account = self.data().accounts.get(account_id).map(|va| va.into_current()).expect("ERR_USER_NOT_REGISTER"); + assert!(!account.proposals.contains_key(&proposal_id), "ERR_ALREADY_VOTED"); + let account_vote = AccountVote { + vote: vote.clone(), + amount: account.ballot_amount, + }; + account.proposals.insert(&proposal_id, &account_vote); + self.data_mut().accounts.insert(account_id, &account.into()); + account_vote.amount + } } #[near_bindgen] diff --git a/referendum/src/lib.rs b/referendum/src/lib.rs index cc85a15..467ea09 100644 --- a/referendum/src/lib.rs +++ b/referendum/src/lib.rs @@ -9,9 +9,11 @@ use near_sdk::{env, near_bindgen, AccountId, Balance, PanicOnDefault, PromiseOrV use crate::session::SessionInfo; use crate::account::VAccount; +use crate::proposals::VersionedProposal; use crate::utils::*; mod session; +mod proposals; mod account; mod utils; mod owner; @@ -20,7 +22,9 @@ near_sdk::setup_alloc!(); #[derive(BorshStorageKey, BorshSerialize)] pub enum StorageKeys { - Account, + Accounts, + Proposals, + AccountProposals, } #[derive(BorshDeserialize, BorshSerialize)] @@ -45,6 +49,12 @@ pub struct ContractData { cur_total_ballot: Balance, accounts: LookupMap, + + /// Last available id for the proposals. + pub last_proposal_id: u64, + /// Proposal map from ID to proposal information. + pub proposals: LookupMap, + pub lock_amount_per_proposal: Balance, } #[derive(BorshSerialize, BorshDeserialize)] @@ -73,7 +83,10 @@ impl Contract { sessions: [SessionInfo::default(); MAX_SESSIONS], cur_session: 0, cur_total_ballot: 0, - accounts: LookupMap::new(StorageKeys::Account), + accounts: LookupMap::new(StorageKeys::Accounts), + last_proposal_id: 0, + proposals: LookupMap::new(StorageKeys::Proposals), + lock_amount_per_proposal: DEFAULT_LOCK_NEAR_AMOUNT_FOR_PROPOSAL, }), } } diff --git a/referendum/src/proposals.rs b/referendum/src/proposals.rs new file mode 100644 index 0000000..c22d19a --- /dev/null +++ b/referendum/src/proposals.rs @@ -0,0 +1,355 @@ +use std::collections::HashMap; + +use near_contract_standards::fungible_token::core_impl::ext_fungible_token; +use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::json_types::{Base64VecU8, U128, U64}; +use near_sdk::{log, AccountId, Balance, Gas, PromiseOrValue, Timestamp, Promise}; +use near_sdk::serde::{Deserialize, Serialize}; + +use crate::*; +use crate::utils::Rational; + + +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] +#[serde(crate = "near_sdk::serde")] +pub enum VotePolicy { + Relative(Rational, Rational), + Absolute(Rational, Rational), +} + +impl VotePolicy { + + /// the priority sequense is Remove, Fail, Pass + pub fn judge(&self, aye: &Balance, nay: &Balance, remove: &Balance, total: &Balance) -> ProposalStatus { + match self { + VotePolicy::Relative(limit, threshold) => { + let voted = aye + nay + remove; + if limit.pass(&voted, total) { + if threshold.pass(remove, &voted) { + ProposalStatus::Removed + } else if threshold.pass(nay, &voted) { + ProposalStatus::Rejected + } else if threshold.pass(aye, &voted) { + ProposalStatus::Approved + } else { + ProposalStatus::InProgress + } + } else { + ProposalStatus::InProgress + } + }, + VotePolicy::Absolute(pass_threshold, fail_threshold) => { + if fail_threshold.pass(remove, total) { + ProposalStatus::Removed + } else if fail_threshold.pass(nay, total) { + ProposalStatus::Rejected + } else if pass_threshold.pass(aye, total) { + ProposalStatus::Approved + } else { + ProposalStatus::InProgress + } + }, + // _ => ProposalStatus::InProgress, + } + } + + pub fn is_valid(&self) -> bool { + match self { + VotePolicy::Relative(limit, threshold) => { + limit.is_valid() && threshold.is_valid() + }, + VotePolicy::Absolute(pass_threshold, fail_threshold) => { + pass_threshold.is_valid() && fail_threshold.is_valid() + }, + } + } + +} + +/// Status of a proposal. +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, PartialEq, Debug)] +#[serde(crate = "near_sdk::serde")] +pub enum ProposalStatus { + WarmUp, + InProgress, + /// If quorum voted yes, this proposal is successfully approved. + Approved, + /// If quorum voted no, this proposal is rejected. Bond is returned. + Rejected, + /// If quorum voted to remove (e.g. spam), this proposal is rejected and bond is not returned. + /// Interfaces shouldn't show removed proposals. + Removed, + /// Expired after period of time. + Expired, +} + +/// Kinds of proposals, doing different action. +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize)] +#[cfg_attr(not(target_arch = "wasm32"), derive(Clone, Debug))] +#[serde(crate = "near_sdk::serde")] +pub enum ProposalKind { + /// Just a signaling vote, with no execution. + Vote, +} + +impl ProposalKind { + /// Returns label of policy for given type of proposal. + pub fn to_policy_label(&self) -> &str { + match self { + ProposalKind::Vote => "vote", + } + } +} + +/// Set of possible action to take. +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug)] +#[serde(crate = "near_sdk::serde")] +pub enum Action { + /// Vote to approve given proposal or bounty. + VoteApprove, + /// Vote to reject given proposal or bounty. + VoteReject, + /// Vote to remove given proposal or bounty (because it's spam). + VoteRemove, + /// Finalize proposal, called when it's expired to return the funds + /// (or in the future can be used for early proposal closure). + Finalize, +} + +impl Action { + pub fn to_policy_label(&self) -> String { + format!("{:?}", self) + } +} + +/// Votes recorded in the proposal. +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug)] +#[serde(crate = "near_sdk::serde")] +pub enum Vote { + Approve = 0x0, + Reject = 0x1, + Remove = 0x2, +} + +impl From for Vote { + fn from(action: Action) -> Self { + match action { + Action::VoteApprove => Vote::Approve, + Action::VoteReject => Vote::Reject, + Action::VoteRemove => Vote::Remove, + _ => unreachable!(), + } + } +} + +/// Proposal that are sent to this DAO. +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize)] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug))] +#[serde(crate = "near_sdk::serde")] +pub struct Proposal { + /// Original proposer. + pub proposer: AccountId, + /// The locked near as the endorsement of this proposal + pub lock_amount: Balance, + /// Description of this proposal. + pub description: String, + /// Voting rule details + pub vote_policy: VotePolicy, + /// Kind of proposal with relevant information. + pub kind: ProposalKind, + /// Current status of the proposal. + pub status: ProposalStatus, + /// Count of votes per role per decision: Aye / Nay / Remove / Total. + pub vote_counts: [Balance; 4], + /// Session ID for voting period. + pub session_id: u32, + /// the nano seconds of voting begin time after the session begin for the proposal, + /// before this time, proposer can remove this immediately. + pub start_offset: Timestamp, + /// the nano seconds of voting lasts after start_offset for the proposal, + /// An inprogress poposal would change to expired after it. + /// The (start_offset+lasts) should less than SESSION_INTERVAL. + pub lasts: Timestamp, +} + +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize)] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug))] +#[serde(crate = "near_sdk::serde")] +pub enum VersionedProposal { + Default(Proposal), +} + +impl From for Proposal { + fn from(v: VersionedProposal) -> Self { + match v { + VersionedProposal::Default(p) => p, + } + } +} + +impl Proposal { + /// Adds votes to proposal. + /// pre-requisite: status == InProgress + pub fn update_votes( + &mut self, + vote: &Vote, + amount: &Balance, + total: &Balance, + ) { + self.vote_counts[vote.clone() as usize] += amount; + self.vote_counts[3] = total.clone(); + + self.status = self.vote_policy.judge( + &self.vote_counts[0], + &self.vote_counts[1], + &self.vote_counts[2], + &self.vote_counts[3] + ); + } + + pub fn get_cur_status(&self, genesis_ts: Timestamp) -> ProposalStatus { + let cur_ts = env::block_timestamp(); + let session_start = genesis_ts + self.session_id as u64 * SESSION_INTERMAL; + let begin_ts = session_start + self.start_offset; + let end_ts = begin_ts + self.lasts; + match self.status { + ProposalStatus::WarmUp => { + if cur_ts > end_ts { + ProposalStatus::Expired + } else if cur_ts > begin_ts { + ProposalStatus::InProgress + } else { + self.status.clone() + } + }, + ProposalStatus::InProgress => { + if cur_ts > end_ts { + ProposalStatus::Expired + } else { + self.status.clone() + } + }, + _ => self.status.clone(), + } + } +} + +#[near_bindgen] +impl Contract { + /// Add proposal to this DAO. + #[payable] + pub fn add_proposal(&mut self, description: String, kind: ProposalKind, vote_policy: VotePolicy, session_id: u32, start_offset_sec: u32, lasts_sec: u32) -> u64 { + // check point + self.fresh_sessions(); + + let proposer = env::predecessor_account_id(); + + // check vote_policy + assert!(vote_policy.is_valid(), "ERR_ILLEGAL_VOTE_POLICY"); + + // check and lock deposit + let deposit_amount = env::attached_deposit(); + assert!(deposit_amount <= self.data().lock_amount_per_proposal, "ERR_NOT_ENOUGH_LOCK_NEAR"); + if deposit_amount > self.data().lock_amount_per_proposal { + Promise::new(proposer.clone()).transfer(deposit_amount - self.data().lock_amount_per_proposal); + } + + // TODO: check time validation, session_id gte cur_session_id, (session_id.begin_ts+start_offset+lasts) lt (session_id+1).begin_ts + + let ps = Proposal { + proposer, + lock_amount: self.data().lock_amount_per_proposal, + description, + vote_policy, + kind, + status: ProposalStatus::WarmUp, + vote_counts: [0; 4], + session_id, + start_offset: sec_to_nano(start_offset_sec), + lasts: sec_to_nano(lasts_sec), + }; + + // actually add proposal to this DAO + let id = self.data().last_proposal_id; + self.data_mut().proposals.insert(&id, &VersionedProposal::Default(ps)); + self.data_mut().last_proposal_id += 1; + + id + } + + /// proposer can call this to remove proposal before start time. + pub fn remove_proposal(&mut self, id: u64) -> bool { + // sync point + self.fresh_sessions(); + let proposal: Proposal = self.data().proposals.get(&id).expect("ERR_NO_PROPOSAL").into(); + assert_eq!(proposal.proposer, env::predecessor_account_id(), "ERR_NOT_ALLOW"); + let cur_status = proposal.get_cur_status(self.data().genesis_timestamp); + match cur_status { + ProposalStatus::WarmUp => { + if proposal.lock_amount > 0 { + Promise::new(proposal.proposer.clone()).transfer(proposal.lock_amount); + } + self.data_mut().proposals.remove(&id); + true + }, + _ => false, + } + } + + /// When a proposal expired, the proposer can call this to redeem locked near + pub fn redeem_near_in_expired_proposal(&mut self, id: u64) -> bool { + // sync point + self.fresh_sessions(); + let mut proposal: Proposal = self.data().proposals.get(&id).expect("ERR_NO_PROPOSAL").into(); + assert_eq!(proposal.proposer, env::predecessor_account_id(), "ERR_NOT_ALLOW"); + let cur_status = proposal.get_cur_status(self.data().genesis_timestamp); + proposal.status = cur_status; + if proposal.lock_amount > 0 && proposal.status == ProposalStatus::Expired { + Promise::new(proposal.proposer.clone()).transfer(proposal.lock_amount); + proposal.lock_amount = 0; + self.data_mut().proposals.insert(&id, &VersionedProposal::Default(proposal)); + true + } else { + false + } + } + + /// Act on given proposal by id, if permissions allow. + /// Memo is logged but not stored in the state. Can be used to leave notes or explain the action. + pub fn act_proposal(&mut self, id: u64, action: Action, memo: Option) -> bool { + // sync point + self.fresh_sessions(); + + let vote: Vote = action.into(); + + let mut proposal: Proposal = self.data().proposals.get(&id).expect("ERR_NO_PROPOSAL").into(); + let cur_status = proposal.get_cur_status(self.data().genesis_timestamp); + proposal.status = cur_status; + + // check proposal is inprogress + assert_eq!(proposal.status, ProposalStatus::InProgress, "ERR_PROPOSAL_NOT_VOTABLE"); + + let account_id = env::predecessor_account_id(); + + // get vote amount for this action + let ballot_amount = self.internal_vote(&account_id, id, &vote); + + // update and judge proposal result + proposal.update_votes(&vote, &ballot_amount, &self.data().cur_total_ballot); + + if proposal.status == ProposalStatus::Approved || proposal.status == ProposalStatus::Rejected { + // return lock near to proposer + Promise::new(proposal.proposer.clone()).transfer(proposal.lock_amount); + proposal.lock_amount = 0; + } + + self.data_mut().proposals.insert(&id, &VersionedProposal::Default(proposal)); + + if let Some(memo) = memo { + log!("Memo: {}", memo); + } + + true + } +} \ No newline at end of file diff --git a/referendum/src/utils.rs b/referendum/src/utils.rs index 5369d00..2f6c5a1 100644 --- a/referendum/src/utils.rs +++ b/referendum/src/utils.rs @@ -1,7 +1,9 @@ //! Utils stores pub info use near_sdk::json_types::U128; -use near_sdk::{ext_contract, Gas}; +use near_sdk::{ext_contract, Gas, Balance, Timestamp}; +use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::serde::{Deserialize, Serialize}; /// Attach no deposit. pub const NO_DEPOSIT: u128 = 0; @@ -19,6 +21,39 @@ pub const SESSION_INTERMAL: u64 = 3600 * 24 * 30 * 1_000_000_000; /// make the default launch time to be 30 days after contract initiation pub const DEFAULT_GENESIS_OFFSET: u64 = 3600 * 24 * 30 * 1_000_000_000; +/// default locking amount is 10 near for each proposal +pub const DEFAULT_LOCK_NEAR_AMOUNT_FOR_PROPOSAL: Balance = 10_000_000_000_000_000_000_000_000; + + +#[derive(Serialize, Deserialize, Clone)] +#[serde(crate = "near_sdk::serde")] +#[derive(BorshDeserialize, BorshSerialize)] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] +pub struct Rational { + numerator: u32, + denominator: u32, +} + +impl Rational { + + pub fn pass(&self, num: &Balance, denom: &Balance) -> bool { + // TODO: implement using U256 to judge num/denom >= self + true + } + + pub fn is_valid(&self) -> bool { + self.numerator > 0 && self.denominator >= self.numerator + } +} + +pub fn nano_to_sec(nano: Timestamp) -> u64 { + nano / 1_000_000_000 +} + +pub fn sec_to_nano(sec: u32) -> Timestamp { + sec as u64 * 1_000_000_000 +} + #[ext_contract(ext_self)] pub trait Unlock { fn callback_post_unlock( From 2bab2960f560b0526a84e4b2931c55628ffcb1ca Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 27 Dec 2021 17:58:38 +0800 Subject: [PATCH 3/7] fixs --- referendum/src/proposals.rs | 4 ---- res/referendum.wasm | Bin 168486 -> 211182 bytes 2 files changed, 4 deletions(-) diff --git a/referendum/src/proposals.rs b/referendum/src/proposals.rs index c22d19a..da5a56e 100644 --- a/referendum/src/proposals.rs +++ b/referendum/src/proposals.rs @@ -112,9 +112,6 @@ pub enum Action { VoteReject, /// Vote to remove given proposal or bounty (because it's spam). VoteRemove, - /// Finalize proposal, called when it's expired to return the funds - /// (or in the future can be used for early proposal closure). - Finalize, } impl Action { @@ -138,7 +135,6 @@ impl From for Vote { Action::VoteApprove => Vote::Approve, Action::VoteReject => Vote::Reject, Action::VoteRemove => Vote::Remove, - _ => unreachable!(), } } } diff --git a/res/referendum.wasm b/res/referendum.wasm index 4a48bec4aaecf4c208bf65079d02f63dfc9c1895..6a618a60f8bd8337d16a9248928696db753c2463 100755 GIT binary patch literal 211182 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 delta 52986 zcmb?^349bq_WxAPkx3>;14+o8o*@Yd1PCYzC_*|YiYMOJD&DR^MP2V}CdnjnN}$m~ zMGXpq3W|t=h!6w;6(uMtC~8ntR8UY<+(rF=Usd-^hs)jH=TCH|>w5L-UG?f!beclkZ+AUa{VPaGlij5joRwOTT9B5K79vO~DFvxse}Vm%8nUXV zrlgdXrKF;bURFk!cwMFR&)XxzTaXF}DLpbWdS;|DZwCIQ=w_u~5104iJc+qI35kgT zx7*K|FDZ$;nU3<}lvHmhH6_iD9(()y^znQ9^wE14`O^ToLa#{mdRb};p^yK&Clmr% z^im8gi$iIpAXJLiTbNa-`%?=F{nj}A7@;JZUf?Y#(9ypabWwC9FxEf6^&Qefpr&4= z7lAgZsTf-d28-c=Lf+IeuNS!)jG=ZHZD%J<4rWO@@yQhEzx*p2V zQJw~VD+wqo0X(?q$rTEc=zEcV_fC|<00<8Q; zwY(B{&?pshfg}*XP*T#$AeLoCM-5C#8J=2}mXZSKC6Hi@0F97alvY+0N(<>}p`%ld z?w2y?80wG&0`w0RmiZxwA<96|nE0e`K8xhd)cLz zj~aQy=zrZj(#rptrCxRO$kEr2y!oa}um9IoSKj3Mg(d#$N@U%3JrcjO#H$0b)W4be zY#=B7KP=(8YtX^XSGx8w_w`ra=32zf&4Ik|0w8Iyz!vtn_i4`<@0}0(+SxMS%j~Xy zMcI?=3HH3Fk!|&!{f*~7Hp4fLeeN62KJwPHoxZW`3*S9A-hFd;^u4!7*sT*-BX8pO z@iBZXAIHb@349{IpHJe=d@`THO+J-Bz#rs-PvZ~qhxsFXI)9Wu#vc#!7CwVN!Jp(a z`7HhvpUvm+r};DdSw5G~(zvbR&XQ5}R_aW~zuj!rS zZS#HV+u_^h`_T8W_j&I#-e?|8R(KlXm& zUE^Klebc+q`>yu~?~mSH-re4n-q*c9d4Kk<_P*i$-TR04-$T9oyuW#W_3riF=bP<& z);HJpobP$xW4;f3AN$7mT6{nIUhu8(z3$uPTj^Wnd&9Te_k-^z-;cheDXaW%`67(7 zuv^?XouvzHJo6T6%NrvRSB)p=u5krDyjtg_+)p3LI@4Z=h}{EOK7YAUXh*SP(->A# zuriAJI@et&SI=%kt1XJ)AHbNSJLR(%&550=(a2oiDaV|XrnAS*H`6LJrj2inxGK3P z*&WcikyWd^wZ)BQy4L%Mg%eStO|FxW4ZW87*XSc%`efBRDp|MLyhW=l z+c6gHj2!I=!YSy}A(xfh1=M_1=!OUI#LIY*)^2Xpx|vII@&eyU>|N;kC9}TE>7755 zX>P1_p;L6CEi=FBGCE;dJphJ0W?ScM^XBvlw%nYRUY@d?a3S2&YqjO(XX(8i;1-!% zvQJ61!O;-3R`a#4I$u_Ae%`eJ5dQ2+aQbBRayhTh(Cz!@Kn6-$l*T zjBImv&d?Ys+H4pr%A&5^kYmA^J&;5in7BxzU*1GT{vZj{y5v-+^@E9KfnS?Q2>W)|u|=rqX?JmwKy zI_0N#{ZbZZ5Nx|l(hOw@U&ykBX5_T4V&5OkZw}Ja*&6e7eR#smx>m^FT62az(yyM| zqozMt=$l3A!o;Qb@-F86g?W5l)SO$G#pg!N)rAFo-FWlsLOp#uVIPD{86bZV#v5_z zW^u5Hy=9&l4Dt>2=5@gm-db-y5WFqiO5_Xrk~IjY_BJJee>Bn>aT#uH1*Jp2<5GOd zY0h#?1}OK$%e~2|j&f}mVLTP+=$rnK+h%@NIxtJ&=K`g8wOgSDd_r8XGgzL7IBlL*R>5Dd zH|xp_v$SUkvG?>l^3CgdCKA1a_37q>o;jTqvYhNPGcb^Pb5YMeY_<7K&q7OE-m5oL z%XN;DigGHsq`W_0Rd0&&I|<|qy@CX;vR5fd$R)ipDRq0VDo5Fay^GAfy|U8m!ISAG z{0e)^%2mCs%30=^-pSPb!QMkk_p6MtLC$EnvMrK2!xIqrqxWEHb4;JEnN}O!eOwAj zjlb6L+@yVA*7iB(ytO1SFkMV*B1=JVnBl3_8l~OPU8Ni*g6bIQP{mh>`O=CR3(0z* z*+<0gKqn|Ps-kbM=124KiX-^gMsxSsUHOjj=FSQ|)3zAgsIU!&D{!h{-?OgfseKE1 zG-{6Sn@cljTfgl6zTSv}FsH4c{NY@BZX)$dAP-)LTSL?z!AF&{f(2quNk zj>tQ9sl>g?*j|q@XkXC?^hBc_Q-D|dwVFWNin}d%Wl3s5W zW!YAlY2TQWkL(eC#Yr6^?@_K~SRzc+eqN0zF_ISP6dM(Q|e;LrJWJe?Q zlO5Wv_3OK7`P+Z@k(?B_rds-cPqUcgQY zTE-N9wltaibpxc&Bq64^Knh)lELMCe3Q9-a9((mN1|tvvSMWb;6}u2wZu$dyfdQ}a#5&#Mp(N7 z6)qsf%G|CRc6y4-*foVpGsp@NMiu}VMBASZRLKUC3dY8Vsdf)%ZS#yF**!|FIuaLP z3gh7f7suxWar&oN_FexXOV8aDC16#+7u`kfqr?`{7O02Vbpb0#T1G@8E6U77qc2}~ zpE<}Vp|2~9TE01Arqz_1e;68H8O7rO`Wjv{C@H=mGbhy)Cu|x=Ae+rsYp$Rg!J#Ks zZI@ZrQZKg3n@Fk<^47415%5)&<@Z2uJ%*~^Y(6ox)Cqm#P(8O>7vuvZGUsx4;^G4eu| zYwE*N6Q&dAb#C4{>{#;cT8Di{1D$((Zh~AJ8!mCoRdnbpHH)Apy%#V6-g z9jSe6lLKy#MUGE6CRG;4%t;VTp-g+!yzRttzO&Apbz%<>^-b{2?@mnWDWSz;4|xhY zQJ<)TkFK>??twVkxJI+^q@43xL@Px_vdHd~x&2k{^XSRgAlDtDHVE~{v>8qJGOJC=OD4I@JQnL2aDFWF|rnLU%+sdLn!<+C~Z zj3VApZ_Y`j7>~K)%wtr8+(beFHRi_JWjNar2pW)XrtRzPm6C3*J-x5p+jFs29ec|f zaa5+P>Y&baCiss(25b2t$*wkyq)EAMFV(d|Jv`b+X5aIR(q;UMD%x=`?S(q?n)CDWHqj`x z&*fOHC#gPiBBhmPp%ofsMmfy|DOr5;_!r+DSh6=gAl@6 z8}6Ty-bPff%pOZGfUa^ki) z7Nqb|pfB`?S4#~EaqT^lO1b2Pm7vh(9T~Yrss_2lA!gN3&heY(`dhR1Yx8EE*?xPv z8Mv*G@2oe=Z>#dIZ2(Mj)Or2QM{mmq1_5TNP}V+RHNu%I-TQoJu%f3#|vX;wG+`SN=6-umeZ zX1;kz*ry6lrZ0+SMH;>4`f#WHVb-YferDPjt3{?6iFk=}mqbUIYnxBFbppVSVhf6c<=z}t|+HRUQ153>Lj|9u#mrZ=+cle~^KtjQ*=}-63+=7o}ES(TD zYB1ZTXPmo_gpG3b<7lHm_m#QzmAfCW+7VP7mBhShykP6j=V#rL;D0%bhG z96Y_SP)%%zmr%#}plFg?+ai1P7@9e0R;D=RTb4W!GwuhL+)9UuJRU+E_{1h{?L(?T z)3h9y#Dbf(_6K1E z$g0r%zNI{G9(C3M<~I^%5DP@W?8(j(>`b0D3`#%Ss!G8j)%}=B)O|O5Es0UcRe`-$ zM9L101m2a7wc55g^=bdniVPO2G<8cd5Mnyk7BP%JR(%3NDqg-AtI^EA^OB8 z<9U(!-0b929OFc>k}hkU9s@zo*g$d``*kg^`z&D~FTsrk;au4=`)iYbQ$ z^8?(SXC+6yYW$WuAy5L!>vB1_$%A!+nfQkuMtzWv93G2z4CANS!cQN`+AK)|Jj!(v z19DUWZQ|hwt2JRqf$dg%6-H4Na4_2^yr!qkcvN^jT+il?nD71>>7+;T+Uyw zGgIFv>kboCihzP;xSB~#3Hxj5*Y~)d=sH-CyOlvkD#kkAuJ^}vSI#N1)(@WA3j$gK=?x=PIFc?+GJ!l&*+e=MlPk5_ULFgt(SS>t2yj_;B;)M!UPLuyK%?9iJ-J~vfTXQ z)e73{Nnd(C@oDtZ65^3qdW?UL!~s0ovUH%evExrpvRG8~+F-u4&Mf$#*c|&>p_B9r zUb`yE_N2jy(6Z+`NhE0l(pX<}WQ90a?FxVc)lxlm?1CW|%W_D|wB?t_Mg;mxp-XDb=U{Z&N5Rxh z(ld@R`n=Y1DrsshEa_OHxf4k;j)>ynLS{>8Q=Ox|cq0!!{}(QWg_p}dtO;kqQ-Wqzs7 zeBgsKEw;lx`DjB*1KWT9pn$KgGqXSJ+u!!P6=#!4XDr51-M4Hlx9p*kjc?5Ghc@F_ z%v$XJFps};P{s}Zs5@U*XI}l0eh|h5D5fJBC%Lm1y)HNBeRMk*SF&j=$TEM^#o>eV z$;Mp<6N1UfK2kt`Y{g&?$@{b`|{@Io?z=Qo5vvM z-j7c`1akq!{OaRwsFV0fEwS~MPi{~w%?}K~OyM&INY6WM%Q617Heb)$V)NCX+{NPS z^ew0GRm9h>CjYcN$sRLQdcdc(PFBzT^p;$ENn}$*GJTg~`k>E(dW@d~Y^zO*@{OEo zNomaB@~reRj7%WZ+_1sHRzLk&E{V+Q&-%ttKrZ_{y=zRlB}^I_@o=J9{<$q9{+N(H z_PJE<*FMipo%$GTaNLT2{dv!dbtG*xf0H~&Xh@OITdm^!%-FAy(cXhZ?z;8^z&+T0 zCRp`dd;T#87aba%ttPgdBpfIw=CNA`LJ;rW`dFp3AS4V@MRYB;xsVJQu@$`I%%Ewn zn`eB{El)NL=m8kcL`hf*Yx<07(nd}Gq7azA@I^L0-~NI`>$fkaA06)vhberH-lRPy z{@7i1FkL!z`RiwXN)jMQ-n2nTQ?HOzS}NT9)S#sj9S&lzsZ)vAGbNY zfn-Y%cdjbr%g7rziocDS{f&zLcF06YTVgV5(tHLB13s!5KM6BF3#J%$RmjZqZ#ZUs znl7EQK9)dgXPeeX3flTQ^Tw}3`_K9_zNT5f^_v{?udgehWfk9K9)D0)+td4hKdqb9 zYx;o=t>2uOEy)N2bpW-^57(3s5&vA1WA@#d-uWx(db_YC6=LV5-~>Q}dG5|~zRP1a z?mUscHtYrVV*MgB{l2}OkK1bAP?C?GX=RO_NoYr68P$H z^QznxD3w)Eb&N?kPgQzLaQq>k&hHK-=)SW;1Wv0ZlK6D@-MVYu-64K43b2syot~=} zWA=dBov5Rqgeo_d4YU_iiWEnL6Djx;)O8Fgq<|(?CbS2QCBr9m=Bq#Dg`1N`goOHiz-1|vxzLWpEbFagv#-aqX*P-pa)!dXwa9`88{=CD{|8q zG1f(d4ehVWDzFwm2h-&il?>w6uqvL1qA`z8*^^P)EQRR}0^=bZ8_(sRa?jHP@TRzxx__bBWb@i^|GJsli>HMgGG6$>Y= zgUe2@W$renbcY))Oe&9T=9E(?53D%Xy;bfOY|nF=An{4n zr^OY>hFHp{sZ%=ZPQYW|L;Gb+~V09SVc$YA&d|OkIB&-#_suw5*jS%biD))c{ zg-EryE|=x@0+l#C5#v6hiuSo&exW;Ec8B-?4cZtZ3!jUMmvUJ!+$vgWqpghr5UOTX zx#!478c!u}$Fns)pb^__gY?O4YuOFCu+Am_F4f8^qkd2ifMmy7BbKj}0R;WEAvgjE zq=0^9?g2qB926R(g^9KOLM^>yFf7jDghdUj!RA8bfp5mH_Gn*PJz)9a>_I`c0Hc5w zKuX{7ERjJ2pn#Z7rP!FqvU;6Y<(4CbHHt7C=Bt;HAc;=IA`G@5ZzmENdqqY*D;&Cu zm=N+oe--OJH<7IbYbl^77uJ#rRyWv#hUCLiR`Qt^NwwwTwtQA_f_>I(A$d^NSu@$x z!d#s9tyMIn+QZc&v$G{|xS zLTr85QWYYUS^}W}>akqhP{4Ye`(K<@v;0`8wc6p%s!?o)tMh1LcL7TeulKoOd+v4H z+wAk%sF0@!Xk&;T?H7`#5Hu~qc(whf<3xm--b!n0T-vWv<`9`GO?5N8X@rT**aim6 z-7q!v#q6qw?CM#luuqBoh_FHP8g$c;v41?%DZc2mR`6mK0mkG#E`pR%YRr9za_u;S zhjfY7`h+UD%d0VZvMpqMHWEeU3`~YArgF%%kdrpkQ^Ugwo#_O+l8=C}W7^fB*z^QV zspOX^{1j%E23o;BplxX&MxRBYygW^5pd3;RHPu!p#H7U|LQ+2?LcXx{#Ys3lw93XO z))&xB6~rUDK-WEF0_;qrASW^f-B9$BegRAyV4fFDkkN!17tZpa7|O2IhG_Ozz-%y< z6$mF1F?uK3^oE1va@uI`sdJ?%Ex|h5T@9DX+hZdmikAa07t|!_l zay7=#=_NQige)OApvv8B;SGv}>5=HDjH(Qm9*$p%U7JWgV(ikS%_M%!A)9${hDjfb zI#SV8JCGVqJ_yGg@uitk5-pjF1^=fybHP=m<{o1{v#0gnIE$;)VLYfXi6lIixC=!L zR~b{JS&+}jL5%uG%7CS2NOm-pa`vB-1cJh8hN*0kk48%p=+T@c<;{izCrN7~Kp_tH z;ax6dK##yxG;K*D^C{1SxTtjp^NE5=J{6FuM2*>CbQlYQP2H#hd=kW^q)|qNu|q2D zSJIx)NM%!L-f7Pe{Zr6>uQVZYjGtSBj&;GSb!-qddx5MR0_pr1s)T-tD7N!AKXz)U z+2d923At6>q$x9655a>lUiYv%Z;ee;E{a1duMvG9pFWYZn7R!T^(m#8F3Z)kBr`c1 z60ffbEFoV8ZyV=5Nxz~vM@Gfee4FeR^pC-}X!U?a0Z6O`T#<`f=^&S%K9aSCilkU> z%ClKupS9XR7{E(&Ye@Np$lv6p&O=bf3Z&X(3e!E|Axeu`X<=+Az{~RF<7jD9#OPwy zHQef@7B(@+9B8{OREcypC)@2rTY0nH+nPeWrj#^VR5&={gZZvC`hF#lEWTiR5 zTDFtB)B#b6j%2T|hATAq{OO{#J1aZI#slKxGn!)t4=AV&QOn+0Wq*T*s4QhAVI>}3 zOX9KhFI!>gwz&g)Tc?9RMw-!1-?4SKox97K3%rP&(m#-~Wpy-AQkVP#qH2^HRPx*5 z9$+V|l%<3xND$Tu@o12Bvk=9#PI%s{&HheN<3|xBui~4;kB)Qo}cEOCsel_8Y z^uYu?wuzoS*x&)SmeU|?EsqUCQ?rd*Pb9Y-f{wp3cLf0xGkUNtVd{l!2Yt$s13A3! zE#YH2*h4aF%}rVdHy*i_e7nRErchxAAZU(dk3Bb8fB|R&0g`i*B8)XPg@H(HZldj8 z;7BSWC#8*Yzz3O>B+`Vaf@M!iiec8IggH*3V>2vfV(n=OB}Q%JJtTh8*rDuhC(_N3jgmUJD@ z!MA&8t)Z4zl8;ywxvKakPs~x_m^X_chL}SKfXyl}!>bWyLl&{!bq-BaI-EcpZ#Oo{ zHI8O%e=H2-ZQZVkpRJ2Hw~%eog4^9HV{u)KjWT?q!a$4yL{{h1+=wIm7n5{MGvzUl zuN%aVV@zlv9Bp0vn>lo`t&3_7B?VLwJD0Jp;~ZLssmY!|b-8{P zKlftk-EEyBWNe*^A!F$j5EH$7v&{WwQ0>?MVfNf6N!h)l+#GVYR79}s-{-a~8iwS} z|6AkN>=?;`uBcR{?ezW`1rz=^Uo=e4D8f9v8gy=!kf^g49SV>1|Kf{!0jR~+N2f1p z6;MBbXsLbJ5{^SUqfqC#FB*fZkhLbgL%5u+oZiT_qr)u+C$a{?w4F^vB_YQnDj>(x z9C9q@4rFu`V_-lpuvu;(iplUmK?&WLZ4sUpn@(Dkn{k9rwwRu*Zrf@-gm_s|j7&HnfwA-ROuEW_;g5Hq9uuM`FAuN0x1; zRVRBb!k`PAFnEj+CT7q&LmcU#2-!~cf)CDi$Ftz>Jrs?=>Sj7J5rKmzJ&Ah2i<|Mv z+Wj(XsozVIMK9CE7BlUMv2ZIaeFXBrv?UTn1ev2=I#?`6j<{gNdT|4NRJnC@#f=Hx z+7On%m_X?ue8M2fuN5jK0q5r~g% zN+f590zN@H_aq$-Oa_T~$rYetm{r)q=Rh(6ND>ic^p_?D$t&15V=28VgXVO3fnwhZ zMH!ps;8Q7a(o6AeRYPtID1d}G5grB51M>0^`jjat*zo!6Mhg_-q*TZkTkQ_uHlZmL z0bVCplb-Uakb;2V8E@ai$qY+pLe6+rIXpMYlTk82p(l8Ww8TxP5lS}3h9^A}btDZQ z7}{Ycip&iKwWO0t&KD$;@^&b&8hLp#l1EZ?j`Br~D5O+!0-iAH`BkO8c!bfR`qCc+ z#a+7puuQ?e8;B#Gsbqb_QSV`^(!~Q99{6zBYI2Lkl2PfA;!W)M8)t_RlHSA|LZ>~^ zvaEp*xSK=Qq3=?IA*qUjOnaqHjASf3gS@lcqM8mKGbSG{?LSDpIVEKAqEAe3S+JlSasj7(sf<87z!PtCc|dfN$` zD9UiS=fDD>-W)Gn799^X=aRxWc3?v_@P;7h~!Z__mh;vAz76GS`Zfwv%U1lH3h!K%;gH)uo1dh)raNLquz* zZE7hJUvL_mBz()U2UczHXKa^9E=Vy1A-!s`jyWcsR>{iZsEsfN zU|SG)!3>578HFU_Ch)UDFiQhalqIbsHo*oHd@@#8$kW~fY^N7b0FrJCfNXhemAe%A z5twrTBQN$kSrw@;#SkANRJ5-YNstHn?4ble;S(7U&)4cj*0HQN z|0*ixZe#=awy0pkSQqiYu`I;@jEYx|Wj%0hiTLVRR>D`-iAI9$HYwJa?<5@X>vtC?yJiCRzB`-t~T~1*6 zUFE@Etap6&G{LLEoi%3u2VKR*C$R2aWQBlTiZWcMGJ0v2n12E`%7D{rCtv{TJ4>Vu zX9?78)^K(P?m`jQ4re3MW`a&eo-utEzOm;f-X6{dB)lW3>@jz>r;CCUStz?rX5d86 zd|5vjuYdlDtaqM7!^Xn?c1v9A#giw3UT@Wl^#DZt{rN;Tl)4{q5*sjZodk?CWbGCr zQ|a5@{4;hvN$3TQea>7WLA`kTBvziI5XCV8DWftjyw<{f#sldZrU|dQQU|JnliH%o z$?Q>k$P=EihP?b_7A#&v%|hPUA)KVTktR07f2%Q~R?c)u!*Lc&cIrI^V|k}u^gV^; z(il!X1u_5*-g*kVriqYShb`70{HX1U;QzO_Z1n8F$?06^k7oN^?kFWqO?f@uG&NqoJI1m}n z!Em2GomJ)8!!_{c1%^zw{LrH!)V|YMH^Mb|2KxswKYRu|ozm}}fp9iZNjj4i`raql z0h4V^7emivqpa(3ymU-kzAfUywKnh8i&bZ`zQaC`qHfTOqkt$&I?9FDT*xY7yjr_e zghPAr3#9OVrB~ZX9iXCK3;ex!#Znx77VFv5Za{9Nb&SsHkM0+eO|X=aQ;OJdCMyct zox`a_NHQ5{&?^{rQyAB|M7`J*S#VYTxWN)TCuC1Pu#j*a%?^Szy|m&0G+zR;@8Yrm zT|<`J!9ck?LQ2?=kmAv^S+_KcK2RP2gauoFHX9ta?$iKFzN7(> zkjo2-zMvF(#!Lj;M$fpQ1b(`vuE5&wehkI(z~zkJi%NT*Y6aPFcM-KCy8$-A3S(y3 zL^&akcyAmvZLu+Kab^C zQYYGrO#p~P2DY7PmlK5L#!#1flAeZJR*a2Sb@BLVJVT5*kCk0aRf8#dvJn~vrY6IS zI6lR1L{v8J?K1XJn_vnq>oWdrJ>snCUh5It%)eTXu%LgcM^H>pF*t@U(#~f&rQZNT zZ7-MWC>Nc?NijUP8Z+a0lyB2Dpzeu^ z61uTGdZpZPpOj?jK`wPllFWokKh`Mrea^BH^pftSdmK(+qA*pilb>5WXxbv7qTAWkqcQ#>dI&&LIMJ7gzK%u`U~0c zju&6}WDUc-=d@z`K7bwd_U!{HTS%%f%fn;G82Vq#`cx>_602|(x&YkmREYu(s8$5W z4lUd^8Q_*oy%-BEylZm$9VKL6$%y~wVwSD$hJ#AL@OUi4Bd?jn!3Q!t{YGM@*b)^N zjAVmylcnO#7B(fnIl}&YrxK4evr^g)h_k0=_M+5Y^AH zJZ-#EejUhR8kpK7u6>5(h~q9}LB1*~{&^WYJ7Ed6`5o$YD=YGElc|5#i(Qwol8pZl z?O^Y;)zl-{b)2@ZUi7@2l?7iTFFl0&K8y|X0KmTOY3cJwU}nNL_AQsQ^1uQrQ`b9* zxtFsXzjc+<@c5lLrRya2t0CFMgt-L4*!Cncpj3*vv9T^PMa+;bkf% zoUdTTDgl)5xq_7!NR(@6zO>O+rzv4uv_I>`nk!g!ce_8y^n>&#U*mN2m*L;@s@378 zSE9qElt70QuVe%NuET9tvSSk##nH_W<=3$^{|=c27#Ci}$__#2hpu8Z2`^bq>uzTm z;*uNCbgs-o)6}b3DAqk)%&6Fe@nSxN7Sni7y_%gL@BUVn@!*{RF=4Saf{(9e0}kk& zNiKK)CwiA7RkA@XJ>rwwm=+s<%RgD4oQ^VLcP@$j?LXP@7^?_8uf@@iIN8O4_Ap+wjU(0$NqE#EUBBimUTZ)U8 z@S@f4(Cb)_td117v@(Jd)sf5CApgFYZpdNUat3`)7m3%i&WGr@;(B)Zfr7HmZoc|@ zR&zj0B`Eo$K_$D>zBf9!{J?0;V&L-9(X1%O?+ zM|gsbaPXGHBb;_CJIcSxHfhrCZ*<6Jw%B$H>vTZ3N+%$o1?Ka66GY2xu;w!zK#CJO zz|OSPrXX&s;y<#(M0>t`1hI@^*(U zfTR`2glyjJEOdx|x806@r547mVVZxjt(WKD!MevJoYsUfQ;by()-Ytp9=n4b=ij!U zMNRYXv1gO6cd}l82jj9k4?3I7wbgX*0FAqe!*(;3&^J-hwB;X zqCMFlw%@}Bmdr(c+qqsRU5RGWN86PMkpDcZK^%WC3k`dMI+tDtK7jBCDosup!o|sU zB+_bwy12BM+RveS^4UeOp1+r6TyFXLxRnwiHR-Fntn0O77beOT#4~chvAjOgiPc`D zT-t*;+y#uHdl(Y5<+WA}XK91DIn0jI6y0e@#25tMvq3Biv#KK`IArN~vxp!|Z%C!T zQ)$F$G&zqTw_G+Xjj-q`D$8Smg@caJ0X4uoi;7M@x|vsbz=*=eD78~oLR5k7ok9dj zRuaEQAR#cjUF%qR{tvPWrgbkxm}pNA-*RtH`>{b>QU~$a)gU5uER*kU5Yy^dA8Pt$ z9n(WU$)*@2H3jIOWg5$HE4`;d1nS{(PgrJ=rlOwJoFs`5q*yV%psYwtabg6-=$I&u z7}2gE*S;la^acQy0yv!KhR7x;0zh_2z(Cd4>RHdQBo43EIURBJYQIrC8ZlzZMQXL= z#lZpF9cC1EHKadm?2tUO1KkI!vF~qdEKFEVql068eFH1&CglkDRbYQp`!gGY^ul3^HPw;Cpsn7@z$)){*#e|sf9qXREL+WKuh#qFhY4cIr zm`+(VxOcx}{lv3PtcFJ##g9#h3C?UXPa2|&Bkp6jWLgd7)H;V6s-?!V``E?VGUlh(+B?wZH3<}7l(RNoZa+H9gPY>z_M=rEA!W~VnIneeisQzzBl(*R;;ymmv`nc7 zyqZM9UPWtvHHh}Htb5Wb;+B!EH8zS)<5(B|OoJ#H$BbTY69-@@F?d=6lNjO=m*p>0 ztZ^(WvCN-34u0m0sCa!G>l085d{^K^#^F1pi}p`hB5M#i<5{;Ze>F-hd%>JQ9>MW< zaQ0?A%jUl}iBaRBsMbxG;+63TKW?DD0_KnD*|@SF{cD?L=WgvI^(~%Tz_LX94&eQM zgJh%l#{^aoT1@M~ASd*x)vGFrvEU8XzoIBJMBQiDFnE3f>r}LyU}@{=(=BO~VntJF z-3*L86vx;$f%PLj&zi`LuF9@(SOo_`H#LbHCbDT|)(F!ATAf-I8W<}`Pmn@VCGkX& z9ntrGgu+%dh$Z*4zDBDY5f;|TSTNK2THXt5Dxe5wtbk5*I8x|1o^mw8BktE$?Lp>v z9eQpRS2iOIzo|h?Zf1oXTD_o|ouqG+sC&_|vO{#rrky5E9fZ~%Z4mjBS=muCL(Z5F zP<>-5&HQ-jXsUGEtaxA+h=NerJF-Tboa(=C6cM!NTN}i)lUYI5ed1h>b z*gBb=n;h@up$2j66jpf-Zny9)vnsuAbvNoCGel9IC&}?P}EA22!V5B-vm;JkC-tr zCdg$KEa{x72)#{c6dR`Ez>ZvB1dT0n1#9um;QNZ=n*H|f+2qF7R#@MsT7_hF)H zvEc0J0LRYV=gb}KJo{%pa%qyd{sES#cujFXZ9;=+cz_K^mE)&48S`zG-!6(K z;GH(kVw5I+ya!i>|Cyd7dOgU}RVyn#|44&4?Ljt0!S>TO<@g4%^FcPKlY~Q-UwN02 z262>N7paP*!&*Jg5eRm^%5hW9lm_9S#-=-f-QOVQPhXSX+po)i|9% z9T|J1LRJ_v{O1>TYMN(AH`b#-3Br6F?I=m zwLv`c7#qyn8pJ1$vAitn+z4nQFATximjTk*6KRjLo_(j2|7a8&tE3-k->h)pdfwP5 zE5KVB^*DPpp^glqo*?dM!L~hme5nPt8SdAIE!d%%+#vR~0QNQsyTFJ_FYYj~r`m4b zc{5mX@qu9l=`_i(f-%#s`UI*{PjAj(J^70b;@26l*EoF}e1e^P7BN?ze4#f_${}xi zTV+lu-aL_qKNeFOkEM92VFezw)g%P2Kq7IB&KS}W&zW@U)7VCv0=OPbtaySQGc@u# zY9s8tO}4Tv(R`VUjdJ?7w`j-$2HLqB zoqzyFyEzbY@oGHbcqV)b!|rjW-MsZl_DrFj8(rnVV+yAQ7uP05#n_qbL_Q%ZKA6dh zl9~xEY+p={3im8F@C%|?5pg|;|hHv1=^5)}((v)*C5bgFYuaRPM6weec`U*y_wS2^oq zR+1+Y6M-zy&e0Ra$T_T^F;NZzVGW)3KHn(n2$y%z6l(iV$x?~PJ=@kqx^iEdXu4W|(ldFW~OFOGET zGw_mMjEX_eF#VuA9#uJy%30P+$A+*$O?ytX@#)bXjf&TvVdMFWP2$97Syh&*C+&mU ziJ^Mh+F$Fl-RdaD@=Dn!6dM@@%o}@AB7%_S>rmqGu zv@aXQ6LVRgq%~B8U#plI6`#z713i7U_+u`Pscejj-QVKWz+a8xAM;rG$+Sg@;nD{k zDwsjIV*%pKq+;nqKT9wJ-N^3;eZUA@EJ-&#lS{$0y-i~4JT@tL&ze>s#c3jVRMZ`d zP;m2e%v>B-LW_El$AV_`x0V>T~S)(7Lw(LVJ~3fQxv|886}Djd0k0 ze2|Y3T~zcuj@RVuTT2zkHlZSx$DP6Y32&+#(fk5CQ{U2|JXQCO(mT_fzQf8F?gi|h zxzpZ88^c;7u9Arz5{z0SUc_ICieBHdZ1Lv;*uF=iqWDGDJ3&#yvD;eKzM9}zyRBm+ zoNYu5J0K(}mrg8s_C=Q4CH5;qS}Tndzw>gL8GHi2+4nN*)N2D}9c=BkNKyp^Cbr;1 zE^SVInO(u3S4XHqT`cYqMeTJQ^#u|mt5$1?if>K~L7cW2%l{=&F?uoLFObU?N^gpa*2OG0$y$P80Vb~9!3u@v6_z9Q;1y;heJtT) z2^kfmUcrj#gXn*`aGXx!Z7m#oEP)$^Zm(a$jv)y1mat&*l6q7Kxv|Ea-Y7m^!mdkp zt_4NfXROGBD`&0#9($D)rLAiP$RcCHJNU*FBsRRt3X5MP451~o&!lslD5t|E#1Pd1 zUUQ=kGM2JgM1iGC*;yRRzs|3*yUKTw5ywoo_d5j;fYk5Qkn=_$q-yJcUdhF>*Kke7 z+v3~T*c9F#756M-7qG9zre)CA?NPy(v!3iL(R(=vjO57W>}CFalor6<5-UlKr7#X{ zW!G8RpNC3DgpIdw9p$dU8&Rs!Tiv0dgkJ6k1l z@*J(^${dTX0kP(F)*Zb6@pYCJUb`9qt&^B!e6g1KnnX~0O{xl6W1W61!vK?z`v~!h z&R46SEuc6;#}cEc)^N*MIGxe02E<4mnpE;ZIs3=**`s>OV$+#!YLGopp zLB<{_7>U{^P2#RquzZW7V(Th+=8L0?_N{`QNcb9^YL7)l{u*{b0d*j?;)6#Qb8M5ydj~<^FQcOR9d!ix&UbL44N<^F z@8AIC-l+KT9X5pj0OZ3xS6`aLF`pQ?%c>29cre23eJ=(vwv z4d8RySfr;tdY}aY;}`1iMw3;^ZKSK8=#*P=z~hZJ7A*PQq6WhhNO&rM2h>g802ZK4 z#Rg^s7fIZt)L1egnJXtzY=itB6;n2_s~~W{Z(u`m<@{tje`G8dqvQ=}fbL!OTR-ncEA&VEb$cR`M5ZDkhMZXVO zai$GsjuXsHV#U93R&vO(IA88S@W+oJvR@!{ya_V!YgC-_5xeSu@~s`phl|!t7KdY*FOI9< zMB2yf$bQz3&~f8Qku8{ssrQK4vF&Iw0gP+CFARex01GWIr5& z3hC1v-eK=g*zl@D^(c?jSv`K|=64h%JSr)P@Mud)QU*4{`iWCPnM;6Y`Il;>C{ z^)YS>&atRi4o&!Q;}-9NBxoPOa&KYN_~b@$>gTLS+FHtmRmDQeukCDn;5D9~&$Xwh zBWdaARv)>HC7E$+&5dH&r|{h#6xrhuy1{Y`zGVp)5{+)+g3nm`!Re8aUF;&t!fl5W zxs7Opr4L@Z+0`oM0mN`S3pMbI-*|`Aqdh>iLcpC+0H>tbQVYV3PQB9YC-R4rXfa?d z1vd~Svc>Z|S=TgdH8W#}9HAc$iD++UcO)}y+X){#Wx zr+|=YY-hz8Go?ARf;R0`NI{#swzGbn7b#0e&bpjRXE%!F+u3;;PgzZ9QEtSVlz+=c za8$YXTM%GQqiDgm8>M39w}?@_+Snn`Bk(g7>D~=wjzr-zEH`x-!3+dsH0HTR5&e$! z$=$JsQ0)ow(PsHCl-NR9)@J!dd_f}xLVCu3AybU`p6Q*IDEu6egjc?2N3$2j^@~{r zVIr6IuQeWQXkw2Vx9AEnPwoja~lLccHr|o1KN6hG%o$Px5+FuFLml}os11q*t z3me5LKd@dyXHc0@tUXD1R^iF9o&%yB~AT)!fWO3ra?kd>V5SSxd! z^mt9?I9n|^AmWqcJ^K?I%Rhj{`&s!tGk#|I71lWmcp*LE-578|*2+yF`J+rot)tX& z2u``^*worJ;)kE%-$VCv_OP;JtOId6n(FY1j9pUSdm0=6BAZ}ug;HF*V+A0G1$bl+ zJDI=LIQ!i_jNx0f{et62h=%U`h250Ai9kt%Xh*ZdzrwnrT3r&)qH1e?h35mqurq~U z%9qrO5vj;uTrX-<`9RU-57s$BQS4X*ceApMnZE%bxbhBBMIHpBNcqAhvEw(^tLTva z;#XvGT!9&haL6lq=8E(7vTjF8hnar$*rUr3j;qx52w9*?7rZ#K;jS{5Nf}i#1F7+i z;)Or)R>qrqS?7Y8Dx`zq(e-=f80ES@ftt9!V|?7*ATo0VE3o#{G`k z`2pki|EK{_<2-b1CDV}14H#RjB=wXNFy2(j!}J?ME37n8EhS*gvy$mZCI^gJR??3oe)?dXmCQvl3B1^=dZK~jmmt2klEhB@ zh{Ok0G80L>N8D;9iH7)Plb80k4w6Da6vvx-k2`APZM`X0lF)(#-Df4KGA80ZzqN|o zeQ=DPQsRj1GPQdQ9~ebv@577_DZG6jmaH3_gxH5Yb}W}Z+Q&}ykYWut2E-b zc&81&XGJ)}^~6t^D6F-230svZN2Bn2iE_1Qv07sH&1WelG+~adV#~}TP9V%RnZ^AM90pupCt>}l#fOK%ts`j=7 zLl+UD*7gpy01Xt8-4mznGbB3PH^~8u@q^_FK!@01kBCyZo}uvpyeiDUrX_#x;<>UX zAdeUTfU2FF*s59v2evl~jqz$XW+`zd<3}E~m!>I5)f`1`yQS`?wO~AEU~D^}o>;+n zdg4Nw97EigEk0wsAiPS>oPXh80>X4IZ5<&(N*$F*G#9f?c=BX(;EdUA_+oU)hX)Kh}@uo&G zkMsP3r)jjtDw)?tD9X1CB@MLojbc0M@NXJLf}0ngAcsVk27vSOnOE~ec?qZ_&!7WK z3`4pR7&+Z+v~G>K+0DE6lb8cq_+%P4V&M!I_{Rnmql7%^sVE@car1$tigvJf)Q0Zg zlNq@DfSm&BVx&58aZjV@?ZIz-O(#176GsPFNuVKpj#olaDjGce_!Qg0zykKsCh?Jn zUwxomI@QYy`GklV?d4~>spT79P`zWzu0CE&bq4!*KL-Q~|G=_Ed_1%3bdt@uWmCVD zJv}1k`FMZwSR(D%LqYm4AMcuD$-V9Zi&d~m4$we(MFOtL{iRV{lfaMR>zl-!1YY1@ zOn!#87^kWecs75fNqn2YgJ&NqF!wPr-wMoq<#^sg&+sPvO_^=U@)yo14V*sl1>5ck`Y= zSR$BcF?Ae%OzVlPk;Wd0eu`~fK_=31Ou$CneS`-Y%w+t=1|=M36?v-GG-s`r4z*~O zc_NM1@`X=|$r>*dy)>TTe}u;A3e<_o%W&xX^EBRzw?0GVM;@%GT@~?1niiediGS@W zSoI_jfmy`4d;1Y{O=JwAhqL#mX7cWQ?_=V&Ox^>H#FLr)G~PT$?8)SB`{ypBTH~9< z$=N(l4C~6ZML&1tLs*U~u(uK1IHl~YdSAGmz++->CfsuZqz;BohE>OnZnDhNp{&(q z74DUV2^|U}v~xl&r;a74sT~WsRk%(T=E}l!^huKuhHYauwnr?DP{DuIuIF@YVDk*jr!bnU(GzB78 zHK}9mSW?wiNiw6dFFncl>o50>+N35i5{(JJI-Q>rALr*fAJ4x4Q76TbBmOGkCyAr`^Tb6r6>+w|Y-Sw1>egcJ*}rPqepMgLR$CalNAFU} zTkwXu(SjSVh&AH5?mVw5R-A-66USAIwLW@bNpdcjM`u{~x^b2ezo-E})pHXD(!%J- z5T=HV1XU|v>~3YDMMFxtk84Xw-HaS-_^^y;_ux}mfvs9{?8X6=63YLJO0V?dxg307 z^kE-9&l_XB7~h}gkW9_)&wn5>6_uDZ@x8c`_YAj7&e&R>?jX;>Q8^U5oPC-Yj$NnxfI9IUyACsY?=N;efKZ!6$QDHBI7He2Ug_Uu zm5Wmb@HsKFvgnTid=;7=Jy`b*uwUV9mL1QIuW_Y@CCMw z!A}(&+k2pPeu(BfO59Yz_xSf#ob!^jGcETJC*9h{mWH29QTR>~nyjuO~ zsRqBGUmx!=-xQfI@qFwGruZ41-VA=kDr z^E>3)7N*sid!XUyt9OoZ-sW>+EXQVQTwXBqEjpI3v+V$G*s0{3a8ZY`2|v6f?ZEWo zcwW31r*R`56h|=Gk{u8mP)yeL$K&`(ApYz@!}x(}E>1oHb1){RTTb9lv8y_$yWZ^p z^ip6V+vGT>TIP`6Wmh=|8^XbLby3}k{NcZ|Ewcxn%-vVD%g$_iISuN;K`RwMpq?Jj zv0=q24OzymMqkI}W#S0liIsO$m;-GDZ7uJz&=YT+&hH@Gb=(>JNcz6(3_d6rnM9Ii z(*=||1+D}Utl26Mo6g|Z@u|;BkBZ!;d(Py`7;l**jyW4QNY0rgmYvOS=Fd!8bmTc; ze)-Zz2%tTJBtY8IA%{@fA#)%-1J38cfi09WvW;e$Yfr0f4^wV0BjU`3$Zo)kNDrwl z#JuyNs}q~#cX*=WwlQBikom?g={wrs?Af%Hz{cioTQBB!$hCE-r9-Z*Z_OQYZQYFI zcgVI~g?iU=o}pW?ckU&6%`FznIsv zzBYmOOn2a}lV|P5vM~+wueT;CqWk9QNlkjHCYr?iBYERBf(U|$gN;jzv$-*!Qbv)n z(V5$kzDj)eN%jPdZ5=Ao>rT-}2_J~&ic5I6bgMgDd*U{xS|yA2UV`HlBy0(n@qzSR za~U6$GgB7ZLWkECjfGZ@n06WO(R|L8!YD#Ojc7jM}PT=JsN$2nh4Y}-)7Yw6mmr?u-{$-Q6dKAAjtK}&) zFyKq;aOLrM@gCUM>M0QLSXG3k0flF!1X()GM|@?OOYTJ5h9Jx1dIj#i9v0ll(>Xd=dm}%sDu~d))9$37$FgPnY<)If)sTy@Cjxd>H3iz{e5 zo)xqny(mhldIf#l_TE;}TXlW){nt6OljF44_nqHw{r3K^wf1}Owb$NrW(M;NKc8#= zw3eaeQUm$T-Di=@Qd5RmoY%@Cn##?NcheKGHCg!aUn24Hy{e~)K=goE=%%zFU*~>P z#}c5uBX-$Mt!Z|JXjDu+X|u=sbTNHkiLK;umOl*0Ym1Gcy~@WGX%pyjz@2wlXQs#7 zWFnRD#fZvG%w+RY=EErBzmP5^2b)~P@#jB;`_;zB&JNJm^fdxxXSk^ zYrm0z-Z>z4Ovb&#j7^-TFSoqoile+%oQT?woRmcZH)oOdr(i1yPkA*;1iHu2IlDxy;r;^%2_$1Ych z$m#l`dU(2?XvcIKKwggsc^O6BtnjvdnV!-*e)cOAo21zk`wg~dHopN;xR~|J@_&5| z{>C1c$Tu~ce4|`^_6qf)JLRIu3|s^LriE>UX9iaDLR@6dz+_l}1OBTt)Nc{5VlmKz z_hTl#N*O%B8(u|Qu}dIK6iqzTR)R+ONa(IsM3Q|Kn`HEtn2w~rR0(3chr(zF98wQe z(m{`SiBxrG|Mac zKjq@)&D>^~Pp!?YUEAhcGs(_v?mP>FfHosc70YI!LT`D*`?JuQ^E~3rEL=}6@`#w( zFtTXlxY_6nv>9QnsG6npMfWMqWaU9;6gAqiSG*=J% z&80}|_iK1EMcZFr>+7J2b74H8wQVjXaCl)Zs)CS8DUrjJQd9-uOFq1^lpbdMLn*F) z5yqDheg@hjo-c!Qk1c9l8AW!HyBGh~HUCrXjm>BFl$Y;1{8ov!kD;HjwN?3qC#v5& z`>!>JUi-JAZ*rD-v@zP31AZRero05@uc2Ir|F6ut%OeiYLmlB}T$@K7YBjMc{-BvP zpW?g93n!bh#@@!&NpT=2SjE{GO!i9j@#7k4g`_|b??2j}Z1d->%=`9y_#bq@BQ7kU zaU2eOla_G!qaJ!^y+!^+*jnBcyIrIN9()FIQ(-oJp>;^wL|g8ci@j5-Xq$qqO`PgyP#Neu)uw({mwlc)xOUUzf_|u ziJ7ZtJ{{aFVk-yzpd^l^%P>j&ae1rA2vdPVqZ zYTw{nudV}c1TM5!%c$9ots2w9E(-kIM?>o3_Pxr|C&V8W-m#T)Z!dmZO(Eev&3lUY z&o-@yfK6PY8E-K-3&$i>ZR@g)wQo6AIs-D%MHN3 zRa2Ckz@H_p!hgbRN`IQPk=#J=J!jrbE$qrPT}vL{=;E8QJi6=F;+BS;ka6qiMY^h; z3H4ie-trRH(={sH;0@nEYsqp{?A}NnV$ZEd6SU7vwVBWFfxu%zT>osUQ6+VYU3-5W zyaQ=tzjA&hc>}I#8yn6X12@r@S`@sQ#?vj2cgALFVTqhp$^BM)2CZW+^Krz+_bFZc zvV~UMN68DNx|YmKT2bSFQ;qQsAfu#b+}MnSX`*X`TrSNeUo7`L4=1J-NlKEO@Sc6yS10yYjoY-r%} zM%dvTfZ@v^dk2kT%m4Qs`abjH4tUbQ{dd9(MmTvVr8JR7Rkh;}e{d0$Y^$R+f7?## z8M>Y4I%Yp^2~chPPMAknchSWAcEO)?qu9TTT=z}%$9`)p#(zY+!)lKvTD~@YY*y^0 zr~o;ZV(f0(`~OlLSw+7Z6mk7M4IkfW&E*{H%N(@@zD|s-qJiRHd#LANsDc5k?GY!VjPbg=YsZ04RsP!sZ9fyM*@hV8f zr~K2v*FKao9Q3rFfpImn_}?w~+-0%ir4SjLOp`b<}ez*dSL1Df)<8V+D5I>9~KusCoVH_#u9i!GEQ5r*MMT_&t=$2^z zHMJC{j?((+lCE0=ac_{kh9Elj?d1|8*a;YI7hli*_1n`^uvn_^Ye1E-42-p(nQy_YSoi@ zw00E~xLc>^X1hj;<)712X%9gm2Z~)m++tbp|3REbM&jQQ4-@k~r@mtGNs6j>(wFW* zapWZ32>HU_syqXgP*qXV#qpCc`PHYWQHYw zjz^r6@xw_HK}ihoFm5jFr>R-j?*gpa2=XY$f+XhBxKR>w)~q8jXZMguIz!Fs^{A(3 z(ONtPSR&y7Xgmv&_&Fa=M#v9WA_dd}lnQDIg2T)gd`dc~HK+}!Ehq!@0H__PJqWM8 z@|&(oN6=qDoj{#Im{PIYcw_=}13d(?gR(%~K|MtE8G1%ken}l;mj_z4$^0<*oblMa zkuFRDZ7`Mxin?bhy+rD8V|emQ{J04ZG2thHc_B&tr%ZAlaPC4W=Z-S!KdCoAla08$z@{i`A@@gujX~n+isxMKKhSwls zqaf?LU(~CnsKDs@R?W(#)EDX16y8FLk3y9vgv6gA&K6MOV`6MIC5KK!a_)gQeA&EJ zU#zaCjP_D(D`Y$$#}{7iVd6yHd`j(g}}`J@G?%n2+v-|O#;HuD>O6lkHxf=#VCucR&DKxrB`TZ)4M>t z@_71k8zg>2gj}VT^(5>j>{qE&oVC%xK8H)FhHxtctK<-Ww0 zeHcjJmtwj#zIR{BhKL^?fk-juTgr{u3YEtJ?}Ep<<$(BMm0S_>9qmY(A9n9X=zvHT zI0EsJAiY599xlfJgWe1IN4Qntm0X6l1d0v6(%`;LbWQ{^W<$cuf*&r2H@7?nco_3$ zIGO<-#%$xqFu=n&U)%g18>=yNmJ{&;5GUpRwGcGU7ia7O6&bJ_@nQoWFVeoJ9%9Z9 z)PzPwh}Az(tYw0}m8`=ak$N>k?{qdl-1dneez-c5K$Af)g04o0e*dKOc&R@fy!skn zPd^j!AYHHgpERgM>Ma6~_j@B|Q!4ShCOP9?2KnC*_cP#Ki1X@@=^4iv@GV_lQloGi z40cLn0zb5@sR{E;mhupjoUu_p1(>%vsb2zY>{Fvz!>3p=!jm-_i1|Okq+)V^`V(c=Oxiq?{;(Q- zeX{469+u5lGje!4Wb(Uj!1@r1nLpErj5lI+Ys}V=JpqZ?)O9sr7ve26EaI+AXF02}k?#TKLI_vv-o8~BLLs=0*cn~8-tD2K{y;`R;d z5K;y{?-r#XKXC-xB8x`fq|8t$l9mYk?KkQ9lK10u!(WafxTz91^>vLAw=>9jHnXLb z@)+O*1C9fZ0)7d^53*OLfTn_YS^G{AV#(*!TKs+!&i>h7@Y2Cc@#6bmsKdbNP?4M1 z%ZMBCE5OVPPOvI75WWiXfL;T=4tfJ5)3QOI1=2UbB!MJ-0Od(=HsZYhFwFtY1(k}J zU+M9#!HN2|`d3V8-nNW5&VW~&RQEHeNbQ^AyND!{uRMN1yRp|@KX~^p#3{LdYe@G2(nqgJ2hbyxXvIDsQ zVIaa~86wtSO{fRR3+QNu=#d@52?q?CMGUwh8Y8Ze)<30A_zn z>K_E=^(66OU~TgH@@Lb{70Z$e^)Or6iIX@1*jNDDW}Z?~-WfPa!`}2jwSmRb&YKye zzF>LaL96l@_*N)~Ae;~4apC#30Q4s4Es*3bL|ohoR&6CyJL*H_#tGbE8=vjU%XYds z1^Aqk(=ow4sjybE9(-P}#m+ppRR0(}uBF3SJoXIYT>jr=eiv(TtN&4FNk>v(e28J{DN#ZYZn&eIo-BlZt$&a5~KpSj**-c%5Or*10`iS z1qJzzY^NrxG|7rPv{RNrmn+LHe;H)N(rg?tgI0jpY`m>6*x*j$y#{Khn3Z7h z!}WE7-eG`;akQ{l)dfi>I_c(Nn2)^{A(zVZF6ccFu1s&ix_xI=8)vQuHrC9DWz8x( zTa^vaV;j8@#5H4F*xB2uq53^3$QJvpvdNMxe8pi7KNw)KM!@&$E*)RE-N?N=`3*DgtxK!Xvrcl`OrEZ z#A73|iZ#*9fa?IWHF+Pz*>dGR0DTBDR@e)?6=bZ~Hj~cwS}aZnt07``m>LmdY}ziL zh8%;BynDjbmehVX_>xzJ_#V(+kdeR7hY@JajTCVaYJUpqE?g06CbjD>Hb`ySHCc^<_)FjyFtIJYJPK3*6T)HmTiz&tl(fev6}1;zn4H^|2W>lOB1h*tag zaKV#>jkl`5E=N2O5f>|-6ZeLa(#N_B&eZO*;kBDP%}zo`fA9HMP4@HWUQx#hWt~3jpeg@ zZ^Tu=4;%DP1GDcV%VXyla*>>9U41Cl&7lUfdhcK{lFiks;Pm6z~R82A>w+f+ADMw zFt5OE2wNho9wd6VM1FUMh^Yue+B~6O()LCeDt>OIMtD!Pgo{M^Pl#_?sp*4OJZaTz z!3FducdHS{8}N0=+Zgb1^bHp*_3zeTF(OUv5Slbp-?Z8wtABrbZ3}W+&K* zkcZHPkQ)g3^)$6pyiB(We6~TKB1B&)ClI1PS+8F@%(?QERrC4S;o<#HdCEICU0vyy zw&{7Rb`Q*pD+MGm-+gmMBp!r#rm!?uBO-G0M#4u+cNL)vUa)H8atfnw(apokc51(_ q##!(sQX27D-~rjLBFCdncTe8BP4cfqT6;D3o;i2UyR5xBQ2k#NI#lHV From a9f79460dfe78c3d049de9c49f7e4faec60a5a66 Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 30 Dec 2021 10:23:17 +0800 Subject: [PATCH 4/7] make nonsense judgement to global level --- referendum/src/lib.rs | 9 +++++ referendum/src/owner.rs | 41 ++++++++++++++++++++- referendum/src/proposals.rs | 71 +++++++++++++++++++----------------- referendum/src/utils.rs | 13 +++++++ res/referendum.wasm | Bin 211182 -> 223583 bytes 5 files changed, 99 insertions(+), 35 deletions(-) diff --git a/referendum/src/lib.rs b/referendum/src/lib.rs index 467ea09..d482e69 100644 --- a/referendum/src/lib.rs +++ b/referendum/src/lib.rs @@ -6,6 +6,7 @@ use near_sdk::collections::{LookupMap, UnorderedMap}; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::json_types::{ValidAccountId}; use near_sdk::{env, near_bindgen, AccountId, Balance, PanicOnDefault, PromiseOrValue, Timestamp, BorshStorageKey}; +use proposals::VotePolicy; use crate::session::SessionInfo; use crate::account::VAccount; @@ -50,11 +51,17 @@ pub struct ContractData { accounts: LookupMap, + // the global vote policy + vote_policy: Vec, + /// Last available id for the proposals. pub last_proposal_id: u64, /// Proposal map from ID to proposal information. pub proposals: LookupMap, + + /// limits pub lock_amount_per_proposal: Balance, + pub nonsense_threshold: Rational, } #[derive(BorshSerialize, BorshDeserialize)] @@ -84,9 +91,11 @@ impl Contract { cur_session: 0, cur_total_ballot: 0, accounts: LookupMap::new(StorageKeys::Accounts), + vote_policy: vec![DEFAULT_VP_RELATIVE, DEFAULT_VP_ABSOLUTE], last_proposal_id: 0, proposals: LookupMap::new(StorageKeys::Proposals), lock_amount_per_proposal: DEFAULT_LOCK_NEAR_AMOUNT_FOR_PROPOSAL, + nonsense_threshold: DEFAULT_NONSENSE_THRESHOLD, }), } } diff --git a/referendum/src/owner.rs b/referendum/src/owner.rs index 898833c..949282a 100644 --- a/referendum/src/owner.rs +++ b/referendum/src/owner.rs @@ -1,7 +1,9 @@ //! Implement all the relevant logic for owner of this contract. +use near_sdk::json_types::U128; use crate::*; + #[near_bindgen] impl Contract { /// Change owner. Only can be called by owner. @@ -15,13 +17,48 @@ impl Contract { self.data().owner_id.clone() } - pub fn modify_genesis_timestamp(&mut self, genesis_timestamp: u64) { + pub fn modify_genesis_timestamp(&mut self, genesis_timestamp_in_sec: u32) { self.assert_owner(); + let genesis_ts = sec_to_nano(genesis_timestamp_in_sec); assert!( env::block_timestamp() <= self.data().genesis_timestamp, "ERR_HAS_LAUNCHED" ); - self.data_mut().genesis_timestamp = genesis_timestamp; + assert!(genesis_ts > env::block_timestamp(), "ERR_ILLEGAL_GENESIS_TIME"); + self.data_mut().genesis_timestamp = genesis_ts; + } + + pub fn modify_endorsement_amount(&mut self, amount: U128) { + self.assert_owner(); + let amount: Balance = amount.into(); + assert!(amount > 0, "ERR_MUST_HAVE_ENDORSEMENT"); + self.data_mut().lock_amount_per_proposal = amount; + } + + pub fn modify_nonsense_threshold(&mut self, threshold: Rational) { + self.assert_owner(); + assert!(threshold.is_valid(), "ERR_ILLEGAL_THRESHOLD"); + self.data_mut().nonsense_threshold = threshold; + } + + pub fn modify_vote_policy(&mut self, vote_policy: VotePolicy) { + self.assert_owner(); + match &vote_policy { + VotePolicy::Relative(l, j) => { + assert!(l.is_valid(), "ERR_ILLEGAL_THRESHOLD"); + assert!(j.is_valid(), "ERR_ILLEGAL_THRESHOLD"); + if let Some(elem) = self.data_mut().vote_policy.get_mut(0) { + *elem = vote_policy; + } + }, + VotePolicy::Absolute(p, f) => { + assert!(p.is_valid(), "ERR_ILLEGAL_THRESHOLD"); + assert!(f.is_valid(), "ERR_ILLEGAL_THRESHOLD"); + if let Some(elem) = self.data_mut().vote_policy.get_mut(1) { + *elem = vote_policy; + } + }, + } } pub(crate) fn assert_owner(&self) { diff --git a/referendum/src/proposals.rs b/referendum/src/proposals.rs index da5a56e..81e7827 100644 --- a/referendum/src/proposals.rs +++ b/referendum/src/proposals.rs @@ -10,6 +10,13 @@ use crate::*; use crate::utils::Rational; +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(crate = "near_sdk::serde")] +pub enum PolicyType { + Relative = 0x0, + Absolute = 0x1, +} + #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)] #[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] #[serde(crate = "near_sdk::serde")] @@ -20,37 +27,36 @@ pub enum VotePolicy { impl VotePolicy { - /// the priority sequense is Remove, Fail, Pass - pub fn judge(&self, aye: &Balance, nay: &Balance, remove: &Balance, total: &Balance) -> ProposalStatus { - match self { - VotePolicy::Relative(limit, threshold) => { - let voted = aye + nay + remove; - if limit.pass(&voted, total) { - if threshold.pass(remove, &voted) { - ProposalStatus::Removed - } else if threshold.pass(nay, &voted) { + /// to see if the proposal goes to a final state + pub fn judge(&self, aye: &Balance, nay: &Balance, remove: &Balance, total: &Balance, nonsense_threshold: &Rational) -> ProposalStatus { + if nonsense_threshold.pass(remove, total) { + ProposalStatus::Removed + } else { + match self { + VotePolicy::Relative(limit, threshold) => { + let voted = aye + nay + remove; + if limit.pass(&voted, total) { + if threshold.pass(nay, &voted) { + ProposalStatus::Rejected + } else if threshold.pass(aye, &voted) { + ProposalStatus::Approved + } else { + ProposalStatus::InProgress + } + } else { + ProposalStatus::InProgress + } + }, + VotePolicy::Absolute(pass_threshold, fail_threshold) => { + if fail_threshold.pass(nay, total) { ProposalStatus::Rejected - } else if threshold.pass(aye, &voted) { + } else if pass_threshold.pass(aye, total) { ProposalStatus::Approved } else { ProposalStatus::InProgress } - } else { - ProposalStatus::InProgress - } - }, - VotePolicy::Absolute(pass_threshold, fail_threshold) => { - if fail_threshold.pass(remove, total) { - ProposalStatus::Removed - } else if fail_threshold.pass(nay, total) { - ProposalStatus::Rejected - } else if pass_threshold.pass(aye, total) { - ProposalStatus::Approved - } else { - ProposalStatus::InProgress - } - }, - // _ => ProposalStatus::InProgress, + }, + } } } @@ -192,6 +198,7 @@ impl Proposal { vote: &Vote, amount: &Balance, total: &Balance, + nonsense_threshold: &Rational, ) { self.vote_counts[vote.clone() as usize] += amount; self.vote_counts[3] = total.clone(); @@ -200,7 +207,8 @@ impl Proposal { &self.vote_counts[0], &self.vote_counts[1], &self.vote_counts[2], - &self.vote_counts[3] + &self.vote_counts[3], + nonsense_threshold, ); } @@ -235,15 +243,12 @@ impl Proposal { impl Contract { /// Add proposal to this DAO. #[payable] - pub fn add_proposal(&mut self, description: String, kind: ProposalKind, vote_policy: VotePolicy, session_id: u32, start_offset_sec: u32, lasts_sec: u32) -> u64 { + pub fn add_proposal(&mut self, description: String, kind: ProposalKind, policy_type: PolicyType, session_id: u32, start_offset_sec: u32, lasts_sec: u32) -> u64 { // check point self.fresh_sessions(); let proposer = env::predecessor_account_id(); - // check vote_policy - assert!(vote_policy.is_valid(), "ERR_ILLEGAL_VOTE_POLICY"); - // check and lock deposit let deposit_amount = env::attached_deposit(); assert!(deposit_amount <= self.data().lock_amount_per_proposal, "ERR_NOT_ENOUGH_LOCK_NEAR"); @@ -257,7 +262,7 @@ impl Contract { proposer, lock_amount: self.data().lock_amount_per_proposal, description, - vote_policy, + vote_policy: self.data().vote_policy.get(policy_type as usize).unwrap().clone(), kind, status: ProposalStatus::WarmUp, vote_counts: [0; 4], @@ -332,7 +337,7 @@ impl Contract { let ballot_amount = self.internal_vote(&account_id, id, &vote); // update and judge proposal result - proposal.update_votes(&vote, &ballot_amount, &self.data().cur_total_ballot); + proposal.update_votes(&vote, &ballot_amount, &self.data().cur_total_ballot, &self.data().nonsense_threshold); if proposal.status == ProposalStatus::Approved || proposal.status == ProposalStatus::Rejected { // return lock near to proposer diff --git a/referendum/src/utils.rs b/referendum/src/utils.rs index 2f6c5a1..c0d76f7 100644 --- a/referendum/src/utils.rs +++ b/referendum/src/utils.rs @@ -4,6 +4,7 @@ use near_sdk::json_types::U128; use near_sdk::{ext_contract, Gas, Balance, Timestamp}; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::serde::{Deserialize, Serialize}; +use crate::proposals::{VotePolicy, Vote}; /// Attach no deposit. pub const NO_DEPOSIT: u128 = 0; @@ -24,6 +25,18 @@ pub const DEFAULT_GENESIS_OFFSET: u64 = 3600 * 24 * 30 * 1_000_000_000; /// default locking amount is 10 near for each proposal pub const DEFAULT_LOCK_NEAR_AMOUNT_FOR_PROPOSAL: Balance = 10_000_000_000_000_000_000_000_000; +pub const DEFAULT_NONSENSE_THRESHOLD: Rational = Rational {numerator: 1, denominator: 2}; + +pub const DEFAULT_VP_RELATIVE: VotePolicy = VotePolicy::Relative( + Rational {numerator: 33, denominator: 100}, + Rational {numerator: 1, denominator: 2} +); + +pub const DEFAULT_VP_ABSOLUTE: VotePolicy = VotePolicy::Absolute( + Rational {numerator: 45, denominator: 100}, + Rational {numerator: 33, denominator: 100} +); + #[derive(Serialize, Deserialize, Clone)] #[serde(crate = "near_sdk::serde")] diff --git a/res/referendum.wasm b/res/referendum.wasm index 6a618a60f8bd8337d16a9248928696db753c2463..44584b70fabd31a0ede89615664ba4609440f68b 100755 GIT binary patch delta 75827 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 delta 67041 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 Pxc-cg$$ndvO~wBMQ6_%I literal 0 HcmV?d00001 From d8cdd95e8a4ffe118dcfaaf8d15ed70101e51edc Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 3 Jan 2022 12:29:28 +0800 Subject: [PATCH 7/7] release referendum 1.0.0 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 08cba9a..9a872db 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,6 @@ Basic Ref token ### XRef Token Ref Share Token + +### referendum +A referendum DAO for XREF token

VkFNs4Vi+#GlW>I=dulVku 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 twASzq(5>)IzK%4iB@2xn*;Qk5c=n{|BeDdWrx5 From bfc510814689df35cd7107ab4b1339c2a9d0f1aa Mon Sep 17 00:00:00 2001 From: MagicGordon Date: Mon, 3 Jan 2022 12:19:39 +0800 Subject: [PATCH 5/7] add lock calc and storage (#2) Implement referendum Co-authored-by: Marco --- .gitignore | 3 +- referendum/README.md | 238 +++++++++++++++ referendum/build.sh | 2 +- referendum/src/account.rs | 296 +++++++++++++------ referendum/src/lib.rs | 43 ++- referendum/src/owner.rs | 5 +- referendum/src/proposals.rs | 307 +++++++++++++------ referendum/src/session.rs | 80 ++++- referendum/src/storage_impl.rs | 91 ++++++ referendum/src/utils.rs | 45 ++- referendum/src/views.rs | 208 +++++++++++++ referendum/tests/common/init.rs | 74 +++++ referendum/tests/common/mod.rs | 2 + referendum/tests/common/utils.rs | 102 +++++++ referendum/tests/owner.rs | 44 +++ referendum/tests/test_lock.rs | 285 ++++++++++++++++++ referendum/tests/test_proposal.rs | 361 ++++++++++++++++++++++ referendum/tests/test_storage.rs | 150 ++++++++++ referendum/tests/test_unlock.rs | 114 +++++++ referendum/tests/test_vote.rs | 476 ++++++++++++++++++++++++++++++ 20 files changed, 2709 insertions(+), 217 deletions(-) create mode 100644 referendum/README.md create mode 100644 referendum/src/storage_impl.rs create mode 100644 referendum/src/views.rs create mode 100644 referendum/tests/common/init.rs create mode 100644 referendum/tests/common/mod.rs create mode 100644 referendum/tests/common/utils.rs create mode 100644 referendum/tests/owner.rs create mode 100644 referendum/tests/test_lock.rs create mode 100644 referendum/tests/test_proposal.rs create mode 100644 referendum/tests/test_storage.rs create mode 100644 referendum/tests/test_unlock.rs create mode 100644 referendum/tests/test_vote.rs diff --git a/.gitignore b/.gitignore index 6cbfeaf..1825630 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ neardev .DS_Store res/ref_token_local.wasm -res/xref_token_local.wasm \ No newline at end of file +res/xref_token_local.wasm +res/referendum_local.wasm \ No newline at end of file diff --git a/referendum/README.md b/referendum/README.md new file mode 100644 index 0000000..a5f5e34 --- /dev/null +++ b/referendum/README.md @@ -0,0 +1,238 @@ +# Referendum + +Detailed discussion about Referendum, see this [post](https://gov.ref.finance/t/product-x-referendum/384). + +## Instructions + +### Initialization +After deploy, we can initiate the contract as following: +```bash +near call $REFERENDUM new '{"owner_id": "'$OWNER'", "token_id": "'$TOKEN'"}' --account_id $REFERENDUM +``` +Then owner can determine a launch date and set it into contract in 30 days after deployment: +```bash +# set 2022-02-01 00:00:00 UTC to be genesis time +near call $REFERENDUM modify_genesis_timestamp '{"genesis_timestamp_in_sec": 1643673600}' --account_id $OWNER +``` + +### Owner Methods +Ownership can be transfered: +```bash +near view $REFERENDUM get_owner +near call $REFERENDUM set_owner '{"owner_id": "'$NEW_OWNER'"}' --account_id $OWNER +``` +Owner can set launch date, see Initialization for details. + +Owner can modify endorsement NEAR amount per proposal: +```bash +# set endorsement NEAR amount to 15 NEAR. +near call $REFERENDUM modify_endorsement_amount '{"amount": "15'$ZERO24'"}' --account_id $OWNER +``` + +Owner can set nonsense threshold: +```bash +# set threshold to 40% +near call $REFERENDUM modify_nonsense_threshold '{"threshold": {"numerator": 40, "denominator": 100}}' --account_id $OWNER +``` + +Owner can set vote policy: +```bash +# set relative policy to 30% voting ballot and 50%+ supported opinion wins +near call $REFERENDUM modify_vote_policy '{"vote_policy": {"Relative": [{"numerator": 30, "denominator": 100}, {"numerator": 1, "denominator": 2}]}}' --account_id $OWNER + +# set absolute policy to pass with 55%+ ballot power and fail with 45%+ ballot power +near call $REFERENDUM modify_vote_policy '{"vote_policy": {"Absolute": [{"numerator": 55, "denominator": 100}, {"numerator": 45, "denominator": 100}]}}' --account_id $OWNER +``` + +### Proposer and Proposals +Anyone can initiate a referendum proposal with fixed amount of NEAR as endorsement: +```bash +# alice.near deposit 15 NEAR as endorsement to create a referendum, +# referendum will start at 7 days (604800) after beginning of session 0, and lasts 14 days (1209600), +# The vote policy is Absolute (the other is Relative), +# Currently there is only one kind of referendum, Vote. +near call $REFERENDUM add_proposal '{"description": "example referendum, see detail at https://xxxxxxx", "kind": "Vote", "policy_type": "Absolute", "session_id": 0, "start_offset_sec": 604800, "lasts_sec": 1209600}' --account_id=alice.near --amount 15 +``` +The deposit NEAR would lock until the referendum goes to a final state, that is one of Approved, Rejected, Nonsense or Expired. + +On approved and Rejected state, the locked NEAR would auto transfer back to proposer; +On nonsense state, the locked NEAR would be slashed; +On expired state, proposer need to explicit call to redeem the locked NEAR: +```bash +# it returns true when succeed +near call $REFERENDUM redeem_near_in_expired_proposal '{"id": 0}' --account_id=alice.near +``` + +The proposer can also remove his proposal before it starts and gets locked NEAR back: +```bash +# it returns true when succeed +near call $REFERENDUM remove_proposal '{"id": 0}' +``` + +### User Register +This contract obeys NEP-145 to manage storage, but choose a fixed storage fee policy in this contract. Each user only needs deposit to lock a fixed 0.01 NEAR as storage cost. + +Detailed interface description could be found at [NEP-145](https://nomicon.io/Standards/StorageManagement.html). + +Here we only list some common-use interfaces: + +* `storage_deposit`, to register a user, +* `storage_unregister`, to unregister caller self and get 0.01 NEAR back, +* `storage_balance_of`, to get given user storage balance. + + +### User Methods +To lock token (XREF) and get ballot power, user need start from token contract: +```bash +# alice lock 100 TOKEN for 9 sessions +near call $TOKEN ft_tranfser_call '{"receiver_id": "'$REFERENDUM'", "amount": "100'$ZERO18'", "msg": "9"}' --account_id=alice.near --amount=$YN +``` +*Note: user can only start a new lock when there is no existing locking at his account.* + +When there is an existing locking, user can append token to it: +```bash +# alice append 100 TOKEN to his existing locking +near call $TOKEN ft_tranfser_call '{"receiver_id": "'$REFERENDUM'", "amount": "100'$ZERO18'", "msg": ""}' --account_id=alice.near --amount=$YN +``` +*Note: user can only append lock when there is a existing locking at his account.* + +To withdraw token when they are unlocked, user call: +```bash +near call $REFERENDUM withdraw --account_id=alice.near --amount=$YN +``` +*Note: If user wanna those token to be part of a new locking, he can directly start `ft_transfer_call` without withdrawing them first. those un-withdraw amount would auto caculate into the total locking amount.* + +User can vote any InProgress referendum: +```bash +# action could be one of VoteApprove, VoteReject, VoteNonsense +near call $REFERENDUM act_proposal '{"id": 0, "action": "VoteApprove"}' --account_id=alice.near +``` +*Note: user can only vote once per proposal and the ballot power would auto renew if user append locking more token and get more ballot.* + +### View Methods +#### **To view contract info:** +```bash +near view $REFERENDUM contract_metadata +``` +The return value structure is: +```rust +pub struct ContractMetadata { + /// the owner account id of contract + pub owner_id: AccountId, + /// accept lock token account id + pub locked_token: AccountId, + /// the launch timestamp in seconds + pub genesis_timestamp_sec: u32, + /// current session id (start from 0) + pub cur_session_id: u32, + /// current total ballot amount (calculate at call time) + pub cur_total_ballot: U128, + /// current locking token amount (include those expired but hasn't unlock by user) + pub cur_lock_amount: U128, + /// the availabe proposal id for new proposal + pub last_proposal_id: u32, + /// lock near amount for endorsement a proposal + pub lock_amount_per_proposal: U128, + /// current account number in contract + pub account_number: u64, + /// a list of [Relative, Absolute] in which each item is formated as + /// [{"numerator": n, "denominator": m}, {"numerator": n, "denominator": m}] + pub vote_policy: Vec, + /// in format as {"numerator": n, "denominator": m} + pub nonsense_threshold: Rational, +} +``` + +#### **To view proposal info:** + +```bash +# returns `ProposalInfo` structure or null +near view $REFERENDUM get_proposal_info '{"proposal_id": 0}' + +# returns array of `ProposalInfo` +near view $REFERENDUM get_proposals_in_session '{"session_id": 0}' + +# returns array of proposal id +near view $REFERENDUM get_proposal_ids_in_session '{"session_id": 0}' +``` +The `ProposalInfo` structure is: +```rust +pub struct ProposalInfo{ + pub id: u32, + pub proposer: AccountId, + /// near amount for endorsement + pub lock_amount: U128, + pub description: String, + /// one of the following: + /// "VotePolicy": {"Relative": [{"numerator": n, "denominator": m}, {"numerator": n, "denominator": m}]} + /// "VotePolicy": {"Absolute": [{"numerator": n, "denominator": m}, {"numerator": n, "denominator": m}]} + pub vote_policy: proposals::VotePolicy, + /// currently would only be "Vote" + pub kind: proposals::ProposalKind, + /// one of the following: + /// "WarmUp", "InProgress", "Approved", "Rejected", "Nonsense", "Expired" + pub status: proposals::ProposalStatus, + /// [Approve_count, Reject_count, Nonsense_count, Total_ballots] + pub vote_counts: [U128; 4], + /// The session this proposal is valid in + pub session_id: u32, + /// the start time = session_begin_time + start_offset + pub start_offset_sec: u32, + /// the proposal max valid period in seconds + pub lasts_sec: u32, +} +``` +#### **To get account info** +For basic account info: +```bash +# return `AccountInfo` or null +near view $REFERENDUM get_account_info '{"account_id": "alice.near"}' +``` +The `AccountInfo` is: +```rust +pub struct AccountInfo { + /// locked token (XREF) amount + pub locking_amount: U128, + /// ballot amount (calculate at call time) + pub ballot_amount: U128, + /// unlock at the begin of this session, meanwhile ballots reset to zero + pub unlocking_session_id: u32, +} +``` +For account votes: +```bash +# return array of `HumanReadableAccountVote` +near view $REFERENDUM get_account_proposals_in_session '{"account_id": "alice.near", "session_id": 0}' +``` +The `HumanReadableAccountVote` is: +```rust +pub struct HumanReadableAccountVote { + pub proposal_id: u32, + pub vote: Vote, + pub amount: U128, +} +``` + +## Development +1. Install `rustup` via [https://rustup.rs/](https://rustup.rs/) +2. Run the following: +```bash +rustup default stable +rustup target add wasm32-unknown-unknown +``` +### Compiling +You can build release version by running script: +``` +./build_release.sh +``` +### Testing +Contract has unit tests as well as simulation tests. All together can be run: +```bash +cargo test -- --nocapture +``` +### Deploying to TestNet +To deploy to TestNet, you can use: +```bash +near dev-deploy ../res/referendum.wasm +``` +This will output on the contract ID it deployed. diff --git a/referendum/build.sh b/referendum/build.sh index 226b0a1..8b170ea 100644 --- a/referendum/build.sh +++ b/referendum/build.sh @@ -3,5 +3,5 @@ set -e rustup target add wasm32-unknown-unknown RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release cd .. -cp target/wasm32-unknown-unknown/release/referendum.wasm ./res/referendum.wasm +cp target/wasm32-unknown-unknown/release/referendum.wasm ./res/referendum_local.wasm cd - \ No newline at end of file diff --git a/referendum/src/account.rs b/referendum/src/account.rs index b6d0866..2a272e0 100644 --- a/referendum/src/account.rs +++ b/referendum/src/account.rs @@ -1,14 +1,14 @@ //! Account is information per user about their locking balances and ballots. -//! +//! -use crate::*; use crate::utils::{ext_self, GAS_FOR_FT_TRANSFER, GAS_FOR_RESOLVE_TRANSFER, NO_DEPOSIT}; -use near_contract_standards::fungible_token::receiver::FungibleTokenReceiver; +use crate::*; use near_contract_standards::fungible_token::core_impl::ext_fungible_token; +use near_contract_standards::fungible_token::receiver::FungibleTokenReceiver; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::collections::LookupMap; -use near_sdk::{Balance, AccountId, assert_one_yocto, PromiseOrValue, log, PromiseResult}; use near_sdk::json_types::U128; +use near_sdk::{assert_one_yocto, log, AccountId, Balance, Promise, PromiseOrValue, PromiseResult}; use crate::proposals::Vote; @@ -45,68 +45,196 @@ pub struct Account { pub locking_amount: Balance, /// The amount of ballots the account holds pub ballot_amount: Balance, - /// unlocking session id + /// unlocking session id, unlocking at the begining of this session pub unlocking_session_id: u32, - /// Record proposal voting info, when ballot_amount changes, should update this one and global proposal vote info - pub proposals: LookupMap, + /// Record proposal voting info + pub proposals: LookupMap, } impl Account { - pub(crate) fn add_locking(&mut self, locking_amount: Balance, ballot_amount: Balance, unlocking_session_id: u32) { + pub(crate) fn add_locking( + &mut self, + locking_amount: Balance, + ballot_amount: Balance, + unlocking_session_id: u32, + ) { self.locking_amount += locking_amount; self.ballot_amount += ballot_amount; self.unlocking_session_id = unlocking_session_id; } - pub(crate) fn unlock(&mut self, cur_session_id: u32) -> Balance { - if cur_session_id >= self.unlocking_session_id { - let amount = self.locking_amount; + pub(crate) fn remove_locking(&mut self) -> Balance { + if self.ballot_amount == 0 { + let amount = self.locking_amount; self.locking_amount = 0; - self.ballot_amount = 0; - self.unlocking_session_id = 0; amount } else { 0 } } -} + /// return account's current valid ballot + pub(crate) fn sync_ballot(&self, cur_session_id: u32) -> Balance { + if cur_session_id >= self.unlocking_session_id { + 0 + } else { + self.ballot_amount + } + } + + /// update account's valid ballot according to current session id + pub(crate) fn touch(&mut self, cur_session_id: u32) { + self.ballot_amount = self.sync_ballot(cur_session_id); + } +} impl Contract { - /// lasts = 0 means append + /// lasts = 0 means APPEND mode, otherwise NEW mode with session numbers to lock, + /// In APPEND mode, user must have valid ballots, + /// In NEW mode, user must have 0 ballots,but can have unlocked tokens fn internal_lock(&mut self, account_id: &AccountId, locking_amount: Balance, lasts: u32) { - // TODO: - // calculate ballots - // locate end_session (array index) and end_session_id - // verify append has valid running locking - // vierify new lock has no running locking - let ballot_amount: Balance = 0; - let end_session: usize = 0; - let end_session_id: u32 = 0; - - // update the account - let mut account = self.data().accounts.get(account_id).map(|va| va.into_current()).expect("ERR_USER_NOT_REGISTER"); - account.add_locking(locking_amount, ballot_amount, end_session_id); - self.data_mut().accounts.insert(account_id, &account.into()); - // update the session - self.data_mut().sessions[end_session].expire_amount += ballot_amount; - // update the ballot + let current_state = self.data(); + let mut account = current_state + .accounts + .get(account_id) + .map(|va| va.into_current()) + .expect("ERR_USER_NOT_REGISTER"); + let current_session_info = current_state.sessions[current_state.cur_session]; + + account.touch(self.get_cur_session_id()); + + let current_session_remaining_days = nano_to_day(SESSION_INTERMAL) + - nano_to_day( + env::block_timestamp() + - current_state.genesis_timestamp + - current_session_info.session_id as u64 * SESSION_INTERMAL, + ); + + let (ballot_amount, unlocking_session_id) = { + if lasts == 0 { + // APPEND mode, verify non-zero ballot + assert!(account.ballot_amount != 0, "ERR_NO_RUNNING_LOCKING"); + ( + calculate_ballots( + current_session_remaining_days, + locking_amount, + account.unlocking_session_id - current_session_info.session_id), + account.unlocking_session_id + ) + } else { + // NEW mode, verify zero ballot + assert_eq!(account.ballot_amount, 0, "ERR_EXIST_RUNNING_LOCKING"); + ( + calculate_ballots( + current_session_remaining_days, + account.locking_amount + locking_amount, + lasts), + current_session_info.session_id + lasts + ) + } + }; + + // locate end_session (array index) + let end_session = (current_state.cur_session + + (unlocking_session_id - 1 - current_session_info.session_id) as usize) + % MAX_SESSIONS; + + // update account + account.add_locking(locking_amount, ballot_amount, unlocking_session_id); self.data_mut().cur_total_ballot += ballot_amount; - // TODO: add log + if lasts == 0 { + // auto update user involved proposal votes + if let Some(proposal_ids) = self + .data() + .proposal_ids_in_sessions + .get(current_session_info.session_id as u64) + { + for proposal_id in proposal_ids { + if let Some(mut account_vote) = account.proposals.get(&proposal_id) { + let append_amount = self.internal_append_vote( + proposal_id, + &account_vote.vote, + &ballot_amount, + ); + account_vote.amount += append_amount; + account.proposals.insert(&proposal_id, &account_vote); + } + } + } + log!( + "User {} appends locking with {} token got {} ballots, total {} ballots", + account_id, + locking_amount, + ballot_amount, + account.ballot_amount, + ); + } else { + log!( + "User {} starts new locking with total {} token got {} ballots, unlocking_session_id : {}", + account_id, + account.locking_amount, + ballot_amount, + unlocking_session_id + ); + } + + self.data_mut().sessions[end_session].expire_amount += ballot_amount; + self.data_mut().accounts.insert(account_id, &account.into()); } - fn internal_unlock(&mut self, account_id: &AccountId) -> Balance { - // TODO: get cur session id - let cur_session_id = 0; - let mut account = self.data().accounts.get(account_id).map(|va| va.into_current()).expect("ERR_USER_NOT_REGISTER"); - let amount = account.unlock(cur_session_id); + fn internal_withdraw(&mut self, account_id: &AccountId) -> Balance { + let current_state = self.data(); + let mut account = current_state + .accounts + .get(account_id) + .map(|va| va.into_current()) + .expect("ERR_USER_NOT_REGISTER"); + account.touch(self.get_cur_session_id()); + let amount = account.remove_locking(); + assert!(amount > 0, "ERR_NOTHING_CAN_BE_WITHDRAW"); self.data_mut().accounts.insert(account_id, &account.into()); amount } - pub(crate) fn internal_vote(&mut self, account_id: &AccountId, proposal_id: u64, vote: &Vote) -> Balance { - let mut account = self.data().accounts.get(account_id).map(|va| va.into_current()).expect("ERR_USER_NOT_REGISTER"); - assert!(!account.proposals.contains_key(&proposal_id), "ERR_ALREADY_VOTED"); + pub(crate) fn internal_register_account(&mut self, account_id: &AccountId) { + self.data_mut().accounts.insert( + account_id, + &Account { + locking_amount: 0, + ballot_amount: 0, + unlocking_session_id: 0, + proposals: LookupMap::new(StorageKeys::AccountProposals { + account_id: account_id.clone(), + }), + } + .into(), + ); + } + + /// user first vote for given proposal + /// return non-zero ballot power + /// panic if following: + /// * user not registered + /// * user has no valid ballots + /// * user already voted + pub(crate) fn internal_account_vote( + &mut self, + account_id: &AccountId, + proposal_id: u32, + vote: &Vote, + ) -> Balance { + let mut account = self + .data() + .accounts + .get(account_id) + .map(|va| va.into_current()) + .expect("ERR_USER_NOT_REGISTER"); + account.touch(self.get_cur_session_id()); + assert!(account.ballot_amount > 0, "ERR_NO_BALLOTS"); + assert!( + !account.proposals.contains_key(&proposal_id), + "ERR_ALREADY_VOTED" + ); let account_vote = AccountVote { vote: vote.clone(), amount: account.ballot_amount, @@ -119,78 +247,75 @@ impl Contract { #[near_bindgen] impl Contract { - - /// unslock token and send assets back to the predecessor account. + /// withdraw unlocked token back to the predecessor account. /// Requirements: /// * The predecessor account should be registered. /// * Requires attached deposit of exactly 1 yoctoNEAR. + /// Return: + /// * Promise or Panic if nothing unlocked #[payable] - pub fn unlock(&mut self) -> PromiseOrValue { - + pub fn withdraw(&mut self) -> Promise { assert_one_yocto(); - // sync point - self.fresh_sessions(); let account_id = env::predecessor_account_id(); + self.fresh_sessions(); + let unlocked = self.internal_withdraw(&account_id); + log!("Withdraw {} token back to {}", unlocked, account_id); - let unlocked = self.internal_unlock(&account_id); - - if unlocked > 0 { - log!("Unlock {} token back to {}", unlocked, account_id); - ext_fungible_token::ft_transfer( - account_id.clone(), - U128(unlocked), - None, - &self.data().locked_token, - 1, - GAS_FOR_FT_TRANSFER, - ) - .then(ext_self::callback_post_unlock( - account_id.clone(), - U128(unlocked), - &env::current_account_id(), - NO_DEPOSIT, - GAS_FOR_RESOLVE_TRANSFER, - )).into() - } else { - PromiseOrValue::Value(0) - } + self.data_mut().cur_lock_amount -= unlocked; + ext_fungible_token::ft_transfer( + account_id.clone(), + U128(unlocked), + None, + &self.data().locked_token, + 1, + GAS_FOR_FT_TRANSFER, + ) + .then(ext_self::callback_post_withdraw( + account_id.clone(), + U128(unlocked), + &env::current_account_id(), + NO_DEPOSIT, + GAS_FOR_RESOLVE_TRANSFER, + )) } #[private] - pub fn callback_post_unlock( - &mut self, - sender_id: AccountId, - amount: U128, - ) { + pub fn callback_post_withdraw(&mut self, sender_id: AccountId, amount: U128) { assert_eq!( env::promise_results_count(), 1, - "Err: expected 1 promise result from unstake" + "ERR: expected 1 promise result from withdraw" ); match env::promise_result(0) { PromiseResult::NotReady => unreachable!(), PromiseResult::Successful(_) => {} PromiseResult::Failed => { - // This reverts the changes from unlock function. - // If account doesn't exit, the unlock token stay in contract. + // This reverts the changes from withdraw function. + // If account doesn't exit, the token stays in contract. if self.data().accounts.contains_key(&sender_id) { - let mut account = self.data().accounts.get(&sender_id).map(|va| va.into_current()).unwrap(); + let mut account = self + .data() + .accounts + .get(&sender_id) + .map(|va| va.into_current()) + .unwrap(); account.locking_amount += amount.0; + self.data_mut().cur_lock_amount += amount.0; self.data_mut().accounts.insert(&sender_id, &account.into()); env::log( format!( - "Account {} unlock failed and reverted.", - sender_id + "Account {} withdraw {} token failed and reverted.", + sender_id, amount.0 ) .as_bytes(), ); } else { env::log( format!( - "Account {} has unregisterd. unlocking token goes to contract.", - sender_id + "Account {} has unregisterd. withdraw {} token goes to contract.", + sender_id, amount.0 ) .as_bytes(), ); @@ -215,21 +340,18 @@ impl FungibleTokenReceiver for Contract { let token_in = env::predecessor_account_id(); let amount: Balance = amount.into(); assert_eq!(token_in, self.data().locked_token, "ERR_ILLEGAL_TOKEN"); - + if msg.is_empty() { // user append locking - log!("append lock {} token", amount); self.internal_lock(sender_id.as_ref(), amount, 0); } else { // new locking let locking_period = msg.parse::().expect("ERR_ILLEGAL_MSG"); assert!(locking_period > 0, "ERR_ILLEGAL_MSG"); assert!((locking_period as usize) <= MAX_SESSIONS, "ERR_ILLEGAL_MSG"); - - log!("New lock {} token with {} sessions", amount, msg); self.internal_lock(sender_id.as_ref(), amount, locking_period); - } + self.data_mut().cur_lock_amount += amount; PromiseOrValue::Value(U128(0)) } -} \ No newline at end of file +} diff --git a/referendum/src/lib.rs b/referendum/src/lib.rs index d482e69..99235dd 100644 --- a/referendum/src/lib.rs +++ b/referendum/src/lib.rs @@ -2,22 +2,24 @@ * REF referendum contract * */ -use near_sdk::collections::{LookupMap, UnorderedMap}; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; -use near_sdk::json_types::{ValidAccountId}; -use near_sdk::{env, near_bindgen, AccountId, Balance, PanicOnDefault, PromiseOrValue, Timestamp, BorshStorageKey}; +use near_sdk::collections::{LookupMap, Vector}; +use near_sdk::json_types::ValidAccountId; +use near_sdk::{env, near_bindgen, AccountId, Balance, BorshStorageKey, PanicOnDefault, Timestamp}; use proposals::VotePolicy; -use crate::session::SessionInfo; use crate::account::VAccount; use crate::proposals::VersionedProposal; +use crate::session::SessionInfo; use crate::utils::*; -mod session; -mod proposals; mod account; -mod utils; mod owner; +mod proposals; +mod session; +mod storage_impl; +mod utils; +mod views; near_sdk::setup_alloc!(); @@ -25,12 +27,12 @@ near_sdk::setup_alloc!(); pub enum StorageKeys { Accounts, Proposals, - AccountProposals, + ProposalIdsInSession, + AccountProposals { account_id: AccountId }, } #[derive(BorshDeserialize, BorshSerialize)] pub struct ContractData { - // owner of this contract owner_id: AccountId, @@ -43,22 +45,28 @@ pub struct ContractData { // maintains a global session circle array sessions: [SessionInfo; MAX_SESSIONS], + // each session contains proposal id array + proposal_ids_in_sessions: Vector>, + // current session idx in sessions array cur_session: usize, // total ballot amount in current session cur_total_ballot: Balance, + // total lock token amount + cur_lock_amount: Balance, accounts: LookupMap, + account_number: u64, // the global vote policy vote_policy: Vec, /// Last available id for the proposals. - pub last_proposal_id: u64, + pub last_proposal_id: u32, /// Proposal map from ID to proposal information. - pub proposals: LookupMap, - + pub proposals: LookupMap, + /// limits pub lock_amount_per_proposal: Balance, pub nonsense_threshold: Rational, @@ -88,9 +96,12 @@ impl Contract { locked_token: token_id.into(), genesis_timestamp: env::block_timestamp() + DEFAULT_GENESIS_OFFSET, sessions: [SessionInfo::default(); MAX_SESSIONS], + proposal_ids_in_sessions: Vector::new(StorageKeys::ProposalIdsInSession), cur_session: 0, cur_total_ballot: 0, + cur_lock_amount: 0, accounts: LookupMap::new(StorageKeys::Accounts), + account_number: 0, vote_policy: vec![DEFAULT_VP_RELATIVE, DEFAULT_VP_ABSOLUTE], last_proposal_id: 0, proposals: LookupMap::new(StorageKeys::Proposals), @@ -113,4 +124,12 @@ impl Contract { VContractData::Current(data) => data, } } + + fn has_launch(&self) -> bool { + return env::block_timestamp() > self.data().genesis_timestamp; + } + + fn get_cur_session_id(&self) -> u32 { + ((env::block_timestamp() - self.data().genesis_timestamp) / SESSION_INTERMAL) as u32 + } } diff --git a/referendum/src/owner.rs b/referendum/src/owner.rs index 949282a..dc40619 100644 --- a/referendum/src/owner.rs +++ b/referendum/src/owner.rs @@ -70,10 +70,7 @@ impl Contract { } pub(crate) fn assert_launch(&self) { - assert!( - env::block_timestamp() > self.data().genesis_timestamp, - "ERR_NOT_LAUNCHED" - ); + assert!(self.has_launch(), "ERR_NOT_LAUNCHED"); } /// Migration function. diff --git a/referendum/src/proposals.rs b/referendum/src/proposals.rs index 81e7827..ea3c346 100644 --- a/referendum/src/proposals.rs +++ b/referendum/src/proposals.rs @@ -1,14 +1,10 @@ -use std::collections::HashMap; - -use near_contract_standards::fungible_token::core_impl::ext_fungible_token; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; -use near_sdk::json_types::{Base64VecU8, U128, U64}; -use near_sdk::{log, AccountId, Balance, Gas, PromiseOrValue, Timestamp, Promise}; use near_sdk::serde::{Deserialize, Serialize}; +use near_sdk::{log, AccountId, Balance, Promise, Timestamp}; +use near_sdk::json_types::U128; -use crate::*; use crate::utils::Rational; - +use crate::*; #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(crate = "near_sdk::serde")] @@ -17,6 +13,17 @@ pub enum PolicyType { Absolute = 0x1, } +#[cfg(not(target_arch = "wasm32"))] +impl From for PolicyType { + fn from(tp: u8) -> Self { + match tp { + 0 => PolicyType::Relative, + 1 => PolicyType::Absolute, + _ => env::panic(b"ERR_INVALID_POLICY_TYPE"), + } + } +} + #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)] #[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] #[serde(crate = "near_sdk::serde")] @@ -25,20 +32,33 @@ pub enum VotePolicy { Absolute(Rational, Rational), } -impl VotePolicy { +#[cfg(not(target_arch = "wasm32"))] +impl From> for VotePolicy { + fn from(content: Vec) -> Self { + VotePolicy::try_from_slice(&content).unwrap() + } +} +impl VotePolicy { /// to see if the proposal goes to a final state - pub fn judge(&self, aye: &Balance, nay: &Balance, remove: &Balance, total: &Balance, nonsense_threshold: &Rational) -> ProposalStatus { - if nonsense_threshold.pass(remove, total) { - ProposalStatus::Removed + pub fn judge( + &self, + approve_power: &Balance, + reject_power: &Balance, + nonsense_power: &Balance, + total: &Balance, + nonsense_threshold: &Rational, + ) -> ProposalStatus { + if nonsense_threshold.pass(nonsense_power, total) { + ProposalStatus::Nonsense } else { match self { VotePolicy::Relative(limit, threshold) => { - let voted = aye + nay + remove; + let voted = approve_power + reject_power + nonsense_power; if limit.pass(&voted, total) { - if threshold.pass(nay, &voted) { + if threshold.pass(reject_power, &voted) { ProposalStatus::Rejected - } else if threshold.pass(aye, &voted) { + } else if threshold.pass(approve_power, &voted) { ProposalStatus::Approved } else { ProposalStatus::InProgress @@ -46,31 +66,28 @@ impl VotePolicy { } else { ProposalStatus::InProgress } - }, + } VotePolicy::Absolute(pass_threshold, fail_threshold) => { - if fail_threshold.pass(nay, total) { + if fail_threshold.pass(reject_power, total) { ProposalStatus::Rejected - } else if pass_threshold.pass(aye, total) { + } else if pass_threshold.pass(approve_power, total) { ProposalStatus::Approved } else { ProposalStatus::InProgress } - }, + } } } } pub fn is_valid(&self) -> bool { match self { - VotePolicy::Relative(limit, threshold) => { - limit.is_valid() && threshold.is_valid() - }, + VotePolicy::Relative(limit, threshold) => limit.is_valid() && threshold.is_valid(), VotePolicy::Absolute(pass_threshold, fail_threshold) => { pass_threshold.is_valid() && fail_threshold.is_valid() - }, + } } } - } /// Status of a proposal. @@ -83,56 +100,63 @@ pub enum ProposalStatus { Approved, /// If quorum voted no, this proposal is rejected. Bond is returned. Rejected, - /// If quorum voted to remove (e.g. spam), this proposal is rejected and bond is not returned. - /// Interfaces shouldn't show removed proposals. - Removed, + /// If quorum voted to nonsense (e.g. spam), this proposal is rejected and bond is not returned. + /// Interfaces shouldn't show nonsense proposals. + Nonsense, /// Expired after period of time. Expired, } /// Kinds of proposals, doing different action. -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize)] -#[cfg_attr(not(target_arch = "wasm32"), derive(Clone, Debug))] +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] #[serde(crate = "near_sdk::serde")] pub enum ProposalKind { - /// Just a signaling vote, with no execution. + /// Just a single vote, with no execution. Vote, } -impl ProposalKind { - /// Returns label of policy for given type of proposal. - pub fn to_policy_label(&self) -> &str { - match self { - ProposalKind::Vote => "vote", +impl From<&str> for ProposalKind { + fn from(kind: &str) -> Self { + match kind { + "vote" => ProposalKind::Vote, + _ => env::panic(b"ERR_INVALID_PROPOSAL_KIND"), } } } /// Set of possible action to take. -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug)] +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize)] #[serde(crate = "near_sdk::serde")] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] pub enum Action { - /// Vote to approve given proposal or bounty. + /// Vote to approve given proposal VoteApprove, - /// Vote to reject given proposal or bounty. + /// Vote to reject given proposal VoteReject, - /// Vote to remove given proposal or bounty (because it's spam). - VoteRemove, + /// Vote to nonsense given proposal(because it's spam). + VoteNonsense, } -impl Action { - pub fn to_policy_label(&self) -> String { - format!("{:?}", self) +impl From<&str> for Action { + fn from(action: &str) -> Self { + match action { + "approve" => Action::VoteApprove, + "reject" => Action::VoteReject, + "nonsense" => Action::VoteNonsense, + _ => env::panic(b"ERR_INVALID_ACTION_KIND"), + } } } /// Votes recorded in the proposal. -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug)] +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)] #[serde(crate = "near_sdk::serde")] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] pub enum Vote { Approve = 0x0, Reject = 0x1, - Remove = 0x2, + Nonsense = 0x2, } impl From for Vote { @@ -140,7 +164,7 @@ impl From for Vote { match action { Action::VoteApprove => Vote::Approve, Action::VoteReject => Vote::Reject, - Action::VoteRemove => Vote::Remove, + Action::VoteNonsense => Vote::Nonsense, } } } @@ -162,14 +186,14 @@ pub struct Proposal { pub kind: ProposalKind, /// Current status of the proposal. pub status: ProposalStatus, - /// Count of votes per role per decision: Aye / Nay / Remove / Total. + /// Count of votes per role per opinion and total: Approve / Reject / Nonsense / Total. pub vote_counts: [Balance; 4], /// Session ID for voting period. pub session_id: u32, - /// the nano seconds of voting begin time after the session begin for the proposal, + /// the nano seconds of voting begin time after the session begin for the proposal, /// before this time, proposer can remove this immediately. pub start_offset: Timestamp, - /// the nano seconds of voting lasts after start_offset for the proposal, + /// the nano seconds of voting lasts after start_offset for the proposal, /// An inprogress poposal would change to expired after it. /// The (start_offset+lasts) should less than SESSION_INTERVAL. pub lasts: Timestamp, @@ -204,9 +228,9 @@ impl Proposal { self.vote_counts[3] = total.clone(); self.status = self.vote_policy.judge( - &self.vote_counts[0], - &self.vote_counts[1], - &self.vote_counts[2], + &self.vote_counts[0], + &self.vote_counts[1], + &self.vote_counts[2], &self.vote_counts[3], nonsense_threshold, ); @@ -226,24 +250,75 @@ impl Proposal { } else { self.status.clone() } - }, + } ProposalStatus::InProgress => { if cur_ts > end_ts { ProposalStatus::Expired } else { self.status.clone() } - }, + } _ => self.status.clone(), } } } +impl Contract { + pub(crate) fn internal_append_vote( + &mut self, + id: u32, + vote: &Vote, + amount: &Balance, + ) -> Balance { + let mut proposal: Proposal = self + .data() + .proposals + .get(&id) + .expect("ERR_NO_PROPOSAL") + .into(); + let cur_status = proposal.get_cur_status(self.data().genesis_timestamp); + proposal.status = cur_status; + + // check proposal is inprogress + match proposal.status { + ProposalStatus::InProgress => { + // update and judge proposal result + proposal.update_votes( + &vote, + amount, + &self.data().cur_total_ballot, + &self.data().nonsense_threshold, + ); + if proposal.status == ProposalStatus::Approved + || proposal.status == ProposalStatus::Rejected + { + // return lock near to proposer + Promise::new(proposal.proposer.clone()).transfer(proposal.lock_amount); + proposal.lock_amount = 0; + } + self.data_mut() + .proposals + .insert(&id, &VersionedProposal::Default(proposal)); + *amount + }, + _ => 0, + } + } +} + #[near_bindgen] impl Contract { /// Add proposal to this DAO. #[payable] - pub fn add_proposal(&mut self, description: String, kind: ProposalKind, policy_type: PolicyType, session_id: u32, start_offset_sec: u32, lasts_sec: u32) -> u64 { + pub fn add_proposal( + &mut self, + description: String, + kind: ProposalKind, + policy_type: PolicyType, + session_id: u32, + start_offset_sec: u32, + lasts_sec: u32, + ) -> u32 { // check point self.fresh_sessions(); @@ -251,18 +326,42 @@ impl Contract { // check and lock deposit let deposit_amount = env::attached_deposit(); - assert!(deposit_amount <= self.data().lock_amount_per_proposal, "ERR_NOT_ENOUGH_LOCK_NEAR"); + assert!( + deposit_amount >= self.data().lock_amount_per_proposal, + "ERR_NOT_ENOUGH_LOCK_NEAR" + ); if deposit_amount > self.data().lock_amount_per_proposal { - Promise::new(proposer.clone()).transfer(deposit_amount - self.data().lock_amount_per_proposal); + Promise::new(proposer.clone()) + .transfer(deposit_amount - self.data().lock_amount_per_proposal); } - // TODO: check time validation, session_id gte cur_session_id, (session_id.begin_ts+start_offset+lasts) lt (session_id+1).begin_ts + // Check time validation, session_id gte cur_session_id, (session_id.begin_ts+start_offset+lasts) lt (session_id+1).begin_ts + let current_session_id = self.data().sessions[self.data().cur_session].session_id; + assert!( + session_id >= current_session_id, + "ERR_SESSION_ID_NEED_GE_CURRENT_SESSION_ID" + ); + let base_timestamp = self.data().genesis_timestamp + SESSION_INTERMAL * session_id as u64; + assert!( + (base_timestamp + sec_to_nano(start_offset_sec)) > env::block_timestamp(), + "ERR_PROPOSAL_START_TIME_NEED_GE_CURRENT_TIME" + ); + assert!( + (base_timestamp + sec_to_nano(start_offset_sec + lasts_sec)) + < base_timestamp + SESSION_INTERMAL, + "ERR_PROPOSAL_END_TIME_NEED_LE_NEXT_SESSION_BEGIN_TIME" + ); let ps = Proposal { proposer, lock_amount: self.data().lock_amount_per_proposal, description, - vote_policy: self.data().vote_policy.get(policy_type as usize).unwrap().clone(), + vote_policy: self + .data() + .vote_policy + .get(policy_type as usize) + .unwrap() + .clone(), kind, status: ProposalStatus::WarmUp, vote_counts: [0; 4], @@ -273,18 +372,36 @@ impl Contract { // actually add proposal to this DAO let id = self.data().last_proposal_id; - self.data_mut().proposals.insert(&id, &VersionedProposal::Default(ps)); + self.data_mut() + .proposals + .insert(&id, &VersionedProposal::Default(ps)); self.data_mut().last_proposal_id += 1; + self.add_proposal_to_session(id, session_id); + id } /// proposer can call this to remove proposal before start time. - pub fn remove_proposal(&mut self, id: u64) -> bool { + /// id: proposal id + /// return true if sucessfully removed, false if already start + /// panic if following: + /// * no proposal found + /// * predecessor not prposer + pub fn remove_proposal(&mut self, id: u32) -> bool { // sync point self.fresh_sessions(); - let proposal: Proposal = self.data().proposals.get(&id).expect("ERR_NO_PROPOSAL").into(); - assert_eq!(proposal.proposer, env::predecessor_account_id(), "ERR_NOT_ALLOW"); + let proposal: Proposal = self + .data() + .proposals + .get(&id) + .expect("ERR_NO_PROPOSAL") + .into(); + assert_eq!( + proposal.proposer, + env::predecessor_account_id(), + "ERR_NOT_ALLOW" + ); let cur_status = proposal.get_cur_status(self.data().genesis_timestamp); match cur_status { ProposalStatus::WarmUp => { @@ -292,24 +409,43 @@ impl Contract { Promise::new(proposal.proposer.clone()).transfer(proposal.lock_amount); } self.data_mut().proposals.remove(&id); + + self.remove_proposal_from_session(id, proposal.session_id); + true - }, + } _ => false, } } /// When a proposal expired, the proposer can call this to redeem locked near - pub fn redeem_near_in_expired_proposal(&mut self, id: u64) -> bool { + /// id: proposal id + /// return true if schedule to transfer back locked near, false if nothing to redeem (already redeemed or nonsense) + /// panic if following: + /// * no proposal found + /// * predecessor not prposer + pub fn redeem_near_in_expired_proposal(&mut self, id: u32) -> bool { // sync point self.fresh_sessions(); - let mut proposal: Proposal = self.data().proposals.get(&id).expect("ERR_NO_PROPOSAL").into(); - assert_eq!(proposal.proposer, env::predecessor_account_id(), "ERR_NOT_ALLOW"); + let mut proposal: Proposal = self + .data() + .proposals + .get(&id) + .expect("ERR_NO_PROPOSAL") + .into(); + assert_eq!( + proposal.proposer, + env::predecessor_account_id(), + "ERR_NOT_ALLOW" + ); let cur_status = proposal.get_cur_status(self.data().genesis_timestamp); proposal.status = cur_status; if proposal.lock_amount > 0 && proposal.status == ProposalStatus::Expired { Promise::new(proposal.proposer.clone()).transfer(proposal.lock_amount); proposal.lock_amount = 0; - self.data_mut().proposals.insert(&id, &VersionedProposal::Default(proposal)); + self.data_mut() + .proposals + .insert(&id, &VersionedProposal::Default(proposal)); true } else { false @@ -317,40 +453,27 @@ impl Contract { } /// Act on given proposal by id, if permissions allow. - /// Memo is logged but not stored in the state. Can be used to leave notes or explain the action. - pub fn act_proposal(&mut self, id: u64, action: Action, memo: Option) -> bool { + /// id: propoal id + /// action: one of "VoteApprove", "VoteReject", "VoteNonsense" + /// memo: is logged but not stored in the state. Can be used to leave notes or explain the action. + /// return accepted ballot power + /// would panic if act failed + pub fn act_proposal(&mut self, id: u32, action: Action, memo: Option) -> U128 { // sync point self.fresh_sessions(); - let vote: Vote = action.into(); - - let mut proposal: Proposal = self.data().proposals.get(&id).expect("ERR_NO_PROPOSAL").into(); - let cur_status = proposal.get_cur_status(self.data().genesis_timestamp); - proposal.status = cur_status; - - // check proposal is inprogress - assert_eq!(proposal.status, ProposalStatus::InProgress, "ERR_PROPOSAL_NOT_VOTABLE"); - let account_id = env::predecessor_account_id(); - // get vote amount for this action - let ballot_amount = self.internal_vote(&account_id, id, &vote); - - // update and judge proposal result - proposal.update_votes(&vote, &ballot_amount, &self.data().cur_total_ballot, &self.data().nonsense_threshold); - - if proposal.status == ProposalStatus::Approved || proposal.status == ProposalStatus::Rejected { - // return lock near to proposer - Promise::new(proposal.proposer.clone()).transfer(proposal.lock_amount); - proposal.lock_amount = 0; - } + let vote: Vote = action.into(); + let ballot_amount = self.internal_account_vote(&account_id, id, &vote); - self.data_mut().proposals.insert(&id, &VersionedProposal::Default(proposal)); + let accept_ballot = self.internal_append_vote(id, &vote, &ballot_amount); + assert_eq!(accept_ballot, ballot_amount, "ERR_PROPOSAL_NOT_VOTABLE"); if let Some(memo) = memo { log!("Memo: {}", memo); } - true + accept_ballot.into() } -} \ No newline at end of file +} diff --git a/referendum/src/session.rs b/referendum/src/session.rs index 9b2065b..2b1267a 100644 --- a/referendum/src/session.rs +++ b/referendum/src/session.rs @@ -1,39 +1,71 @@ -//! Session stores information per session +//! Session stores information per session use crate::*; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; -use near_sdk::{Balance, Timestamp}; -use near_sdk::serde::{Deserialize, Serialize}; -use near_sdk::json_types::{U128}; +use near_sdk::Balance; #[derive(BorshSerialize, BorshDeserialize, Clone, Copy, Default)] pub struct SessionInfo { pub session_id: u32, - // pub expire_time: Timestamp, pub expire_amount: Balance, } impl Contract { + /// get newest cur ballots + pub(crate) fn calc_cur_ballots(&self) -> Balance { + if self.has_launch() { + let cur_session_id = self.get_cur_session_id(); + if self.data().sessions[1].session_id == 0 { + // hasn't initialized + 0 + } else { + // get real ballot + let head = self.data().cur_session; + let mut ballot = self.data().cur_total_ballot; + for i in 0..MAX_SESSIONS { + let idx = (i + head) % MAX_SESSIONS; + let session = self.data().sessions[idx].clone(); + if session.session_id < cur_session_id { + // expire ballot + ballot -= session.expire_amount; + } else { + break; + } + } + ballot + } + } else { + // before launch, ballot amount is 0 + 0 + } + } + /// update sessions. pub(crate) fn fresh_sessions(&mut self) { self.assert_launch(); - let cur_session_id = (env::block_timestamp() - self.data().genesis_timestamp) / SESSION_INTERMAL; - + let cur_session_id = self.get_cur_session_id(); + let head = self.data().cur_session; if self.data().sessions[1].session_id == 0 { - // TODO: need initiate all sessions according to genesis timestamp + // initialize session info + for i in 0..MAX_SESSIONS { + self.data_mut().sessions[i].session_id = cur_session_id + i as u32; + self.data_mut().proposal_ids_in_sessions.push(&vec![]); + } } else { // checkpoint logic for i in 0..MAX_SESSIONS { - let idx = (i + head) % MAX_SESSIONS; + let idx = (i + head) % MAX_SESSIONS; let session = self.data().sessions[idx].clone(); - if (session.session_id as u64) < cur_session_id { + if session.session_id < cur_session_id { // expire ballot self.data_mut().cur_total_ballot -= session.expire_amount; // prepare for new session self.data_mut().sessions[idx].expire_amount = 0; - self.data_mut().sessions[idx].session_id = session.session_id + MAX_SESSIONS as u32; + self.data_mut().sessions[idx].session_id = + session.session_id + MAX_SESSIONS as u32; + self.data_mut().proposal_ids_in_sessions.push(&vec![]); } else { // spin to the new head self.data_mut().cur_session = idx; @@ -42,4 +74,28 @@ impl Contract { } } } -} \ No newline at end of file + + pub(crate) fn add_proposal_to_session(&mut self, proposal_id: u32, session_id: u32) { + let mut proposal_ids = self + .data() + .proposal_ids_in_sessions + .get(session_id as u64) + .unwrap(); + proposal_ids.push(proposal_id); + self.data_mut() + .proposal_ids_in_sessions + .replace(session_id as u64, &proposal_ids); + } + + pub(crate) fn remove_proposal_from_session(&mut self, proposal_id: u32, session_id: u32) { + let mut proposal_ids = self + .data() + .proposal_ids_in_sessions + .get(session_id as u64) + .unwrap(); + proposal_ids.retain(|&x| x != proposal_id); + self.data_mut() + .proposal_ids_in_sessions + .replace(session_id as u64, &proposal_ids); + } +} diff --git a/referendum/src/storage_impl.rs b/referendum/src/storage_impl.rs new file mode 100644 index 0000000..169a68a --- /dev/null +++ b/referendum/src/storage_impl.rs @@ -0,0 +1,91 @@ +use crate::*; +use near_contract_standards::storage_management::{ + StorageBalance, StorageBalanceBounds, StorageManagement, +}; + +use std::convert::TryInto; +use near_sdk::json_types::{ValidAccountId, U128}; +use near_sdk::{assert_one_yocto, env, near_bindgen, Promise}; + +#[near_bindgen] +impl StorageManagement for Contract { + #[allow(unused_variables)] + #[payable] + fn storage_deposit( + &mut self, + account_id: Option, + registration_only: Option, + ) -> StorageBalance { + self.assert_launch(); + let amount = env::attached_deposit(); + let account_id = account_id + .map(|a| a.into()) + .unwrap_or_else(|| env::predecessor_account_id()); + let min_balance = self.storage_balance_bounds().min.0; + let already_registered = self.data().accounts.contains_key(&account_id); + if amount < min_balance && !already_registered { + env::panic(b"ERR_DEPOSIT_LESS_THAN_MIN_STORAGE"); + } + if already_registered { + if amount > 0 { + Promise::new(env::predecessor_account_id()).transfer(amount); + } + } else { + self.internal_register_account(&account_id); + self.data_mut().account_number += 1; + let refund = amount - min_balance; + if refund > 0 { + Promise::new(env::predecessor_account_id()).transfer(refund); + } + } + self.storage_balance_of(account_id.try_into().unwrap()) + .unwrap() + } + + #[allow(unused_variables)] + #[payable] + fn storage_withdraw(&mut self, amount: Option) -> StorageBalance { + assert_one_yocto(); + env::panic(b"ERR_NO_STORAGE_CAN_WITHDRAW"); + } + + #[allow(unused_variables)] + #[payable] + fn storage_unregister(&mut self, force: Option) -> bool { + assert_one_yocto(); + self.assert_launch(); + let current_state = self.data(); + let account_id = env::predecessor_account_id(); + if let Some(VAccount::Current(account)) = current_state.accounts.get(&account_id) { + assert!( + account.locking_amount == 0, + "ERR_ACCOUNT_NOT_UNLOCK" + ); + self.data_mut().accounts.remove(&account_id); + let number = self.data().account_number.checked_sub(1).unwrap_or(0); + self.data_mut().account_number = number; + Promise::new(account_id.clone()).transfer(STORAGE_BALANCE_MIN_BOUND); + true + } else { + false + } + } + + fn storage_balance_bounds(&self) -> StorageBalanceBounds { + StorageBalanceBounds { + min: U128(STORAGE_BALANCE_MIN_BOUND), + max: None, + } + } + + fn storage_balance_of(&self, account_id: ValidAccountId) -> Option { + if self.data().accounts.contains_key(&account_id.into()) { + Some(StorageBalance { + total: U128(STORAGE_BALANCE_MIN_BOUND), + available: U128(0), + }) + }else{ + None + } + } +} \ No newline at end of file diff --git a/referendum/src/utils.rs b/referendum/src/utils.rs index c0d76f7..2a34544 100644 --- a/referendum/src/utils.rs +++ b/referendum/src/utils.rs @@ -1,10 +1,18 @@ //! Utils stores pub info +use std::ops::Mul; + use near_sdk::json_types::U128; -use near_sdk::{ext_contract, Gas, Balance, Timestamp}; +use near_sdk::{ext_contract, Gas, Timestamp, Balance}; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::serde::{Deserialize, Serialize}; -use crate::proposals::{VotePolicy, Vote}; +use uint::construct_uint; + +construct_uint! { + /// 256-bit unsigned integer. + pub struct U256(4); +} +use crate::proposals::VotePolicy; /// Attach no deposit. pub const NO_DEPOSIT: u128 = 0; @@ -22,6 +30,7 @@ pub const SESSION_INTERMAL: u64 = 3600 * 24 * 30 * 1_000_000_000; /// make the default launch time to be 30 days after contract initiation pub const DEFAULT_GENESIS_OFFSET: u64 = 3600 * 24 * 30 * 1_000_000_000; +pub const STORAGE_BALANCE_MIN_BOUND: u128 = 10_000_000_000_000_000_000_000; /// default locking amount is 10 near for each proposal pub const DEFAULT_LOCK_NEAR_AMOUNT_FOR_PROPOSAL: Balance = 10_000_000_000_000_000_000_000_000; @@ -47,11 +56,17 @@ pub struct Rational { denominator: u32, } +impl From> for Rational { + fn from(content: Vec) -> Self { + Rational::try_from_slice(&content).unwrap() + } +} + impl Rational { pub fn pass(&self, num: &Balance, denom: &Balance) -> bool { - // TODO: implement using U256 to judge num/denom >= self - true + U256::from(*num).mul(U256::from(self.denominator)). + ge(&U256::from(self.numerator).mul(U256::from(*denom))) } pub fn is_valid(&self) -> bool { @@ -59,8 +74,8 @@ impl Rational { } } -pub fn nano_to_sec(nano: Timestamp) -> u64 { - nano / 1_000_000_000 +pub fn nano_to_sec(nano: Timestamp) -> u32 { + (nano / 1_000_000_000) as u32 } pub fn sec_to_nano(sec: u32) -> Timestamp { @@ -68,10 +83,24 @@ pub fn sec_to_nano(sec: u32) -> Timestamp { } #[ext_contract(ext_self)] -pub trait Unlock { - fn callback_post_unlock( +pub trait Withdraw { + fn callback_post_withdraw( &mut self, sender_id: AccountId, amount: U128, ); +} + +pub fn nano_to_day(nano: Timestamp) -> u64 { + nano / (3600 * 24 * 1_000_000_000) +} + +pub fn calculate_ballots(current_session_remaining_days: u64, total_amount: Balance, locking_period: u32) -> Balance{ + assert!(locking_period > 0, "ERR_ILLEGAL_LASTS"); + let future_session_ballots = total_amount * (locking_period - 1) as u128; + let current_session_ballots = (U256::from(total_amount) + * U256::from(current_session_remaining_days) + / U256::from(nano_to_day(SESSION_INTERMAL))) + .as_u128(); + future_session_ballots + current_session_ballots } \ No newline at end of file diff --git a/referendum/src/views.rs b/referendum/src/views.rs new file mode 100644 index 0000000..9753884 --- /dev/null +++ b/referendum/src/views.rs @@ -0,0 +1,208 @@ +//! View functions for the contract. + +use crate::*; +use crate::proposals::Vote; +use near_sdk::serde::{Deserialize, Serialize}; +use near_sdk::json_types::U128; + +#[derive(Serialize, Deserialize, Clone)] +#[serde(crate = "near_sdk::serde")] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] +pub struct ContractMetadata { + /// the owner account id of contract + pub owner_id: AccountId, + /// accept lock token account id + pub locked_token: AccountId, + /// the launch timestamp in seconds + pub genesis_timestamp_sec: u32, + /// current session id (start from 0) + pub cur_session_id: u32, + /// current total ballot amount (calculate at call time) + pub cur_total_ballot: U128, + /// current locking token amount (include those expired but hasn't unlock by user) + pub cur_lock_amount: U128, + /// the availabe proposal id for new proposal + pub last_proposal_id: u32, + /// lock near amount for endorsement a proposal + pub lock_amount_per_proposal: U128, + /// current account number in contract + pub account_number: u64, + /// a list of [Relative, Absolute] in which each item is formated as + /// [{"numerator": n, "denominator": m}, {"numerator": n, "denominator": m}] + pub vote_policy: Vec, + /// in format as {"numerator": n, "denominator": m} + pub nonsense_threshold: Rational, +} + +#[derive(Serialize, Deserialize)] +#[serde(crate = "near_sdk::serde")] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] +pub struct ProposalInfo{ + pub id: u32, + pub proposer: AccountId, + /// near amount for endorsement + pub lock_amount: U128, + pub description: String, + /// one of the following: + /// "VotePolicy": {"Relative": [{"numerator": n, "denominator": m}, {"numerator": n, "denominator": m}]} + /// "VotePolicy": {"Absolute": [{"numerator": n, "denominator": m}, {"numerator": n, "denominator": m}]} + pub vote_policy: proposals::VotePolicy, + /// currently would only be "Vote" + pub kind: proposals::ProposalKind, + /// one of the following: + /// "WarmUp", "InProgress", "Approved", "Rejected", "Nonsense", "Expired" + pub status: proposals::ProposalStatus, + /// [Approve_count, Reject_count, Nonsense_count, Total_ballots] + pub vote_counts: [U128; 4], + /// The session this proposal is valid in + pub session_id: u32, + /// the start time = session_begin_time + start_offset + pub start_offset_sec: u32, + /// the proposal max valid period in seconds + pub lasts_sec: u32, +} + +#[derive(Serialize, Deserialize, Clone)] +#[serde(crate = "near_sdk::serde")] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] +pub struct AccountInfo { + /// locked token (XREF) amount + pub locking_amount: U128, + /// ballot amount (calculate at call time) + pub ballot_amount: U128, + /// unlock at the begin of this session, meanwhile ballots reset to zero + pub unlocking_session_id: u32, +} + +#[derive(Serialize, Deserialize, Clone)] +#[serde(crate = "near_sdk::serde")] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] +pub struct HumanReadableAccountVote { + pub proposal_id: u32, + pub vote: Vote, + pub amount: U128, +} + + +#[derive(Serialize, Deserialize)] +#[serde(crate = "near_sdk::serde")] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq, Clone, Copy))] +pub struct SessionState { + pub session_id: u32, + pub expire_amount: U128, +} + +impl From for SessionState { + fn from(session_info: SessionInfo) -> Self { + Self { + session_id: session_info.session_id, + expire_amount: session_info.expire_amount.into(), + } + } +} + +#[near_bindgen] +impl Contract { + /// Return contract basic info + pub fn contract_metadata(&self) -> ContractMetadata { + let current_state = self.data(); + ContractMetadata { + owner_id: current_state.owner_id.clone(), + locked_token: current_state.locked_token.clone(), + genesis_timestamp_sec: nano_to_sec(current_state.genesis_timestamp), + cur_session_id: self.get_cur_session_id(), + cur_total_ballot: self.calc_cur_ballots().into(), + cur_lock_amount: current_state.cur_lock_amount.into(), + last_proposal_id: current_state.last_proposal_id, + lock_amount_per_proposal: U128(current_state.lock_amount_per_proposal), + account_number: current_state.account_number, + vote_policy: current_state.vote_policy.clone(), + nonsense_threshold: current_state.nonsense_threshold.clone(), + } + } + + /// get single proposal current info + pub fn get_proposal_info(&self, proposal_id: u32) -> Option{ + if let Some(VersionedProposal::Default(proposal)) = self.data().proposals.get(&proposal_id).as_ref() { + Some(ProposalInfo{ + id: proposal_id, + proposer: proposal.proposer.clone(), + lock_amount: U128(proposal.lock_amount), + description: proposal.description.clone(), + vote_policy: proposal.vote_policy.clone(), + kind: proposal.kind.clone(), + status: proposal.get_cur_status(self.data().genesis_timestamp), + vote_counts: proposal.vote_counts.map(|v| U128(v)), + session_id: proposal.session_id, + start_offset_sec: nano_to_sec(proposal.start_offset), + lasts_sec: nano_to_sec(proposal.lasts), + }) + }else{ + None + } + } + + /// get proposals by session + pub fn get_proposals_in_session(&self, session_id: u32) -> Vec { + let mut ret: Vec = vec![]; + for id in self.get_proposal_ids_in_session(session_id) { + if let Some(item) = self.get_proposal_info(id) { + ret.push(item); + } + } + ret + } + + pub fn get_proposal_ids_in_session(&self, session_id: u32) -> Vec { + match self.data().proposal_ids_in_sessions.get(session_id as u64) { + Some(proposal_ids) => proposal_ids, + None => vec![] + } + } + + pub fn get_account_info(&self, account_id: ValidAccountId) -> Option { + if let Some(vacc) = self.data().accounts.get(account_id.as_ref()) { + match vacc { + VAccount::Current(acc) => { + Some(AccountInfo { + locking_amount: acc.locking_amount.into(), + ballot_amount: acc.sync_ballot(self.get_cur_session_id()).into(), + unlocking_session_id: acc.unlocking_session_id, + }) + } + } + } else { + None + } + } + + pub fn get_account_proposals_in_session(&self, account_id: ValidAccountId, session_id: u32) -> Vec { + let mut ret: Vec = vec![]; + match self.data().proposal_ids_in_sessions.get(session_id as u64) { + Some(proposal_ids) => { + if let Some(vacc) = self.data().accounts.get(account_id.as_ref()) { + match vacc { + VAccount::Current(acc) => { + for proposal_id in proposal_ids { + if let Some(account_vote) = acc.proposals.get(&proposal_id).as_ref() { + ret.push(HumanReadableAccountVote { + proposal_id, + vote: account_vote.vote.clone(), + amount: account_vote.amount.into(), + }); + } + } + } + } + } + }, + None => {}, + } + ret + } + + // TODO: maybe unnecessary to get session info + pub fn get_session_state(&self, session_idx: usize) -> SessionState { + self.data().sessions[session_idx].into() + } +} \ No newline at end of file diff --git a/referendum/tests/common/init.rs b/referendum/tests/common/init.rs new file mode 100644 index 0000000..02e03f8 --- /dev/null +++ b/referendum/tests/common/init.rs @@ -0,0 +1,74 @@ +#![allow(unused)] +use near_sdk_sim::{call, deploy, init_simulator, to_yocto, ContractAccount, UserAccount}; +use test_token::ContractContract as TestToken; +use referendum::ContractContract as Referendum; +use crate::*; + +near_sdk_sim::lazy_static_include::lazy_static_include_bytes! { + TEST_WASM_BYTES => "../res/test_token.wasm", + REFERENDUM_WASM_BYTES => "../res/referendum_local.wasm", +} + + + +pub fn init_env(register_user: bool) -> (UserAccount, UserAccount, UserAccount, ContractAccount, ContractAccount) { + let root = init_simulator(None); + + let owner = root.create_user("owner".to_string(), to_yocto("100")); + let user = root.create_user("user".to_string(), to_yocto("100")); + + let xref_contract = deploy!( + contract: TestToken, + contract_id: "xref", + bytes: &TEST_WASM_BYTES, + signer_account: root + ); + call!(root, xref_contract.new("xref".to_string(), "xref".to_string(), 18)).assert_success(); + call!(owner, xref_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + call!(user, xref_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + + call!(root, xref_contract.mint(owner.valid_account_id(), to_yocto("10000").into())).assert_success(); + call!(root, xref_contract.mint(user.valid_account_id(), to_yocto("100").into())).assert_success(); + + let referendum_contract = deploy!( + contract: Referendum, + contract_id: "referendum", + bytes: &REFERENDUM_WASM_BYTES, + signer_account: root + ); + call!(root, referendum_contract.new(owner.valid_account_id(), xref_contract.valid_account_id())).assert_success(); + call!(root, xref_contract.storage_deposit(Some(referendum_contract.valid_account_id()), None), deposit = to_yocto("1")).assert_success(); + if register_user { + let current_timestamp = root.borrow_runtime().current_block().block_timestamp; + call!( + owner, + referendum_contract.modify_genesis_timestamp(nano_to_sec(current_timestamp) + 10) + ) + .assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(nano_to_sec(current_timestamp) + 10); + + call!(user, referendum_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + } + (root, owner, user, xref_contract, referendum_contract) +} + +pub fn init_proposal_users(root: &UserAccount, xref_contract: &ContractAccount, referendum_contract: &ContractAccount) -> (UserAccount, UserAccount, UserAccount){ + let proposal_user = root.create_user("proposal_user".to_string(), to_yocto("100")); + let vote_user1 = root.create_user("vote_user1".to_string(), to_yocto("100")); + let vote_user2 = root.create_user("vote_user2".to_string(), to_yocto("100")); + + call!(proposal_user, xref_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + call!(vote_user1, xref_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + call!(vote_user2, xref_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + + call!(proposal_user, referendum_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + call!(vote_user1, referendum_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + call!(vote_user2, referendum_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + + call!(root, xref_contract.mint(proposal_user.valid_account_id(), to_yocto("100").into())).assert_success(); + call!(root, xref_contract.mint(vote_user1.valid_account_id(), to_yocto("100").into())).assert_success(); + call!(root, xref_contract.mint(vote_user2.valid_account_id(), to_yocto("100").into())).assert_success(); + + (proposal_user, vote_user1, vote_user2) +} \ No newline at end of file diff --git a/referendum/tests/common/mod.rs b/referendum/tests/common/mod.rs new file mode 100644 index 0000000..d050952 --- /dev/null +++ b/referendum/tests/common/mod.rs @@ -0,0 +1,2 @@ +pub mod init; +pub mod utils; \ No newline at end of file diff --git a/referendum/tests/common/utils.rs b/referendum/tests/common/utils.rs new file mode 100644 index 0000000..4a3125b --- /dev/null +++ b/referendum/tests/common/utils.rs @@ -0,0 +1,102 @@ +#![allow(unused)] +use near_sdk_sim::{ExecutionResult, view}; +use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::serde::{Deserialize, Serialize}; +use near_sdk::json_types::U128; +use near_sdk::AccountId; + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct AccountInfo { + pub locking_amount: U128, + pub ballot_amount: U128, + pub unlocking_session_id: u32, +} + +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] +#[serde(crate = "near_sdk::serde")] +pub struct SessionState { + pub session_id: u32, + pub expire_amount: U128, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct ContractMetadata { + pub owner_id: AccountId, + pub locked_token: AccountId, + pub genesis_timestamp_sec: u32, + pub cur_session_id: u32, + pub cur_total_ballot: U128, + pub cur_lock_amount: U128, + pub last_proposal_id: u32, + pub lock_amount_per_proposal: U128, + pub account_number: u64, + pub vote_policy: Vec, + pub nonsense_threshold: Rational, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(crate = "near_sdk::serde")] +pub enum ProposalKind { + Vote, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(crate = "near_sdk::serde")] +pub enum ProposalStatus { + WarmUp, + InProgress, + Approved, + Rejected, + Nonsense, + Expired, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct ProposalInfo{ + pub id: u32, + pub proposer: AccountId, + pub lock_amount: U128, + pub description: String, + pub vote_policy: VotePolicy, + pub kind: ProposalKind, + pub status: ProposalStatus, + pub vote_counts: [U128; 4], + pub session_id: u32, + pub start_offset_sec: u32, + pub lasts_sec: u32, +} + +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] +#[serde(crate = "near_sdk::serde")] +pub struct Rational { + pub numerator: u32, + pub denominator: u32, +} + +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)] +#[cfg_attr(not(target_arch = "wasm32"), derive(Debug, PartialEq))] +#[serde(crate = "near_sdk::serde")] +pub enum VotePolicy { + Relative(Rational, Rational), + Absolute(Rational, Rational), +} + +pub fn get_error_count(r: &ExecutionResult) -> u32 { + r.promise_errors().len() as u32 +} + +pub fn get_error_status(r: &ExecutionResult) -> String { + format!("{:?}", r.promise_errors()[0].as_ref().unwrap().status()) +} + +pub fn nano_to_sec(nano: u64) -> u32 { + (nano / 1_000_000_000) as u32 +} + +pub fn sec_to_nano(sec: u32) -> u64 { + sec as u64 * 1_000_000_000 +} \ No newline at end of file diff --git a/referendum/tests/owner.rs b/referendum/tests/owner.rs new file mode 100644 index 0000000..180d2e0 --- /dev/null +++ b/referendum/tests/owner.rs @@ -0,0 +1,44 @@ +use near_sdk_sim::{call, view, to_yocto}; +use near_sdk::json_types::U128; +mod common; +use crate::common::{ + init::*, + utils::* +}; + +#[test] +fn test_owner(){ + let (root, owner, user, _, referendum_contract) = + init_env(false); + + call!( + owner, + referendum_contract.set_owner(user.valid_account_id()) + ).assert_success(); + + let out_come = call!( + owner, + referendum_contract.set_owner(user.valid_account_id()) + ); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NOT_ALLOWED")); + + let current_timestamp = root.borrow_runtime().current_block().block_timestamp; + call!( + user, + referendum_contract.modify_genesis_timestamp(nano_to_sec(current_timestamp) + 10) + ).assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(nano_to_sec(current_timestamp) + 10); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.genesis_timestamp_sec, nano_to_sec(current_timestamp) + 10); + + assert_eq!(contract_metadata.lock_amount_per_proposal.0, to_yocto("10")); + call!( + user, + referendum_contract.modify_endorsement_amount(U128(to_yocto("20"))) + ).assert_success(); + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.lock_amount_per_proposal.0, to_yocto("20")); +} \ No newline at end of file diff --git a/referendum/tests/test_lock.rs b/referendum/tests/test_lock.rs new file mode 100644 index 0000000..f6ea127 --- /dev/null +++ b/referendum/tests/test_lock.rs @@ -0,0 +1,285 @@ +use near_sdk_sim::{call, view, to_yocto}; +mod common; +use crate::common::{ + init::*, + utils::* +}; + +#[test] +fn test_lock_user_not_register(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let user = root.create_user("user_not_register".to_string(), to_yocto("100")); + call!(user, xref_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + call!(root, xref_contract.mint(user.valid_account_id(), to_yocto("100").into())).assert_success(); + + let out_come = call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "10".to_string()), + deposit = 1 + ); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_USER_NOT_REGISTER")); +} + +#[test] +fn test_lock_new_lasts1(){ + let (_, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 0); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("10")); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("10")); + assert_eq!(account_info.ballot_amount.0, to_yocto("10")); + assert_eq!(account_info.unlocking_session_id, 1); + + let session_state = view!(referendum_contract.get_session_state(0)).unwrap_json::(); + assert_eq!(session_state.session_id, 0); + assert_eq!(session_state.expire_amount.0, to_yocto("10")); +} + +#[test] +fn test_lock_new_lasts24(){ + let (_, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "24".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 0); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("10") * 24); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 0); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("10") * 24); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("10")); + assert_eq!(account_info.ballot_amount.0, to_yocto("10") * 24); + assert_eq!(account_info.unlocking_session_id, 24); + + let session_state = view!(referendum_contract.get_session_state(23)).unwrap_json::(); + assert_eq!(session_state.session_id, 23); + assert_eq!(session_state.expire_amount.0, to_yocto("10") * 24); +} + +#[test] +fn test_lock_new_when_session_last_day(){ + let (root, _, user, xref_contract, referendum_contract) = + init_env(true); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 29 * 3600 * 24 * 1_000_000_000; + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 0); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("1")); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("30")); + assert_eq!(account_info.ballot_amount.0, to_yocto("1")); + assert_eq!(account_info.unlocking_session_id, 1); + + let session_state = view!(referendum_contract.get_session_state(0)).unwrap_json::(); + assert_eq!(session_state.session_id, 0); + assert_eq!(session_state.expire_amount.0, to_yocto("1")); +} + +#[test] +fn test_lock_new_expire(){ + let (root, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("10")); + assert_eq!(account_info.ballot_amount.0, to_yocto("10")); + assert_eq!(account_info.unlocking_session_id, 1); + + let session_state = view!(referendum_contract.get_session_state(0)).unwrap_json::(); + assert_eq!(session_state.session_id, 0); + assert_eq!(session_state.expire_amount.0, to_yocto("10")); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 30 * 3600 * 24 * 1_000_000_000; + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("20")); + assert_eq!(account_info.ballot_amount.0, to_yocto("20")); + assert_eq!(account_info.unlocking_session_id, 2); +} + +#[test] +fn test_lock_append_expire(){ + let (root, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("10")); + assert_eq!(account_info.ballot_amount.0, to_yocto("10")); + assert_eq!(account_info.unlocking_session_id, 1); + + let session_state = view!(referendum_contract.get_session_state(0)).unwrap_json::(); + assert_eq!(session_state.session_id, 0); + assert_eq!(session_state.expire_amount.0, to_yocto("10")); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 31 * 3600 * 24 * 1_000_000_000; + + let out_come = call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "".to_string()), + deposit = 1 + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NO_RUNNING_LOCKING")); +} + +#[test] +fn test_lock_append(){ + let (_, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "10".to_string()), + deposit = 1 + ).assert_success(); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 0); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("20") * 10); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("20")); + assert_eq!(account_info.ballot_amount.0, to_yocto("20") * 10); + assert_eq!(account_info.unlocking_session_id, 10); + + let session_state = view!(referendum_contract.get_session_state(9)).unwrap_json::(); + assert_eq!(session_state.session_id, 9); + assert_eq!(session_state.expire_amount.0, to_yocto("20") * 10); +} + +#[test] +fn test_lock_middle_append(){ + let (root, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "10".to_string()), + deposit = 1 + ).assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 5 * 30 * 3600 * 24 * 1_000_000_000; + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 5); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("10") * 10 + to_yocto("10") * 5); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("20")); + assert_eq!(account_info.ballot_amount.0, to_yocto("10") * 10 + to_yocto("10") * 5); + assert_eq!(account_info.unlocking_session_id, 10); + + let session_state = view!(referendum_contract.get_session_state(9)).unwrap_json::(); + assert_eq!(session_state.session_id, 9); + assert_eq!(session_state.expire_amount.0, to_yocto("10") * 10 + to_yocto("10") * 5); +} + +#[test] +fn test_lock_append_add_msg(){ + let (_, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "10".to_string()), + deposit = 1 + ).assert_success(); + + let out_come = call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "10".to_string()), + deposit = 1 + ); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_EXIST_RUNNING_LOCKING")); +} + +#[test] +fn test_lock_append_when_no_lock(){ + let (_, _, user, xref_contract, referendum_contract) = + init_env(true); + + let out_come = call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "".to_string()), + deposit = 1 + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NO_RUNNING_LOCKING")); +} + +#[test] +fn test_lock_append_illegal_msg(){ + let (_, _, user, xref_contract, referendum_contract) = + init_env(true); + + let out_come = call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "0".to_string()), + deposit = 1 + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_ILLEGAL_MSG")); +} diff --git a/referendum/tests/test_proposal.rs b/referendum/tests/test_proposal.rs new file mode 100644 index 0000000..e99ba48 --- /dev/null +++ b/referendum/tests/test_proposal.rs @@ -0,0 +1,361 @@ +use near_sdk_sim::{call, view, to_yocto}; +use near_sdk::json_types::U128; +use near_sdk::borsh::BorshSerialize; +mod common; +use crate::common::{ + init::*, + utils::* +}; + +#[test] +fn test_add_proposal(){ + let (root, owner, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let vote_policy = VotePolicy::Relative(Rational{numerator:1, denominator:2}, Rational{numerator:1, denominator:2}); + + call!( + owner, + referendum_contract.modify_vote_policy(vote_policy.try_to_vec().unwrap().into()) + ).assert_success(); + + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 1, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ); + + assert_eq!(out_come.unwrap_json::(), 0); + assert!(orig_user_balance - proposal_user.account().unwrap().amount > to_yocto("10")); + assert!(orig_user_balance - proposal_user.account().unwrap().amount < to_yocto("10.11")); + + let proposal_info = view!(referendum_contract.get_proposal_info(0)).unwrap_json::(); + + assert_eq!(proposal_info.proposer, proposal_user.account_id); + assert_eq!(proposal_info.lock_amount.0, 10_000_000_000_000_000_000_000_000); + assert_eq!(proposal_info.description, "test proposal".to_string()); + assert_eq!(proposal_info.vote_policy, vote_policy); + assert_eq!(proposal_info.kind, ProposalKind::Vote); + assert_eq!(proposal_info.status, ProposalStatus::WarmUp); + assert_eq!(proposal_info.vote_counts, [U128(0); 4]); + assert_eq!(proposal_info.session_id, 1); + assert_eq!(proposal_info.start_offset_sec, 1000); + assert_eq!(proposal_info.lasts_sec, 100000); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.last_proposal_id, 1); + + assert_eq!(view!(referendum_contract.get_proposal_ids_in_session(1)).unwrap_json::>(), [0]); +} + +#[test] +fn test_add_proposal_not_enough_lock_near(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 1, 1000, 100000), + deposit = 1 + ); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NOT_ENOUGH_LOCK_NEAR")); +} + +#[test] +fn test_add_proposal_refund(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let orig_user_balance = proposal_user.account().unwrap().amount; + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 1, 1000, 100000), + deposit = 20_000_000_000_000_000_000_000_000 + ).assert_success(); + assert!(orig_user_balance - proposal_user.account().unwrap().amount > to_yocto("10")); + assert!(orig_user_balance - proposal_user.account().unwrap().amount < to_yocto("10.11")); +} + +#[test] +fn test_add_proposal_start_time_lt_current_time(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 1, 7 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_PROPOSAL_START_TIME_NEED_GE_CURRENT_TIME")); +} + +#[test] +fn test_add_proposal_end_time_gt_next_session_begin_time(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 60 * 60, 30 * 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(get_error_count(&out_come), 1); + println!("{}", get_error_status(&out_come)); + assert!(get_error_status(&out_come).contains("ERR_PROPOSAL_END_TIME_NEED_LE_NEXT_SESSION_BEGIN_TIME")); +} + +#[test] +fn test_add_proposal_session_id_before_current_session(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 31 * 3600 * 24 * 1_000_000_000; + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_SESSION_ID_NEED_GE_CURRENT_SESSION_ID")); +} + +#[test] +fn test_remove_proposal_during_warm_up(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 1, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + let orig_user_balance = proposal_user.account().unwrap().amount; + assert!(call!( + proposal_user, + referendum_contract.remove_proposal(0) + ).unwrap_json::()); + assert!(proposal_user.account().unwrap().amount - orig_user_balance > to_yocto("9.99")); + assert!(proposal_user.account().unwrap().amount - orig_user_balance < to_yocto("10")); + + assert_eq!(None, view!(referendum_contract.get_proposal_info(0)).unwrap_json::>()); +} + +#[test] +fn test_remove_proposal_during_in_progress(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 60 * 60, 7 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp += 3600 * 24 * 1_000_000_000; + + let out_come = call!( + proposal_user, + referendum_contract.remove_proposal(0) + ); + assert!(!out_come.unwrap_json::()); +} + +#[test] +fn test_remove_proposal_no_proposal(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 60 * 60, 7 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + let out_come = call!( + proposal_user, + referendum_contract.remove_proposal(1) + ); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NO_PROPOSAL")); +} + +#[test] +fn test_remove_proposal_not_allow(){ + let (root, _, user, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 60 * 60, 7 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + let out_come = call!( + user, + referendum_contract.remove_proposal(0) + ); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NOT_ALLOW")); +} + +#[test] +fn test_redeem(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + let out_come = call!( + proposal_user, + referendum_contract.redeem_near_in_expired_proposal(0) + ); + + assert!(!out_come.unwrap_json::()); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 31 * 3600 * 24 * 1_000_000_000; + + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + proposal_user, + referendum_contract.redeem_near_in_expired_proposal(0) + ); + + assert!(out_come.unwrap_json::()); + assert!(proposal_user.account().unwrap().amount - orig_user_balance > to_yocto("9.99")); + assert!(proposal_user.account().unwrap().amount - orig_user_balance < to_yocto("10")); + + let proposal_info = view!(referendum_contract.get_proposal_info(0)).unwrap_json::(); + assert_eq!(proposal_info.status, ProposalStatus::Expired); + assert_eq!(proposal_info.lock_amount.0, 0); +} + +#[test] +fn test_redeem_no_proposal(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 31 * 3600 * 24 * 1_000_000_000; + + let out_come = call!( + proposal_user, + referendum_contract.redeem_near_in_expired_proposal(1) + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NO_PROPOSAL")); +} + +#[test] +fn test_redeem_not_allow(){ + let (root, _, user, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 31 * 3600 * 24 * 1_000_000_000; + + let out_come = call!( + user, + referendum_contract.redeem_near_in_expired_proposal(0) + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NOT_ALLOW")); +} + +#[test] +fn test_proposal_ids_in_session(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, _, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 1, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 0); + + assert_eq!(view!(referendum_contract.get_proposal_ids_in_session(1)).unwrap_json::>(), [0]); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 1); + + assert_eq!(view!(referendum_contract.get_proposal_ids_in_session(0)).unwrap_json::>(), [1]); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 1, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 2); + + assert_eq!(view!(referendum_contract.get_proposal_ids_in_session(1)).unwrap_json::>(), [0,2]); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 10, 1000, 100000), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 3); + + assert_eq!(view!(referendum_contract.get_proposal_ids_in_session(10)).unwrap_json::>(), [3]); + + assert!(call!( + proposal_user, + referendum_contract.remove_proposal(2) + ).unwrap_json::()); + + assert_eq!(view!(referendum_contract.get_proposal_ids_in_session(1)).unwrap_json::>(), [0]); + +} \ No newline at end of file diff --git a/referendum/tests/test_storage.rs b/referendum/tests/test_storage.rs new file mode 100644 index 0000000..a8a62a9 --- /dev/null +++ b/referendum/tests/test_storage.rs @@ -0,0 +1,150 @@ +use near_sdk_sim::{call, view, to_yocto}; +mod common; +use crate::common::{ + init::*, + utils::* +}; + +#[test] +fn test_storage_deposit_not_launched(){ + let (_, _, user, _, referendum_contract) = + init_env(false); + + let out_come = call!(user, referendum_contract.storage_deposit(None, None), deposit = to_yocto("1")); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NOT_LAUNCHED")); +} + +#[test] +fn test_storage_deposit_normal(){ + let (root, owner, user, _, referendum_contract) = + init_env(false); + + let current_timestamp = root.borrow_runtime().current_block().block_timestamp; + call!( + owner, + referendum_contract.modify_genesis_timestamp(nano_to_sec(current_timestamp) + 10) + ) + .assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(nano_to_sec(current_timestamp) + 10); + + let orig_user_balance = user.account().unwrap().amount; + call!(user, referendum_contract.storage_deposit(None, None), deposit = to_yocto("0.01")).assert_success(); + assert!(orig_user_balance - user.account().unwrap().amount > to_yocto("0.01")); + assert!(orig_user_balance - user.account().unwrap().amount < to_yocto("0.011")); +} + +#[test] +fn test_storage_deposit_repeat(){ + let (root, owner, user, _, referendum_contract) = + init_env(false); + + let current_timestamp = root.borrow_runtime().current_block().block_timestamp; + call!( + owner, + referendum_contract.modify_genesis_timestamp(nano_to_sec(current_timestamp) + 10) + ) + .assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(nano_to_sec(current_timestamp) + 10); + + let orig_user_balance = user.account().unwrap().amount; + call!(user, referendum_contract.storage_deposit(None, None), deposit = to_yocto("0.01")).assert_success(); + assert!(orig_user_balance - user.account().unwrap().amount > to_yocto("0.01")); + assert!(orig_user_balance - user.account().unwrap().amount < to_yocto("0.011")); + + let orig_user_balance = user.account().unwrap().amount; + call!(user, referendum_contract.storage_deposit(None, None), deposit = to_yocto("0.01")).assert_success(); + assert!(orig_user_balance - user.account().unwrap().amount < to_yocto("0.001")); +} + +#[test] +fn test_storage_deposit_refund(){ + let (root, owner, user, _, referendum_contract) = + init_env(false); + + let current_timestamp = root.borrow_runtime().current_block().block_timestamp; + call!( + owner, + referendum_contract.modify_genesis_timestamp(nano_to_sec(current_timestamp) + 10) + ) + .assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(nano_to_sec(current_timestamp) + 10); + + let orig_user_balance = user.account().unwrap().amount; + call!(user, referendum_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + assert!(orig_user_balance - user.account().unwrap().amount > to_yocto("0.01")); + assert!(orig_user_balance - user.account().unwrap().amount < to_yocto("0.011")); +} + +#[test] +fn test_storage_unregister_normal(){ + let (root, _, user, xref_contract, referendum_contract) = + init_env(true); + + let orig_user_balance = user.account().unwrap().amount; + call!(user, referendum_contract.storage_unregister(None), deposit = 1).assert_success(); + assert!(user.account().unwrap().amount - orig_user_balance > to_yocto("0.009")); + assert!(user.account().unwrap().amount - orig_user_balance < to_yocto("0.01")); + + call!(user, referendum_contract.storage_deposit(None, None), deposit = to_yocto("1")).assert_success(); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 31 * 3600 * 24 * 1_000_000_000; + + call!( + user, + referendum_contract.withdraw(), + deposit = 1 + ).assert_success(); + + call!(user, referendum_contract.storage_unregister(None), deposit = 1).assert_success(); +} + +#[test] +fn test_storage_unregister_repeat(){ + let (_, _, user, _, referendum_contract) = + init_env(true); + + let orig_user_balance = user.account().unwrap().amount; + call!(user, referendum_contract.storage_unregister(None), deposit = 1).assert_success(); + assert!(user.account().unwrap().amount - orig_user_balance > to_yocto("0.009")); + assert!(user.account().unwrap().amount - orig_user_balance < to_yocto("0.01")); + + let orig_user_balance = user.account().unwrap().amount; + call!(user, referendum_contract.storage_unregister(None), deposit = 1).assert_success(); + assert!(orig_user_balance - user.account().unwrap().amount < to_yocto("0.001")); +} + +#[test] +fn test_storage_unregister_before_unlock(){ + let (_, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let out_come = call!(user, referendum_contract.storage_unregister(None), deposit = 1); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_ACCOUNT_NOT_UNLOCK")); +} + +#[test] +fn storage_withdraw(){ + let (_, _, user, _, referendum_contract) = + init_env(true); + + let out_come = call!(user, referendum_contract.storage_withdraw(None), deposit = 1); + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NO_STORAGE_CAN_WITHDRAW")); +} \ No newline at end of file diff --git a/referendum/tests/test_unlock.rs b/referendum/tests/test_unlock.rs new file mode 100644 index 0000000..4f1bced --- /dev/null +++ b/referendum/tests/test_unlock.rs @@ -0,0 +1,114 @@ +use near_sdk_sim::{call, view, to_yocto}; +use near_sdk::json_types::U128; +mod common; +use crate::common::{ + init::*, + utils::* +}; + +#[test] +fn test_unlock(){ + let (root, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 0); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("10")); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("10")); + assert_eq!(account_info.ballot_amount.0, to_yocto("10")); + assert_eq!(account_info.unlocking_session_id, 1); + + let session_state = view!(referendum_contract.get_session_state(0)).unwrap_json::(); + assert_eq!(session_state.session_id, 0); + assert_eq!(session_state.expire_amount.0, to_yocto("10")); + + assert_eq!(view!(xref_contract.ft_balance_of(user.valid_account_id())).unwrap_json::().0, to_yocto("90")); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 31 * 3600 * 24 * 1_000_000_000; + + call!( + user, + referendum_contract.withdraw(), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 1); + assert_eq!(contract_metadata.cur_total_ballot.0, 0); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, 0); + assert_eq!(account_info.ballot_amount.0, 0); + assert_eq!(account_info.unlocking_session_id, 1); + + let session_state = view!(referendum_contract.get_session_state(0)).unwrap_json::(); + assert_eq!(session_state.session_id, 24); + assert_eq!(session_state.expire_amount.0, 0); + + assert_eq!(view!(xref_contract.ft_balance_of(user.valid_account_id())).unwrap_json::().0, to_yocto("100")); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 1); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("29")); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("30")); + assert_eq!(account_info.ballot_amount.0, to_yocto("29")); + assert_eq!(account_info.unlocking_session_id, 2); + + let session_state = view!(referendum_contract.get_session_state(1)).unwrap_json::(); + assert_eq!(session_state.session_id, 1); + assert_eq!(session_state.expire_amount.0, to_yocto("29")); + + assert_eq!(view!(xref_contract.ft_balance_of(user.valid_account_id())).unwrap_json::().0, to_yocto("70")); +} + +#[test] +fn test_unlock_ahead(){ + let (_, _, user, xref_contract, referendum_contract) = + init_env(true); + + call!( + user, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_session_id, 0); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("10")); + + let account_info = view!(referendum_contract.get_account_info(user.valid_account_id())).unwrap_json::(); + assert_eq!(account_info.locking_amount.0, to_yocto("10")); + assert_eq!(account_info.ballot_amount.0, to_yocto("10")); + assert_eq!(account_info.unlocking_session_id, 1); + + let session_state = view!(referendum_contract.get_session_state(0)).unwrap_json::(); + assert_eq!(session_state.session_id, 0); + assert_eq!(session_state.expire_amount.0, to_yocto("10")); + + assert_eq!(view!(xref_contract.ft_balance_of(user.valid_account_id())).unwrap_json::().0, to_yocto("90")); + + let out_come = call!( + user, + referendum_contract.withdraw(), + deposit = 1 + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NOTHING_CAN_BE_WITHDRAW")); +} \ No newline at end of file diff --git a/referendum/tests/test_vote.rs b/referendum/tests/test_vote.rs new file mode 100644 index 0000000..62b08f0 --- /dev/null +++ b/referendum/tests/test_vote.rs @@ -0,0 +1,476 @@ +use near_sdk_sim::{call, view, to_yocto}; +use near_sdk::borsh::BorshSerialize; +use near_sdk::json_types::U128; +mod common; +use crate::common::{ + init::*, + utils::* +}; + +#[test] +fn test_vote(){ + let (root, owner, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, vote_user1, vote_user2) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let vote_policy1 = VotePolicy::Relative(Rational{numerator:1, denominator:2}, Rational{numerator:1, denominator:2}); + let vote_policy2 = VotePolicy::Absolute(Rational{numerator:1, denominator:2}, Rational{numerator:2, denominator:2}); + + let remove_rational = Rational{numerator:2, denominator:2}; + + call!( + owner, + referendum_contract.modify_vote_policy(vote_policy1.try_to_vec().unwrap().into()) + ).assert_success(); + + call!( + owner, + referendum_contract.modify_vote_policy(vote_policy2.try_to_vec().unwrap().into()) + ).assert_success(); + + call!( + owner, + referendum_contract.modify_nonsense_threshold(remove_rational.try_to_vec().unwrap().into()) + ).assert_success(); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal1".to_string(), "vote".into(), 0.into(), 0, 24 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 0); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal2".to_string(), "vote".into(), 1.into(), 0, 24 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 1); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal3".to_string(), "vote".into(), 0.into(), 0, 24 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 2); + + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + call!( + vote_user2, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("60")); + + //proposal begin + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 1 * 3600 * 24 * 1_000_000_000; + + //vote_user1 vote approve to proposal 0 + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(0, "approve".into(), Some("approve".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, to_yocto("10")); + + let proposal_info = view!(referendum_contract.get_proposal_info(0)).unwrap_json::(); + + assert_eq!(proposal_info.status, ProposalStatus::Approved); + assert_eq!(proposal_info.lock_amount.0, 0); + assert_eq!(proposal_info.vote_counts, [U128(to_yocto("30")), U128(0), U128(0), U128(to_yocto("60"))]); + + //vote_user1 vote reject to proposal 1 + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(1, "reject".into(), Some("reject".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, 0); + + let proposal_info = view!(referendum_contract.get_proposal_info(1)).unwrap_json::(); + println!("{:?}", proposal_info); + + assert_eq!(proposal_info.status, ProposalStatus::InProgress); + assert_eq!(proposal_info.lock_amount.0, to_yocto("10")); + assert_eq!(proposal_info.vote_counts, [U128(0), U128(to_yocto("30")), U128(0), U128(to_yocto("60"))]); + + //vote_user2 vote reject to proposal 1 + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + vote_user2, + referendum_contract.act_proposal(1, "reject".into(), Some("reject".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, to_yocto("10")); + + let proposal_info = view!(referendum_contract.get_proposal_info(1)).unwrap_json::(); + println!("{:?}", proposal_info); + + assert_eq!(proposal_info.status, ProposalStatus::Rejected); + assert_eq!(proposal_info.lock_amount.0, 0); + assert_eq!(proposal_info.vote_counts, [U128(0), U128(to_yocto("60")), U128(0), U128(to_yocto("60"))]); + + //vote_user1 vote remove to proposal 2 + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(2, "nonsense".into(), Some("nonsense".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + + let out_come = call!( + vote_user2, + referendum_contract.act_proposal(2, "nonsense".into(), Some("nonsense".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, 0); + + let proposal_info = view!(referendum_contract.get_proposal_info(2)).unwrap_json::(); + println!("{:?}", proposal_info); + assert_eq!(proposal_info.status, ProposalStatus::Nonsense); + assert_eq!(proposal_info.lock_amount.0, to_yocto("10")); + assert_eq!(proposal_info.vote_counts, [U128(0), U128(0), U128(to_yocto("60")), U128(to_yocto("60"))]); +} + +#[test] +fn test_vote_append(){ + let (root, owner, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, vote_user1, vote_user2) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let vote_policy1 = VotePolicy::Relative(Rational{numerator:1, denominator:2}, Rational{numerator:1, denominator:2}); + let vote_policy2 = VotePolicy::Absolute(Rational{numerator:1, denominator:2}, Rational{numerator:1, denominator:2}); + + call!( + owner, + referendum_contract.modify_vote_policy(vote_policy1.try_to_vec().unwrap().into()) + ).assert_success(); + + call!( + owner, + referendum_contract.modify_vote_policy(vote_policy2.try_to_vec().unwrap().into()) + ).assert_success(); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal1".to_string(), "vote".into(), 0.into(), 0, 20 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 0); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal2".to_string(), "vote".into(), 1.into(), 0, 20 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 1); + + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + call!( + vote_user2, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "2".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("90")); + + //proposal begin + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 3600 * 21 * 1_000_000_000; + + //vote_user1 vote approve to proposal 0 + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(0, "approve".into(), Some("approve".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, 0); + + let proposal_info = view!(referendum_contract.get_proposal_info(0)).unwrap_json::(); + + assert_eq!(proposal_info.status, ProposalStatus::InProgress); + assert_eq!(proposal_info.lock_amount.0, to_yocto("10")); + assert_eq!(proposal_info.vote_counts, [U128(to_yocto("30")), U128(0), U128(0), U128(to_yocto("90"))]); + + //vote_user1 append lock + let orig_user_balance = proposal_user.account().unwrap().amount; + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "".to_string()), + deposit = 1 + ).assert_success(); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, to_yocto("10")); + + let proposal_info = view!(referendum_contract.get_proposal_info(0)).unwrap_json::(); + + assert_eq!(proposal_info.status, ProposalStatus::Approved); + assert_eq!(proposal_info.lock_amount.0, 0); + assert_eq!(proposal_info.vote_counts, [U128(to_yocto("60")), U128(0), U128(0), U128(to_yocto("120"))]); + + //vote_user1 vote reject to proposal 1 + call!( + vote_user2, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("10").into(), None, "".to_string()), + deposit = 1 + ).assert_success(); + + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(1, "reject".into(), Some("reject".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("60")); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, 0); + + let proposal_info = view!(referendum_contract.get_proposal_info(1)).unwrap_json::(); + println!("{:?}", proposal_info); + + assert_eq!(proposal_info.status, ProposalStatus::InProgress); + assert_eq!(proposal_info.lock_amount.0, to_yocto("10")); + assert_eq!(proposal_info.vote_counts, [U128(0), U128(to_yocto("60")), U128(0), U128(to_yocto("140"))]); + + //vote_user1 vote_user1 append lock + let orig_user_balance = proposal_user.account().unwrap().amount; + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "".to_string()), + deposit = 1 + ).assert_success(); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, to_yocto("10")); + + let proposal_info = view!(referendum_contract.get_proposal_info(1)).unwrap_json::(); + println!("{:?}", proposal_info); + + assert_eq!(proposal_info.status, ProposalStatus::Rejected); + assert_eq!(proposal_info.lock_amount.0, 0); + assert_eq!(proposal_info.vote_counts, [U128(0), U128(to_yocto("90")), U128(0), U128(to_yocto("170"))]); +} + +#[test] +fn test_vote_append_mutli(){ + let (root, owner, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, vote_user1, vote_user2) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + let vote_policy1 = VotePolicy::Relative(Rational{numerator:1, denominator:2}, Rational{numerator:1, denominator:2}); + let vote_policy2 = VotePolicy::Absolute(Rational{numerator:1, denominator:2}, Rational{numerator:1, denominator:2}); + + call!( + owner, + referendum_contract.modify_vote_policy(vote_policy1.try_to_vec().unwrap().into()) + ).assert_success(); + + call!( + owner, + referendum_contract.modify_vote_policy(vote_policy2.try_to_vec().unwrap().into()) + ).assert_success(); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal1".to_string(), "vote".into(), 0.into(), 0, 20 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 0); + + let out_come = call!( + proposal_user, + referendum_contract.add_proposal("test proposal2".to_string(), "vote".into(), 1.into(), 0, 20 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ); + assert_eq!(out_come.unwrap_json::(), 1); + + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + call!( + vote_user2, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "2".to_string()), + deposit = 1 + ).assert_success(); + + let contract_metadata = view!(referendum_contract.contract_metadata()).unwrap_json::(); + assert_eq!(contract_metadata.cur_total_ballot.0, to_yocto("90")); + + //proposal begin + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 3600 * 21 * 1_000_000_000; + assert_eq!(view!(referendum_contract.get_proposal_ids_in_session(0)).unwrap_json::>(), [0,1]); + + //vote_user1 vote approve to proposal 0 + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(0, "approve".into(), Some("approve".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, 0); + + let proposal_info = view!(referendum_contract.get_proposal_info(0)).unwrap_json::(); + + assert_eq!(proposal_info.status, ProposalStatus::InProgress); + assert_eq!(proposal_info.lock_amount.0, to_yocto("10")); + assert_eq!(proposal_info.vote_counts, [U128(to_yocto("30")), U128(0), U128(0), U128(to_yocto("90"))]); + + //vote_user1 vote reject to proposal 1 + let orig_user_balance = proposal_user.account().unwrap().amount; + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(1, "reject".into(), Some("reject".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, 0); + + let proposal_info = view!(referendum_contract.get_proposal_info(1)).unwrap_json::(); + println!("{:?}", proposal_info); + + assert_eq!(proposal_info.status, ProposalStatus::InProgress); + assert_eq!(proposal_info.lock_amount.0, to_yocto("10")); + assert_eq!(proposal_info.vote_counts, [U128(0), U128(to_yocto("30")), U128(0), U128(to_yocto("90"))]); + + //vote_user1 append lock + let orig_user_balance = proposal_user.account().unwrap().amount; + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "".to_string()), + deposit = 1 + ).assert_success(); + assert_eq!(proposal_user.account().unwrap().amount - orig_user_balance, to_yocto("20")); + + let proposal_info = view!(referendum_contract.get_proposal_info(0)).unwrap_json::(); + println!("{:?}", proposal_info); + assert_eq!(proposal_info.status, ProposalStatus::Approved); + assert_eq!(proposal_info.lock_amount.0, 0); + assert_eq!(proposal_info.vote_counts, [U128(to_yocto("60")), U128(0), U128(0), U128(to_yocto("120"))]); + + let proposal_info = view!(referendum_contract.get_proposal_info(1)).unwrap_json::(); + println!("{:?}", proposal_info); + assert_eq!(proposal_info.status, ProposalStatus::Rejected); + assert_eq!(proposal_info.lock_amount.0, 0); + assert_eq!(proposal_info.vote_counts, [U128(0), U128(to_yocto("60")), U128(0), U128(to_yocto("120"))]); +} + +#[test] +fn test_vote_no_proposal(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, vote_user1, _) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 24 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(1, "approve".into(), Some("approve".to_string())) + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_NO_PROPOSAL")); +} + +#[test] +fn test_vote_not_votable(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, vote_user1, vote_user2) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 24 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + call!( + vote_user2, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "5".to_string()), + deposit = 1 + ).assert_success(); + + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(0, "approve".into(), Some("approve".to_string())) + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_PROPOSAL_NOT_VOTABLE")); +} + +#[test] +fn test_vote_already_vote(){ + let (root, _, _, xref_contract, referendum_contract) = + init_env(true); + + let (proposal_user, vote_user1, vote_user2) = init_proposal_users(&root, &xref_contract, &referendum_contract); + + + + call!( + proposal_user, + referendum_contract.add_proposal("test proposal".to_string(), "vote".into(), 0.into(), 0, 24 * 60 * 60, 24 * 60 * 60), + deposit = 10_000_000_000_000_000_000_000_000 + ).assert_success(); + + call!( + vote_user1, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "1".to_string()), + deposit = 1 + ).assert_success(); + + call!( + vote_user2, + xref_contract.ft_transfer_call(referendum_contract.valid_account_id(), to_yocto("30").into(), None, "5".to_string()), + deposit = 1 + ).assert_success(); + + root.borrow_runtime_mut().cur_block.block_timestamp = sec_to_nano(view!(referendum_contract.contract_metadata()).unwrap_json::().genesis_timestamp_sec) + 1 * 3600 * 24 * 1_000_000_000; + + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(0, "approve".into(), Some("approve".to_string())) + ); + assert_eq!(out_come.unwrap_json::().0, to_yocto("30")); + + let out_come = call!( + vote_user1, + referendum_contract.act_proposal(0, "approve".into(), Some("approve".to_string())) + ); + + assert_eq!(get_error_count(&out_come), 1); + assert!(get_error_status(&out_come).contains("ERR_ALREADY_VOTED")); +} \ No newline at end of file From 58e7605ab6b1a68ddf56bbf712cd7ba46393260e Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 3 Jan 2022 12:29:01 +0800 Subject: [PATCH 6/7] release referendum 1.0.0 --- referendum/build_release.sh | 7 +++++++ res/referendum_release.wasm | Bin 0 -> 286079 bytes 2 files changed, 7 insertions(+) create mode 100644 referendum/build_release.sh create mode 100755 res/referendum_release.wasm diff --git a/referendum/build_release.sh b/referendum/build_release.sh new file mode 100644 index 0000000..b79859f --- /dev/null +++ b/referendum/build_release.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e +rustup target add wasm32-unknown-unknown +RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release +cd .. +cp target/wasm32-unknown-unknown/release/referendum.wasm ./res/referendum_release.wasm +cd - \ No newline at end of file diff --git a/res/referendum_release.wasm b/res/referendum_release.wasm new file mode 100755 index 0000000000000000000000000000000000000000..29c2bf9b3f80a0ea24cfc18474f63542a6d4cec8 GIT binary patch literal 286079 zcmeFa3!Gk6c`v*#?|$#^%nl?r3WYsyLNl?UO?!|;%Q?-SiqdLZ+uHN-JKuLsh%g$4 zkU$cUem_4lkO9I?5mBO|4Hk_k2r6w+Q3pjuOEFwjRJ2h6QLZW~YJ~6qf1b70-uu1G zOs<4B8JKzBwb$*rKkHe~TH9N(?o{9NJpbC#aVL2Gh7*DfXL~1v8_qu4Kl_9d{@`1c zfB4Tk!QbGWP}Z+_&T1^f$4Cl2ZG!K0+lDpJCyIg%8>D}95pK}W(wxtH)bj8*lu&`Q2)Lq5|!F#?}z0s6%QGYj-Wq)5LUkHw~*PN2p= z@(-Qlkcn@c3Yu^T_NY?@lxGvlQ07v_Z+6HD;WuY@Hrt?_UpZY=_fDv|YVt`Q01d9R zwBb#H26Q5S*}K0XxU#l599?~8YwhTYla{X?eZ$G?){n0BVwN@S*X655S9`NqbkK=s ztX(_0dj0YhC!VWYH>@6AJ8k)Cr)d2boVIrKq|p;c*R5OA-6%SF z^=W6U*NTnTty**9Da%h@ebVSz-oYGdP)pXIeCp`B^(#(2O-q}jr>!}0CNf=|@ z$#!CZ;ItJdpS1i9E7ob>)ic(ilKa|NyJGc8YffFhZgkWjsl0CGia&nI(cWx=Q9EVy z#1mJX()s-*fAq)tym{t|RcDNXBe^`Fvn$_#qqOoG6-LvZJ z&sc4GU$JVH_act|yFDwSr`79TZ<+f=J?ns>P8szMVJAoStgzywla`+{`VY(Bc=Gy{ z%U^%Ss#SyrT&!*Wa3*c?(>;_U9p1CmNu#Sq*N<{Ag}ygRO)bN}T62!=Z|&&1Gghr% z2Q)%dl}8;L=rg5ou27gwB-%;O8`qu;e)(O_v}q-Z+QJh`4`fBBt~qm53kPlC$`$Jb z0^ycHaP-M1t$jQ`3-vIs{9wh_Gz+u(m|F$gq zdsvlq2BLxLK*ay#58C4ci|}h`usYO^+Q~q>U9DEz?KTQqQG(x5G_S?+eEds%e*i!7 zFPh()mmJY*9g!rhsI?paYG@nH0jh!THh$v|{t?f_zYswRB2uV2&}LDKC4lJg1^ijCpfxav|5ykp zlLh?2XFN!f-(NJ4ELwyIM}lrqd455BL>^VI`_mD)WwB5(ITWELCc?Mi^EDzg({ep`U2e zRuWa)1FgX-5Wckf(wA1Fm%cPvIcfD$BL-U_1_lSgT!X+0NP>S02HWkHa44nl|-N0<&CgE7!A{te>)7boBsohy-q>CKxZ5(ai;E0PTVlE?#$_%KL$ zN?IT%DTelQFd}P4E5M_u1?B^t+Am&EZ2=1`z_|0!qP5_#)+_n9_-_#ZYNd*Q zntye0br6NVH>>=@aD$(Yk577y4PJWVQ@3V+D?cwCUOsj7)HQ4WA@C|^oc4ybD^42q zeo?B@2A;Hb#T&hgq8FS9Cu1b@GY-;Jq`doO&_liR-iPACH_3v|i&U zqu827hq+Hh2idYSR$F)5yCr&oEj6C#^49^kg!UBMMiKzR|n9TwlJNvt16dhJIr?{Pz{7!Tnx08V0p5m3%Mt8(V_w zYnN9ym(K}4RKKxyXXz)^JL@-w8-x4&bAxaC?+>;I{}H^i`hnmlwJZF4svinIR{vn| z(fUV%C+Z&!epq{7@Z0*wg7X^J2S2Uf6x>?5I`~NKAA_&>?+qUCHwEAIFAQ$;&kw%k zUl82wUl+W!dTH=u|El0~{=0(v{VRee{fmM-{kH^9`|k<1`xC+U{kH{=`tJ_z_1_-c z;cp4P=wA{%2Am7i6gth~2!N#)|og_U1ac2s^_d8Tqx^17>e~Bi@2_23`(W*w z+EumB);?MLRPC19Cu+CWCTqW`KUBM~_N&^rYd@%culD`gcWRH;eq4K`_Kn)TwQtrQ zsC~EgOzqj)c>SFEJ+-@Q=hipYzh3)V?ZWz{^^5A4)Gw%?U*A-}vi`62Pt|X!f2RJ~ z`bX*y)_+{zT)(ltv2kntuKL~e@y0#%d+T4TpVN4zes1I0di|T%41T-*w|=l8SQacx z{NW&O2mCYp&s$#V4TVj=k@!iF`eR22F+au6ZWfnO*A>VfNUNl*gud=d}e z6tyTbL;|WDS{nZz1f>kOi}Scm#xVG|h)Is9VFo3;mtvsw zMe#+#%4`WvCLU3x)C`C}32FSr=PzKFwOC=66>9PRrXGVKvsjer_K{B=?t zHN*H8%2^U-vTc3 zR?!W>*6fJY($d;?j}8+wzv_H6Z~MTjmzKubKG>1Wj9D9I);^>!J0IwS_+bJ>2?QR7 zgQEoH!n%1TR<+HUXno47ZOhM-p5^VCVevDaSbRqgi`xoVT-pzdOEIpXWod@Ur9@M8 zEIy|bmrE@!hYc>#t-+;`1i%~O3~LX)&Qg%TT}mZh?{SC%>%FbjtxdI0qVhEB-ylehytBG@@b@frvMZ0`jO;()Es{%+&Dqo zJu|NPTqoD;Ac&y_u_%2iG`)odD7G-lM~KgF*tY_#(wA6{K}U1PKw`l!zQpnc+GSxl zJQQ_Eo-uQ@WlKUbOFWj8^b_q6KV_2Rq;CEcY|>xUX2u)0_2P~9`yrhrr|@=#JHQ9O zR=!Y*6M0FnwFN9X7NPCW@qsrKkVV2S_CR4bd(4zAzSzkYdsvw~(#ab8tulF(GbO|9 zjxxEOopdUbJ;X3ivG2A~5ziUJe1)^f+wiXierRp~_JZ|+VWW}hp+>;#Ks25^D~`|5 z22Zo|ydqgvP$cwb*-EX?T&sYCR5S~m7M}`+UIH}*3eD)Y$XKbQL+|vq_*6qy!;2;| zmWtrm-ktHX_S|WumrtRUq;+p!VEaxQuRHc4zdg2J@Y|i8{PwW`i)rI)&fMDp&O2P4 z_?b>-bE-+%iOgm_ow&ejyTewnX&GD1gp;OmgD}_9+W1+*(rN87PiST?!nRISf6LEA zyJO)BA%HaY5N!yT^0)QRxvq?V*@rmikdApFIDx z)b8q~`#O>Pcwu!`T)OBQwTEKTwJG!m7LHao4VxwJ4?B@OZ2b;&r)w4{sfFQUDk-SG zyq?ksfh<D+=vQ@914z9$?VU3AWHh4-yaH0?26wWAX~|A}?g{e*Qd z>8f9`@8?`seYcZOZprDYo$%n*4+fVyal&U6kDqojjPv6~o{D~a&SlSpx5H(habSt= zRnbwGKAod(7k5q~r*YJwEPh5{I)yWH)Mw^MZ0|(+{kdh+lZ9o|?Vek>*jS@kxEv?g z#V=HGNXKVI`Y$?>eq2t8&85304by}%7+oSMHGK0xA~o)T_@1xPO$bt_!56vcVOak`M1$g?}x6QYx+Mjs4)GZW!zgM5%mBKl09_Y}n4U02+tXJ!A z_bU8eufj)q6@Ehs3zNLByXgL2O~2Kv@SEL@ALv!@2U6IZ3>_4Ev{(D@Na54;pxuUl z;`TQjkCVg$q32`kF!6prti~I;DZd?HL`A` zdc0|CyTUx5b~$Y`N2Qz|`3iVq<@DR$D_SAyl+%asi4Pvf-$+WHG9|xZNm5B)GbX7* z^*?VhbYAZl6VFT8^QbwHdmi6U&TOMy zso8Sn{BR)=#s@*O0s98l^-oW#@kK1Q;{%_yq%u?$$K6fog5s1~L=-X>{L>YeG{5o1 z(v5$lSCw)orX#)DP_=;`%iK|mWDBm`tTaHcat_lqkdZo>8-E zNJOHLI7EDqUL=zqPOlL0c&}z{SOQ}@Ag*cm9Ye6+n)Zu8TQEZ+{esl5Y*ndn_3Ll& zwc_wf^_zk23Fxy3x(^&ijRdd&NfnD;Ko1sx%86BjBgc%iFR~%1X_3`Z^!cEd_T=d- zz>mFwoyY?VJcdAjDK~Q@4i&@#naf5f7-r^lI%fks_-Vz>xY}#RWzKkfd`D#?esA*s zwiQ@_@z?MpM4>n|#m5d#4D=eDe3I+>VRW6bDxd=vIlXd^c_T~AVo`SX;~sT#YzfW- zqZX7}xzVINdhur{QH_U@%nyy^c17YYbB?)s@tZ};Od^6|)nKFwO%jS4So}%>;r$}r z!H7?V1SZ;=R?p07ilB+Pgy~Zrb|6^88Gv|?Y#b3o2mzSUp1%BUi0r0G$@MdCuT zAvU-*70frvE^Gonwu0ctRk&KTVJ=aESQgN7a|R5ywLH}MQ&X1GKY&6+{Zje`$`#Pc z?4}1HHuOZ|ONk#%$n@e%^b04LOK@C@bfp9=5nm`~8ctGGvM+t{hT$?LAvDg*JX&9W zjENig#Qdl~%_V?J-jzrh)(ac3E=L7P%R}QMJ#R=;JzwVeXdI;8E74u!9-QXL=Nx1t zhA0KWGFq1;06b1x8;X>+wj)x+2ed&F<*9;fGONijTPCMiGL|gykxL5VCu@a29u(!} zAz2I*>Y|&ZL6tO{K~nk*J|(rxlozn+HO^7Kb%_)iP!_nt8JCp$M zE+{aacc6edt_Hv@B6mK00&o-EWBAjW9tH0YI?!tTsC>U)G{oFo*Il~j_D6dY_E@u%=I!IXju!m2$avD&|HLzbof$E&j5+2j-|7DWH*ZJOSY@&-H(gC zqpyCw1L^U3qWuiC#9k6^1=*=#knlQ0&@f^texDB1AjU{6yJ47=%u?k)Czf?>w%b@f zcaLHDU4?a3rWy?IS&MDVS%Rggc+lhmC{*DdV^KsQSlL#a;9P>D-8P~sX1mZshtz($ zBLi%Y&JOw{a4uk&()FXZgX>4w4(V~5_&RxmR_E?qcr+D=+!|75Y~?Q(50%e5KO4DXZ4Ml9H%*uuhCD&$9pPJ3ln25Xy7&ew=v%spMjA!Q>D2o5Dg)TpwK5MEX5xe#~?`kc0f_)>fYl}+O!zYvoM=2N8uJgBpD9ELl7!gR_YzHT=n#{$6vhF1c{ z4!%I=I{h+#)5XUG4@paDl=z3lA5l-m?o#3;gH1od2n)lQDf@wgwQ;SVrF?)d%v``) z+&$==j|3vJsW5k%8>BL)qk}`qO^J_h2=iSjiopl1P(g;pC+cgNzs;p3y08=_`?6f) zgsEh}iX+8hOP0pDewI8A3AAYQ<9Bf^)I=1jiP@k#VH{5XzKujw1g5%+s7J~-E8@X- znpdkYU5{hu(_n0~ELTZ+D3D4Hl@B{EY*t}WxsUdX19ujtj}N*$T07 zHC7@vF33&YnvuR5v=-`FHHVPNBIJnVzBA)JPHK#pSMf)Wy3EC=5;www`6+`XwY)W` zQ7l)YMoom`1b#}ldytA{_%MHL$PbpuN3cwdq2TymDGKd6l#YC75^bHWPvFUnI$29P zaI>N^t|f>HzFZ$TZH(m~CZ+=|Hod1iL<=oRKe%xc(tI<=(q=fA^pLQtjB2|2;RX7f zTXHwEMcOcD&g>je5l411jB%!mmxL!IX8L%}?K!EQl#>eLg+DT#A_)GlSWsW{B2no{ z8wzi{H>a6qYBfHuGlbZ~IDDgMIPR2ZjBn(u2IigKD-WPXY5qQW4&YU5GmS+VD;Tv% z83=@=%b}Z&;5eL8)Z;YN2M9XjnW%NAfDxC4sy8f)r4Dp+b1Z%MLSPzeoJkEi&ZCM9 z;_uNl$!wO{%ES}!dE+<_V`D_rdoL8V!a$*Dd+~b+6du!|pec+0ku@+h!w_4{XFnFL z(3s1bKG%v8D~UI=F;>UBWX2y7+;W%>r2oi1Af-OdA!da1znTe@kh2k=M`?3_Qfj>T z9XMvH5@WlU4L2sAiJNftjYgdx;|3q-1GBUpXU0?k4<7dCA4SjGtLSEbC z-04tym5g8l?eRycjncPHOyc(!6;J60FXFcko`>I7Isg@kn_ef4b5ub*(om(^hS&|G z4tPR9xg`e*OA@$U#2bErLi~ZM!UF(ynLlfy6EF;E!wrLt-m_nw8JNs5pk!e*hGOuq z!jt9qUO<4bO-NO=iO@lUjoc?b7|9=tpClq)lmOL|dH|A?U_OWu>)|#I_0TtjJH3ts zO@9|Gev>MX#Dho+ENz7zp-j^wqtiZWexA%n@7GW7x`EA`@i*DnKL0}Y{K zKMCK|MsWGHZ78s$^rj@b{!MN80I$W9;BOA04K!you>uOKP*&T|A()4zH&O4zM%9}2 z);Jvui4q5Y-gp7qdg2d5FC=5}%@P?o28xCQ$KR%gzyN-HzkKph-H(6F&)jUr=SOp& zf6mVhB&qD}|NerL-W*xa(o3(&ecpxu&%;#asB=@Ud=j6pQSU0PyLM){-SqD!F2=Ug#4q4hgiE*{jo_$ebNR&5@aH4eXz+Rt2#!p_;R`D$77 zWiXdAidZU)R)8KxvuXl&L%=^C8|Vpg@JCDxjzEyR z!jomilHPvNaI!AO=o3oi0g`xg?wWL`z4m z0AEicJ~UUx!7t_<$DdZ2!j!<|&9<fcN9iNOiVFls!X3{+5ZHI`8fv-)4l0o(y^%pb%c0G?PIf!(i}856lCG zgubB2W3B!!S~yaJ#pY5Mm}ffbjiaP?TGq>bqV(aNW=2g&_Pl9 zCZ3y#{)&6AlG}roGoGzF1z9!EJ{z8%KH#lJ%A3DFy@rz+`$NzB6OTL;rok8j6X9_b zh@`@6w92Tw>J)9((EwmRd+Rs;@Kv}~D};ikF9stnNo3BmzL~)c%V91!P$;G8u|JsT z54^v?=p}R*YGQVno{jv}Bvfz$grHH25JWn)j#f@&rzkXBTL zn(<;yXksnK%%#@iF(xpjb!e}4kT(9h6(;D-L>yF+fv`4IQ-EjpOaH3CvL$6%fbBzA zzr?7W+C(2yVmLk%7BMok&oLfYX=#)o(2bWC`pnD>{YUx}=$paTlG%FAgsp!|GcH@g zL#lSSyxh-UB9~VHppf_(+z_W<-Fe*_;>4-1H`UQ!XqT`&5FY^cjozc5-v4GY*5}V9 zHsBD*)ow||{4>47jWQ)(5A)h`(EM3HJP0(XiupK{612D*uJ8K+7A^J?qHM!CSjHa% zS=w=X9j9GNAC+l;QK#)LuG>LbZ%3Nvr7oR-Y3p}_iPWn90WUm*lw9m}BM|{J=lc;0 z*6AzgB%E;&on+=_^wL+RfYCx&RTEC1Lx=g{do4wvQZC6+mS@LGcpG6kI4=vOV~AhSXf_%wf*L3|ngI%nddBNmL#@|rBbgE;d)OdM8UP7abu+%Y&kb=@k0EH2kEF6nY?hbk{xF{^?v)-#(9zH=6 zRiUf#rv(29C@Lnbg2BOL)XvC|z+FMdX zzxHL`fP8D7nQrGduB4DUb*6jVN<&b9iIurFaMSSZpfl4ad$w_1+A&&bNy(V+q-BSi zlupusvWaEgYK&`mM8Xe-8i8E1NUs}{Apw;jjn4=0SmptaaWBpE zqtqDU+7G_Ejvolwhy~0>s7I4PbutuLQP6K}4A}^mVR9@{idP3J$HN#{S^#m;{;lg^*& z*ZE)c(j`J7AjXd$VLPCWxNS?0T*ln=#--9*EvY3#=^>(xX$d zX6maxlxQkrLB8^Y9~&?R8}VBepfCG{L^!9eHL7%rqDH4D7wjTrhCu++TzJ!-c+BvD z2^(DhlH!t&XT!J0pBU_n++&{o^Ww)ic{ehOpk~krYFn{JOldO+4P?#*UR7J*F!5?d zWagE~pa!T^xgVmAfGxwjP3uXi^Atf9mm!b1hDX?w%v*idjq8A=2by7bA2k?>zyg-zxABw`nuRgZ@dKFl17P*NpI zYw>pnN*}OsOLR!bNR>O|n*xDUcCpP&P(7|w=WKLr z!L1n@x2HsQ=pu3_gZ{|f;uE>Q$|H9RTs=iD9=b_o$h{7wSJ>F>6v%b)+nq(OY{WU_ zUV}Udi`>b;LipVP8CvfCgKdRtLS)wPp2-4rd(v&`K{7dqfOas@}+Qexj zCBr37Cq6u>R|UX3X6kl$J0^_s+v$l9zknx=cY`@ zM)iN@>ZOyhDV^KgT_oS2c)GX_thMu>D4ke4h)jXsX=yQ5{2PmJagGGrz&srvNF1x- zKg5+Vs(dk9L;7W|9-B0Lf;dodB({t$O57c zY@Law95@$!$n)kQtRr zo9`rw^$8m{gn5b#*~1O!sI7V!e^ zCyrPDoURuo#edZyaCI-1l`ouLvY@@gA_=L>&|MO~B$$tjHArT>Sb|EKPD#KMry*P; z`~t67qv9rnVt73GdQ|*h)W(`sW<@9`-Dcpo3O0`U zv8WV!lp@5C!4P|tsH;W2*&?sQ3yfIV2wjz3QfExvj5-4B?w<8z@ zm!z`#ceYO0>0kSu`WK8m*r|NcZ$bG|O&aB!omx3w+TORy?yKG1nP z-FqAuPE;>y_f@^y9oKxYz%?Bj3IYise8N}_FeoA>#yWthMa(Iy7-<}7x5!?}ZKTPY zgGNe!+X5b77J9Hft%GBGiiWhU(D?+OZb>3vW4`k6*;6kst-63r^XFql4o#T*+u^;W%(9 zrKgHGKNqqL?H*;&RwBL-q)hL9>m;8cP{~Y=cuBaFpXgrkd?G(C#izyi3*(}g6LB$d z&93nWEC_CBkdL#P9EqL;29yKWq~aQCx?Ev&MJ@K!*wW4pw3BC1z&^^)$B5Z~M0 zg;ue-`GcOFy#oa%z;~7|2^)_T#3FOogrvT?r9tkM(XEh?@pI+gt#fYL4J6$Acj+P!KKFjyxB2!lrXo0vP{5YV69y_4$6?}B(cOZc4N#vIz z6F@w9yQo7$z3jynghYw-O7F%P_AMREoNWOQ)9ig!a)&UTMHwu^W;G93hRu4OG7Y#T z+#<#C^~`+SCFtpd;n*jyd>~Ma@W5P~*FbXP6B85v?Pg}*#a}lu9q1-Lihn^ih_{J* zB~hIFWc$p=Q+WF~Nx5LPkm;gmhq2WaTt4r053qw^@p-`x7Y6y*N#5Tpe32lf70il9Ca0_)Ofa^Q(u>Uv$c^*M>Cz(qW9=<|TS>>b)@jhA&@6BUfpuig$ zFF`L*1?a6~yt0WaMD&V~#)RH2JJI;Ek5^yLlQm!d&9>YF`1t#l1tay^)CM` zOT6Rsz8<4t+?kH1#LSI`g09iXn%v|qL@eND?KU^f-A!&xMpJ|nN;PX23(&wAdH;E>+?Zk?~@1UJWt!YY3JZVe}pBPhWj zR+H(;BFM-kI#Y$&5HTRv;+YE$>Xw0#;zUo&K{{2CB{Kt(T@YkQFjJMh_}vEQCNrui z!Rn_N@g)ys4wT<`MdlypV=l`4l&Sb0F~b6l2vSMq8#Qc<0}^^i4lkJ(MjbXog@*i! z-P34Ko}FjH_c$iJjCWq{q)yuyW?0EXGu16lk4}=)sJh{Bce3GqU*to0&T=-e5`1S9bI;``huKJ=R=-8{HG#ozfD@w3~Vhvctplx-t8qgY=3p};ZN*D zC`i{9pS@3dtfL_=_wNMnI(dlun9_;vhquVX8Xj&cKAc9>7J&w$)tNPVqz4!974f^p zd;!fb^JJ$18CTbHp7Q>H^v-ic*p)xQlz-NfiXyA__3>8CLQ=ISVM6P1<8a1HJlYlr zS--nRU_rh3eVl|G71fJHF7VMT`{De(fwG6B>rw>m?WYfZf>SN)m~5DSTT1G=l6$12 znk)IYu9DApmE0mF6>T-c>5Bu9oBqszet!qhyq1MO3T+5z1=LS|lAxLi38*(oNgntD z7&DkO{FeBNj^U@Dvw8#Rx# zBshc2wn8ayO62+;j4%|?Q1 zrks=73A6sxTd!nC(OdvSuYvhb3Jtu5>G4I*7R$2JtZ`ijme2KjisF>l;@x!{`38EU zQ`>w?9#HeaUCY_~Y4nL6@)z>mMAtvQ`&|6CZypKsRyMP!G%u~Nh1bbSa|Y^!re4fG zi1h#$yP!WEM1yo+E^VCG<@Xm<61@g>>E#qWdituk6`%&YHa7SJTsn95enNq9v+w|Y zThq&~_n!Le8lUxpC`+Npn?_^k=`zd01-Amlj}yV1GqzQ9^368hBmgOqND0^x%b2nV z0(cq+K==!rv)&L6sVzh+J^jmVZQMtWM(iEe{ZSqBFa-**U_m=BXK+f*EMK_K9+`a_ zL}ow`M}fw%`6Y91{+$$XRQxVsfCG{Bfv6MM*sp9@?0Vzx8gI3 zb1T=6|Aj$HhG<@G4;Kyx$C-!_oIuWj{K*$;x%;}1nYtuQWajvV0Ht!D*&Vk09Y5?s zIqU^qC>Ve=!ir~Mm`FMT@B!MJ@i+~=*i!;&REnq$MJV2>P7!1^<=PD*rbM8E!C;x_flNgRtPZ3h9AI+ui!LYgo%KHg`|NbAh;PXMNpe3aOEv#x}i;) z1N?^thcGzU?n`|x}5ybV%06eO-uk<2Y!AT|V$%?k^7yE5tLP-$aXa%DQ$B74FCm=MK3tVN&^YzD`H zqcN_^M4=;=J0r#%1slhD5#nZ;3i!@XZ~q+lBdy0`nGR{3zmGViY&Zmel`#3=|Ajc@ zmM#wAo&3)|iyY(oXM@!O@H@HW7ym*osVbKs>^hEMt2hMd_r9EaatII21dRh~21nYd z-S&~1`AioR?RRR%1R|`OIlv+NmP01@e-61uB4cwcha50O`<6pK*To_Gr6IaqE|#hF zFhpiw!0^ujL!=JXzGb4@x|nFcGejofzpvHIfbns9nqaa z46qR0De}(&r~0{Ys_*P#qW#Vg{Xl}qk?~jdSr8eoyq9eT{QWQORB!9zko`l={C&}< zE-bx7%@{}cadDl?nInutmPmGji)`L}bifgQ4mYvx?&7ZfPX8QmgrC!G&U^QN4*9TV z8(Rx?VEnu9Ic(!&XoAm&Z?JfOjsoeypt!Z|i` zjzy13;O>tphkXl?*fs3`C3jJBM@onE&1Cr+UQ7jNqV#$WKYp7KL9dqN#rxyW$TV