RepoVoter
This contract allows voting for changes in the configuration stored in the VariableRepo contract.
Variables
votings
Stores votings, their configuration and their votes.
other
variable_repo: Address,
reputation_token: Address
Entry points
init
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
)
Create voting
Creates a new voting.
Preconditions:
- the caller is eligible (it has an available Reputation > stake)
- the stake is equal or greater than
minimum_governance_reputation
value from the Variable Repo
fn 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
)
vote
Casts a vote. The vote (choice with its stake and voter address) is added to the votings list.
Preconditions:
- the voter is eligible (it has an available Reputation > stake)
- the stake is equal or greater than the
minimum_governance_reputation
value from the Variable Repo
- the voting is active - _finish_time has not passed for the respective voting
- if the vote is cast for a formal vote, additionally the result of the informal voting needs to be in favor
fn 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
)
finish_voting
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
Quorum is reached if the number of voters is greater or equal to quorum ratio multiplied by total number of eligible voters.
For example:
- total eligible voters: 10
- quorum ratio: 0.5
- voters: 5
In the example above the quorum is reached as 10*0.5 >= 5.
voting result calculation
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.
informal voting
Preconditions:
informal_voting_finish_time
is less or equal than the current block time
If the quorum defined in informal_voting_quorum
was not reached or the result of the voting was against following things happen:
- the stake of the creator of the vote is burned
- the stake of other voters is returned to them
If the voting result was in favor, following things happen:
- the stake of the creator is converted to the stake of the formal vote in favor
- the stake of the other voters is returned to them
formal voting
Preconditions:
formal_voting_finish_time
is less or equal than the current block time
If the quorum defined in informal_voting_quorum
was not reached:
- the stake of the creator of the voting is burned
- the stake of other voters is returned to them
If the voting result was against:
- the stake of the voters who voted in favor is redistributed between voters who voted against
If the voting result was in favor:
- the stake of the voters who voted against is redistributed between voters who voted in favor
- the
update_at
method in the Variable Repo is called
Repo Voter redistribution
The 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:
- Losing side staked: luser1: 50 tokens, luser2: 50 tokens. In total: 100 tokens.
- Winning side staked: user1: 50 tokens, user2: 50 tokens, user3: 100 tokens. In total: 200 tokens.
- user1 and user2 should both receive 50 tokens of their stake, plus 25% of the losing side's stake, totaling to 75 tokens each.
- user3 should receive 100 initial stake + 50% of the losing side's stake - 150 tokens.
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
)
Flow diagram
To better illustrate the flow of communication between contracts and users, see the following diagram: