How Daox Works — Part 2
Managing DAO
In the previous part of this article the process of a DAO creation and the process of crowdsale were explained. This part explains what types of votings are presented in DAOs and how they work.
All code presented in this article is provided with .js extension only for correct highlight. The real extension is .sol
Votings
If the funds collected during the crowdsale equal or exceed the softCap
, then voting functions become accessible to the participants of a DAO. A separate contract called VotingFactory is in charge of creating various votings.
The address of the above-mentioned contract is set when the CrowdsaleDAO
contract is created. When attempting to create a particular voting with a function from a DAO, it delegates a call with all the transferred parameters to the VotingFactory
contract, which in turn creates a voting contract and returns its address back to the DAO.
All in all there are 4 types of voting in a DAO:
Regular
— voting that does not change the DAO’s current state in any way, whatever the result is, and serves only to let the participants of the DAO to decentrally voice their opinions on a question that is being discussed in voting.Withdrawal
— voting primarily required by the team members, which allows for receiving funds from the deposit established in a DAO during the crowdsale.Refund
— voting that allows members of a DAO to declare a project as failed for one reason or another, and to reimburse the funds from the DAO’s remaining amount, which will be distributed proportionally to the DAO token-holders.Module
— service voting, which allows for changing the address of one module for the address of another module where the mistake has been eliminated, in case an error or a bug is found in one of the functional modules linked to a DAO. This voting also allows for changing the address of the Voting factory contract, in case there are problems related to the votings that need to be fixed.
Before any voting is created the VotingFactory
checks that the voting was generated by the member of a DAO or member of a project team, namely by the holder of tokens that have been distributed in this particular DAO during the crowdsale. The VotingFactory
also checks that the function itself was called by the contract of the DAO, not by a random address. There are individual checks as well, but they will be described further on.
Each of 4 types of voting has its own contract with specific functionality, but common features are combined into a separate contract with basic voting functionality, that is called Voting
. Thus, when the functionality overlaps, all votings delegate the execution request to the Voting
contract.
Let us consider the basic Voting
contract, and then take a good look at each type of voting.
Voting
As seen from the code, the basic Voting
contract has a functionality to create votings, assign votes to one option or another and to complete the voting process. All modifiers that votings share in common are stored here as well. Let us have a look at how each function works, one-by-one.
create
— this function receives all the common parameters from the voting contracts and sets their value to storage variables. It checks that the duration of voting is indicated correctly and will allow participants to have enough time to get acquainted with voting procedures and take part in the voting itself.addVote
— this function gets information about an option that the participant wants to vote for from the voting contracts, and it also receives token balance of the participant, considers the participant as having voted and assigns value that is equal to the number of tokens hold by the participant to the selected option. After that, the tokens of the participant will be frozen until the end of voting. This is done so that after the voting the participant would not be able to transfer his tokens to another address, that could use these tokens one more time during the same voting. Before the function is performed, it checks that the voting is still in progress, that a person who is voting is not a team member, but a member of a DAO, that he has not voted yet and that he votes for the selected option.finish
— this function completes the voting and sums it up, having checked in advance that the completion time has come and the voting has not yet been completed. Then, votes for each option, as well as the total number of votes in reference to all possible options are being counted, upon which the results are calculated.
Regular
This is the simplest type of voting used to handle practical issues that do not result in affecting the DAO in anyway. It has from 2 to 10 user-defined options, and each person taking part in voting should choose one from those. In order to be created, this voting should have indicated name, description, duration in seconds, and array of options.
The code used to create this voting is given below:
When creating this type of voting, the number of transmitted options is checked, and if it is either less or more than the number of predefined options, then the creation process is being halted.
The addVote
function and finish
function do not have any additional code for this type of voting, and are entirely described in the Voting
contract. An option that got the most votes in tokens is regarded as an accepted one.
Withdrawal
This type of voting is designed to make requests for partial withdrawals of the raised proceeds from a DAO.
When creating this kind of voting, it is necessary to indicate name, description, duration, withdrawal amount, address that the funds would be transferred to and currency, that is, if the team members would like to get the funds in Ether or in DXCs.
If the currency for funds withdrawal is Ether, then the sum should be indicated in wei. Before the voting contract is created, the VotingFactory
checks whether the address given for funds withdrawal is on a list of accepted addresses, that was specified in the setWhiteList
function before the start of the crowdsale.
Options for this type of voting are generated automatically, and they are only: “yes” and “no”.
The code for this type of voting looks as follows:
Before the voting is created, it is checked that the withdrawal amount is more than zero and that there is sufficient amount of funds in the DAO.
The voting function addVote
of the Withdrawal
voting is entirely executed in the basic Voting
contract, while the function of voting completion has an additional code:
An option that has gained 50% + 1 token from all the tokens taking part in the voting will be regarded as an accepted one. In case if upon the completion of the voting, the “Yes” option got the most votes, the DAO, for which the voting was created, calls the withdrawal method, the implementation of which is in the VotingDecisions
module. Such parameters as the sum, currency of the withdrawal and the address which the funds should be transferred to, are passed to that function.
The implementation of the withdrawal method looks as follows:
Before the execution it is verified that the DAO is not in the refund phase at the moment, and that the call originated exactly from the voting contract. If the verification is successful, the date of the last withdrawal is set and the transfer takes place.
The date of the last withdrawal is used to prevent lock-up of the funds in a DAO. If the last withdrawal date was more than four months ago, a call to the function, that transfers a DAO to the state of refund to investors mode, becomes available. More details on that state is given below:
Refund
This voting makes it possible to activate the refund state for a DAO. Only a name, description and duration are needed to create this type of voting.
The code for creating this method is provided below:
The voting options are created in the same way as in the Withdrawal
. The addVote
function does not contain any additional code.
There is additional code in the ‘finish’ function:
Voting will be considered successful if the “Yes” option gets more than 90% of all the issued tokens (excluding team-members tokens).
That way, upon the completion of the DAO voting, the makeRefundableByVotingDecision
function is called form the voting creator, implementation of which is in the VotingDecisions
module.
The code of the function looks as follows:
The function checks that the call had been made from the voting contract, and then calls the makeRefundable
function. The function is implemented as follows:
A verification that the DAO has not been previously transferred to the refund stateis made, then, if the verification is passed, the transition to the corresponding state occurs and the rate for both currencies is recalculated in accordance with the remaining funds in the DAO.
When calculating the new rate, the multiplier variable is multiplied by 100,000. This is done in order to avoid having a fractional division result, which is interpreted as 0 in solidity. In subsequent functions, the result is divided by the same multiplier to bring the data to the correct values.
After transition to the refund phase, it becomes possible to call the refund function implemented in the Payment
module.
The function verifies that the DAO is in a refund state and that the refund request is not made by a team member. After that, the participant is refunded in accordance with Ethereum and DXC tokens, remaining on the balance of a DAO. The amount of the refund is calculated based on the amount of the participant’s tokens and a new rate.
Module
This is a special type of voting designed to upgrade the code of a DAO. This type of voting allows to change the address of one of four functional modules or the VotingFactory
.
To create this type of vote, one should pass such parameters as name, description, duration, sequence number of the module that is to be replaced and the address it will be replaced to.
The voting is created using the following code:
Before the voting creation, the verification is made that the passed sequence number of the module falls within valid values. The acceptance of the vote and voting termination rules coincide with the refund type, except that 80% of the votes instead of 90% are required for this type of vote to be accepted.
The completion has the following code:
Thus, if the vote is successful, a call to one of the five functions of a DAO is performed to set the address of the module based on the supplied sequence number.
Each function is verified using the canSetAddress
modifier, which allows to change the address of the module only if the function call was made by the voting contract or the address has not yet been set at all and is being set by the contract’s owner. Therefore, module addresses can be changed only by means of this vote.
Conclusion
To sum up, this part of the article described all voting types and their features. Hope that this article helped every reader to understand how Daox works and feel its potential for fundraising process.
Full code of smart contracts that are used by Daox could be found in our github repository: https://github.com/daox/daox-contracts