make-software / dao-contracts Goto Github PK
View Code? Open in Web Editor NEWSmart Contracts for the MVPR On-Chain Governance System on Casper
License: Apache License 2.0
Smart Contracts for the MVPR On-Chain Governance System on Casper
License: Apache License 2.0
This contract allows voting for changes in whitelists and change of the owner of the contracts that Admin Contract owns, that is:
The voting mechanism is the same as used in RepoVoter Contract #28 with the only difference being different actions are being executed.
Stores votings, their configuration and their votes.
votings: TBD
variable_repo: Address,
reputation_token: Address,
kyc_contract: Address,
Contracts: Enum(variable_repo, reputation_token, kyc_contract),
Actions: Enum(add_to_whitelist, remove_from_whitelist, change_owner)
Initializes the contract with addresses of ReputationToken, VariableRepo and KYC contracts
fn init(&mut self, variable_repo: Address, reputation_token: Address, kyc_contract: Address);
Creates a new voting. We pass as arguments which contract we want act on, an action and an address which will be a parameter for the action.
fn create_voting(
&mut self,
subject: Contracts,
action: Actions,
argument: Address,
stake: U256
)
Successful call emits an Event:
AdminVotingCreated(
subject: Contracts,
action: Actions,
argument: Address,
stake: U256,
creator: Address,
informal_voting_id: U256,
informal_voting_finish_time: U256,
informal_voting_quorum: U32,
formal_voting_id: U256,
formal_voting_finish_time: U256,
formal_voting_quorum: U32
)
Is the same as in RepoVoter Contract #28
Is the same as in RepoVoter Contract #28, with different actions being called in a subject contract.
Voting rewrite plan:
Originally posted by @zie1ony in #119 (comment)
Contract schemas files changed. JS generic client needs to be adjusted to use new format.
Changes:
casper-js-sdk
.Make sure tests are passing.
Extend Mapping to be able to accept other Mappings or even Modules like (OrderedCollection).
Change DocumentHash
from U256
to u32
.
Change VotingId
from U256
to u32
.
increment
to increase
.To fully implement contracts that use voting, we need a KYC Contract. But before its specification is cooked, we can use this skeleton with basic implementation for testing other contracts.
This method will return if the user owning a given address is eligible - has passed the KYC process.
fn has_kyc(&self, address: Address)
In the Skeleton, this method will always return true.
Use Code Review DAO as the scenario for setting up the whole DAO:
Right now we reuse dao_nft
for KYC and VA Tokens. When deploying as WASM to live network it deploys both tokens under the same name "dao_nft_contract_package_hash", which is problematic.
One of the solutions is actually having two very simmilar files kyc_nft.rs
and va_nft.rs
and corresponding bins and wasm files.
List of features requested by the DEVxDAO members, that when implemented, should produce a bid escrow process with expected features.
Reputation Token
Bid Escrow
Onbarding Voter should allow to stake CSPR and post proof by external worker.
Bidding process
Job handling
Mint new REP (job_price * conversion_rate) to additional pool.
For nonVA that doesn't want to become VA:
If nonVA worker wants to become VA:
If VA worker
Staking is used as a way of marking that tokens are used for voting in another contracts.
It should be implemented as:
struct TokenWithStaking {
stakes: Mapping<Address, U256>,
token: Token
}
Signature:
fn stake(&mut self, address: Address, amount: U256);
It should increase the stake in the stakes
mapping by the amount
.
If stakes.get(address) + amount > balance_of(address)
throw an error Error::StakingTooMuch
.
Only whitelisted addresses can execute stake
entry point.
Signature:
fn unstake(&mut self, address: Address, amount: U256);
It should decrease the stake in the stakes
mapping by the amount
.
If stakes.get(address) < amount
throw an error Error::UnstakingTooMuch
.
Only whitelisted addresses can execute unstake
entry point.
It should not be possible to burn staked tokens. They need to be unstaked first.
It should not be possible to transfer staked tokens. They need to be unstaked first.
The whole DAO has 13 contracts. In Rust tests we have a script to deploy all contract and set proper permissions. It is defined here: https://github.com/make-software/dao-contracts/blob/develop/dao-contracts/tests/common/mod.rs#L90
Using the generic client create a deployment script in JS, that is able to deploy contarcts to the given livenet.
This contract allows voting for changes in the configuration stored in the VariableRepo contract.
Stores votings, their configuration and their votes.
votings: TBD
variable_repo: Address,
reputation_token: Address
Initializes the contract with addresses of ReputationToken and VariableRepo.
fn init(&mut self, variable_repo: Address, reputation_token: Address);
It emits an Event after a successful call:
RepoVoterCreated(
repo_voter: Address,
variable_repo: Address,
reputation_token: Address
)
Creates a new voting.
Preconditions:
minimum_governance_reputation
value from the Variable Repofn create_voting(
&mut self,
variable_repo_to_edit: Address, // for the flexibility, we allow voting on other repos in the future
key: String, // which variable we update
value: Bytes, // value of the variable
activation_time: Option<U256> // when to activate
stake: U256 // initial stake for the vote
);
The created voting should have the configuration based on the Variable Repo configuration, stored in the contract's variable_repo
address. The amount of reputation defined in stake is staked by the voter in the first vote in favor. After a successful voting creation, an Event should be emitted containing the votings configuration:
RepoVotingCreated(
variable_repo_to_edit: Address,
key: String,
value: Bytes,
activation_time: Option<U256>
stake: U256,
creator: Address,
informal_voting_id: U256,
informal_voting_finish_time: U256, // calculated based on `informal_voting_time` + current block time
informal_voting_quorum: U32, // copy of the Variable Repo's value
formal_voting_id: U256,
formal_voting_finish_time: U256, // calculated based on `formal_voting_time` + current block time
formal_voting_quorum: U32 // copy of the Variable Repo's value
)
Casts a vote. The vote (choice with its stake and voter address) is added to the votings list.
Preconditions:
minimum_governance_reputation
value from the Variable Repofn vote(
&mut self,
voting_id: U256,
choice: bool,
stake: U256,
);
It emits an Event after a successful call:
VoteCast(
voter: Address,
voting_id: U256,
choice: bool,
stake: U256
)
Calculates and publishes the result of the voting. Depending on the type of voting, it performs different actions.
fn finish_voting(
&mut self,
voting_id: U256
)
Quorum is reached if the number of voters is greater or equal to quorum ratio multiplied by total number of eligible voters.
For example:
If the quorum was reached, the result of the voting is calculated by comparing the sum of the stakes in favor and against.
In the case of a tie, the result is in favor.
Preconditions:
informal_voting_finish_time
is less or equal than the current block timeIf the quorum defined in informal_voting_quorum
was not reached or the result of the voting was against following things happen:
If the voting result was in favor, following things happen:
Preconditions:
formal_voting_finish_time
is less or equal than the current block timeIf the quorum defined in informal_voting_quorum
was not reached:
If the voting result was against:
If the voting result was in favor:
update_at
method in the Variable Repo is calledThe redistribution process takes all the tokens staked by the losing side and transfers them to the winning side. The tokens should be divided in a ratio in which the winners voted. For example:
It emits the following events:
InformalVotingEnded( // after successful call on informal_voting_id
result: converted_to_formal | rejected | quorum_not_reached,
votes_count: U32,
for_stake: U256,
against_stake: U256,
informal_voting_id: U256
formal_voting_id: U256
)
FormalVotingEnded( // after successful call on formal_voting_id
result: passed | rejected | quorum_not_reached,
votes_count: U32,
for_stake: U256,
against_stake: U256,
informal_voting_id: U256
formal_voting_id: U256
)
To better illustrate the flow of communication between contracts and users, see the following diagram:
The Variable Repository Contract allows to store, modify and query the configuration. The configuration is stored as bytes.
values: Mapping<key: String, (value: Bytes, future: Option<(Bytes, U256)>)>
Stores the current value and optionally a value for a moment in the future.
Should work the same as in ReputationToken.
fn change_ownership(&mut self, owner: Address);
Should work the same as in ReputationToken.
fn add_to_whitelist(&mut self, address: Address);
Should work the same as in ReputationToken.
fn remove_from_whitelist(&mut self, address: Address);
It should store the value if doesn't exist or update if exists.
If the activation_time is passed and is greater than the current block time, the future
part of values
should be updated.
If the activation_time is passed and is less than the current block time, the future
part of values
should be set to None.
If no activation_time is passed, only the current value should be updated, the future
part of values
should be set to None.
Only whitelisted accounts should be able to call it.
fn update_at(&mut self, key: String, value: Bytes, activation_time: Option<U256>);
A successful call of this method should emit an Event:
ValueUpdated (
key: String,
value: Bytes,
activation_time: Option<U256>
)
It should provide a value or fail if the value doesn't exist.
If the future
portion of the value is equal or less than block time, the value from the future should be returned. Otherwise, the current value should be returned.
fn get(&self, key: String) -> Bytes;
During the creation of the contract, it should be initialized with a set of variables needed for other contracts. Those should be:
Parameter name | Parameter Value |
---|---|
default_policing_rate | 300 |
reputation_conversion_rate | 10 |
forum_kyc_required | True |
formal_voting_quorum | 500 |
informal_voting_quorum | 50 |
voting_quorum | 200 |
formal_voting_time | 432000000 |
informal_voting_time | 86400000 |
voting_time | 172800000 |
minimum_governance_reputation | 100 |
minimum_voting_reputation | 10 |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.