Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Voting contract #6

Closed
wants to merge 2 commits into from
Closed

Voting contract #6

wants to merge 2 commits into from

Conversation

bowenwang1996
Copy link
Contributor

Initial version of voting contract that allows people to vote on the next network reset height. TODO: add more testing and finish exposing necessary host functions near/nearcore#2475


#[derive(BorshDeserialize, BorshSerialize)]
pub struct AccountVotes {
votes: HashMap<ProposalId, Balance>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to be Map otherwise it'll be too slow. Take a look at fungible-token example to see how to handle inner maps.

}
}

pub fn withdraw(&mut self, proposal_id: ProposalId, stake: Balance) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't need to withdraw. Just set use vote with stake = 0

pub struct Votes {
proposals: Map<ProposalId, Proposal>,
next_proposal_index: ProposalId,
proposed_heights: BTreeMap<BlockHeight, ProposalId>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need BTreeMap for proposals. It all can be done offline and later the contract can be notified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean. This is done so that it is easy to remove expired proposals.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest simplify this contract and don't keep things sorted internally. We can also don't need to automatically resolve proposals when the new vote arrives. Instead we can add a method resolve that takes a proposal ID. And it tries to resolve a given proposal. This way the contract internally doesn't have to garbage collect expired proposals, but instead rely on someone calling resolve on a given proposal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay sounds good.


#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Votes {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to restructure this contract per Proposal.
The contract should have a top-level map of proposals. When a proposal is resolved, you can remove all voting information, because it's now irrelevant from the Proposal. But you still have to keep the proposal.
When proposal expires, you can also remove voting information relevant to the expired proposal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "proposal is resolved"

#[derive(BorshDeserialize, BorshSerialize, Eq, PartialEq, Debug, Serialize)]
pub struct Proposal {
/// Proposed height to reset the network.
proposed_height: BlockHeight,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it's a generic contract, and not specific to network resets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I am slightly confused about that. Do we want to write a general contract that can be used for multiple things? Then we need to encode the actual object that is proposed in some way.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. We may want to include binary metadata: Vec<u8> field to every proposal, which will keep the required information in a serialized form.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evgenykuzyakov so you want to have one contract that simultaneous hold different types of votes. That seems a bit strange to me and I would like to have one contract per voting, i.e, there will be one contract deployed for network reset height, another one for unlocking.

@@ -0,0 +1,21 @@
MIT License
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, should we have one license file for the whole repo instead of per each project?
also you can use https://github.com/near/near-api-js/blob/master/LICENSE and https://github.com/near/near-api-js/blob/master/LICENSE-APACHE for dual licensing.


The purpose of this contract is for people to vote on the next reset height for the network that the
contract is deployed on. Anyone can submit a proposal but only stakeholders can vote. Once over 2/3 of total
stake in an epoch has voted on a proposal, the proposed height becomes final and the voting is closed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I thought we are going to do next thing:

  • Proposal are sent with date of unlock all the time, there is a window to vote for proposal is time to unlock - 2 weeks - 4 epochs
  • Validators vote for proposals as they see fit until voting is allowed: either yay or nay
  • Proposal voting locks for 4 epochs and at that point we evaluate who voted for it, and what is their stake. If 66% of total stake voted -> proceed on 2 week waiting period before unlocking.

Why 4 epochs? Because we want to allow delegates to switch their validators if they don't think the validator they are delegating right now represents them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need 2 week waiting period?

Are you commenting on upgradability or transfers vote?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this discussion to near/NEPs#62

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved there.

@evgenykuzyakov
Copy link
Collaborator

Other version is already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants