The objective for the proposal pact is to enable users to
- Simply create an immutable announcement for a cause on the blockchain - that is verifiable through the account address
- Have a mechanism to vote
- Collect funds on to the pact for the aforementioned cause
- Disburse the funds at the end of voting, with pre-announced beneficiary accounts
Through the frontend, the user should be able to create the proposal pact. In order to do this the user has the option of going to “Create a proposal pact” and enter the values in the form.
Afterwards, the user is presented with a pre-flight check - containing all the values filled in from before, so they could have a final look before going for “Looks good - deploy”
THE DATA STRUCTURES
|Contract side||Accessor and local||Data|
Stores/gets the core pact information, apart from votingInfo
|For non-array data -
For voters and beneficiaries -
Stored in local in
Stores/gets the voting related info in a single struct
Stored locally in
Stores user-pact interaction related data
Stored locally within
Stores how much grant is available for a beneficiary to withdraw
|grants ( address )
||If A is a beneficiary of say 10 ETH, then after the vote is over, grants(A) = 10 ETH.
A then withdraws that, whence grants(A) becomes 0
- createPact - create a new pact with the information passed in.
- setText - as the creator, edit the pact text of an “editable” pact
- addVoters - add a set of voters to a non-open pact, before the voting starts
- pitchIn - add funds to the pact to be disbursed to beneficiaries
- withdrawContribution - withdraw funds added by your own address/account before the voting starts
- postponeVotingWindow - as the creator of the pact, postpone the voting window by 24 hours
- withdrawGrant - withdraw grants allocated to your account/address, as a beneficiary
- voteOnPact - submit a yes or no vote (corresponding to a true or false value) to the pact
- concludeVoting - as an allowed voter, initiate fund disbursement after the voting is complete
LOGIC AND RESTRICTIONS
- The voting period defines whether voting is active. This period starts when the current block’s timestamp is greater than
votingInfo.votingStartTimestampThe block timestamp is very close to the computer’s own timestamp, which is the current UTC unix time in seconds (not milliseconds)
- Enabling voting for a pact is optional, and this must be specified while creating a proposal pact. Without voting, the proposal pact is a mere micro-blog post on blockchain!
- The participation for voting can be open or fixed. In case of
votingInfo.openParticipation = truea user must contribute a minimum amount, to guard against spamming. In case of fixed voters, only a fixed set of voters specified during pact creation, or added later before voting window starts, can cast vote.
- While creating a pact,
votingInfo.minContributioncan be set. A user with contribution less than this won’t be allowed to cast vote.
- The active voting window lasts for
votingInfo.duration. Thus, eligible voters won’t be allowed to vote at timestamp higher than
votingStartTimestamp + duration.
- An eligible voter for openParticipation pact is anyone who has a contribution greater than
pactInfo.minContribution. This value will always be non-zero.
- For a pact with fixed set of voters, any address in the
pactData.votersis eligible to vote once, as long as their contribution is greater than or equal to
votingInfo.minContributionwhich in this case can be zero.
After the voting window is over, all of the pact’s value, stored in
pactData.totalValueis eligible to be transferred to the beneficiaries. The beneficiaries are specified either as fixed, or with the option of a refund.
If the number of yesVotes (vote sent with vote = true) > number of noVotes ( vote = false ) then the fund gets divided among all addresses in
yesBeneficiaries, or if the
refundOnVotedYes == truethen all contributors can get their money back using
noVotes >= yesVotesthen the totalValue gets divided to all addresses in
noBeneficiariesor the option to refund is activated if
refundOnVotedNo == true
concludeVote()method must be called by one of the eligible voters after the voting window is over for the totalValue of the pact to be added to the
grantsmap in the smart contract. This isn’t done automatically, or even at the last eligible person’s vote.
The following data is sent to the smart contract for creating a new pact
- votingInfo (the entire set),
- isEditable (true or false),
- pactText (combined title and description, with a ‘’ separator, if applicable)
- Arrays - voters, yesBeneficiaries, noBeneficiaries
- (optional) a value added to the transaction, that gets locked into the pact
The unique id (pactId) is calculated by the smart contract as a keccak256 hash of the following information:
address of the smart contract,
the string "chainpact_proposalpact",
pactsCounter (auto incrementing counter counting the number of pacts created thus far)
If votingInfo.votingEnabled is sent as false, the entire votingInfo object is ignored
If voting is enabled, the votingInfo related restrictions apply
For an openParticipation pact, this must be set higher than a fixed parameter -
config.minOpenContributionAmount. This value is present in the pact’s config parameters, and also ported to the frontend.
The duration must be higher the
config.minOpenParticipationVotingPeriodfor an openParticipation pact and higher than
minOpenParticipationVotingPeriod / 2for a fixed voters pact. The duration cannot be longer than
If voting is enabled, the yes and no-beneficiaries must be specified
votingInfo.refundOnVotedYes == falsethe
yesBeneficiariesshould be a non-empty array
votingInfo.refundOnVotedNo == falsethe
noBeneficiariesshould be a non-empty array
For it to be honoured, the
votingStartTimeStampcan specified greater than the (possible) timestamp of the block in which the transaction is included. Otherwise a
block.timestamp + 30*60is stored as the votingStartTimeStamp. This is to give eligible voters at least a 30 - minute grace window before the voting even begins.
- Pushes the votingStartTimestamp to 24 hours further, by adding 24*60*60 to it
- Can be performed by the creator before the voting starts, on a pact with voting enabled
- Voting shouldn’t have started yet, and voting should be enabled for the pactId
- Only the pactCreator is allowed to perform this on a pact that isn’t openParticipation
- Voters can be added even with pre-existing voters in the pact
- Can be used by anyone on any pact, as long as the voting is enabled and hasn’t been concluded on it
- Will revert if the voting isn’t active or the account has already voted (
- The account must either have
userInteractionData.canVote = trueor the pact should be openParticipation
- The account must have a contribution greater than
The voting must have started and ended that is:
block.timestamp > votingInfo.votingStartTimestamp + votingInfo.durationand voting is enabled
The account must have the same set of voting rights as mentioned earlier
This sets the
trueand thus cannot be called a second time
- Voting must not have started, and the amount being asked is less than or equal to their contribution amount