The first version of PoolTogether was a roaring success: the community pooled over 150,000 DAI to generate nearly 800 DAI in prizes in only six weeks. The idea of interest as an instrument has now reached a fever pitch with a proliferation of clever projects such as rDAI and Pooled cDAI. We’re thrilled that this concept has gained traction and are excited to move forward alongside these dapps.
The PoolTogether community has given us great feedback in our Telegram channel, and we’ve been listening intently. From the praise, questions, and occasional scorn we determined that:
- Users must be automatically entered into the next Pool
- Users must be able to purchase tickets at any time
- Users must be able to withdraw at any time
- Funds must always accrue interest to maximize the prize
We’re thrilled to present how we accomplished these goals in PoolTogether v2.0!
PoolTogether now consists of a single deployed contract called the Pool. Users deposit and withdraw from the Pool, which tracks their balance and winnings while keeping the funds in Compound. Draws are created periodically by Pool administrators, and their pulse of rewards is the heartbeat of this dapp.
Automatic Re-entry Through Draws
Draws move through three states: open, committed, then rewarded. Draws exist in the open and committed state for a week each. We increased the frequency of prizes so that they would occur more regularly (i.e. every Friday).
There is only ever one open draw. All deposits to the Pool are recorded in the open Draw.
After a week has passed the open Draw is committed. These committed funds are added to the funds already in the pool. A user’s chance of winning is proportional to the ratio of their committed funds to all committed funds. For example:
If a user has 100 committed DAI in tickets, 40 open DAI in pre-purchased tickets, and there is a total of 1000 committed DAI in tickets then they stand a 10% chance of winning. Notice that the open DAI was not included!
After another week has passed the committed Draw is rewarded by computing the winner and updating their balance with the winnings.
It is important to note that there is always one open draw and one committed draw, so in fact Draws are overlapping.
It’s best illustrated with this table:
Pre-purchase Tickets at Any Time
Each week a new Draw is opened, so there is always a Draw from which a user can pre-purchase tickets. Depending on when they purchase, a user may wait anywhere between one to two weeks for a possible prize.
Withdraw at Any Time
Users are able to withdraw their tokens at any time, but everything will be withdrawn at once. The sum of all of their deposits and winnings will be transferred back to them.
Funds Always Accrue Interest
The Pool contract simply accounts for who owns what portion of the pooled funds; the actual funds are always kept in Compound in order to maximize interest accrual.
Pool administrators manage Draws. When they open a new draw, they commit a hash of a secret to the Draw. When a Pool administrator rewards a Draw, they reveal the secret. The secret is combined with the hash of the gross winnings for the Draw to serve as the entropy used to randomly select a winner.
While not perfect, we believe that using the gross winnings is an improvement over using the blockhash as Compound is more difficult to manipulate directly. It’s possible to change Compound’s current rate (and therefore gross winnings) using vast supplies of DAI, but ensuring a particular wei value for the gross winnings would be extremely difficult as the numbers are a moving target.
As in PoolTogether v1, a beneficiary can receive a portion of the winnings. There are two elements to the beneficiary: the address of the beneficiary and the fee fraction the beneficiary receives.
The Pool contract stores two variables called the next fee beneficiary and the next fee fraction. When a new Draw is opened the fee beneficiary and fee fraction fields are initialized with the previously mentioned values, respectively. In this way each Draw “locks-in” the beneficiary and their fee.
We plan to use the beneficiary feature for two types of pools: the prize Pool and philanthropic Pools.
The prize Pool will have the beneficiary set to the Pool itself so that the winnings are compounded. The idea is to increase the capital of PoolTogether without decreasing each user’s odds so that it is more worthwhile to deposit into PoolTogether rather than Compound directly. Credit goes to Luke Duncan for the idea!
Philanthropic Pools will have a fee fraction of 100% and the beneficiaries could be any group from UNICEF to MetaCartel DAO.
The Algorithm in Plain English
Let’s run through the algorithm from end-to-end. We’re going to do skip some details in order to simplify the process.
- The Pool contract is deployed by a developer. They initialize the contract with an administrator, next fee beneficiary, and next fee fraction.
- The administrator opens Draw 1 using a hash of a secret.
- A user deposits into the Pool and the deposit is recorded in Draw 1.
- In one transaction the administrator commits Draw 1 and opens Draw 2 using another hash of a secret.
- Another user deposits into the Pool and the deposit is recorded in Draw 2.
- In one transaction the administrator rewards Draw 1 by revealing the Draw 1 secret, commits Draw 2, and opens Draw 3 using another hash of a secret.
The beneficiary of Draw 1 receives a fee calculated by the fee fraction * gross winnings. The gross winnings is the accrued interest since the last reward. The winner receives the gross winnings less the fee.
- Go back to step 5 and increment all of the draw numbers by 1.
The Pool contract is going to be deployed as an upgradeable contract. We believe it is prudent to retain upgrade privileges until the contract has an established track record of good behaviour. After the probation period is over we will transfer the upgrade privileges to the null address.
Security Bug Bounties
After the launch of PoolTogether v1, we were notified by an attentive developer Scott Bigelow that we had an issue in the smart contracts. It was low-risk, but it allowed us to immediately address the problem and rectify it for our following Pool.
For this version we’ve elected to publish the code before going to mainnet to allow for the full scrutiny of the community. We have established an official security bug bounty program, so if find any issues with the contracts we’ll be happy to reward you.
August 30, 2019
Smart contracts are made available to the public for security bounties.
September 4th, 2019
Smart contracts go live on mainnet and the first Pool is opened!
We’re very excited to launch PoolTogether v2.0. The new design allows users to participate in as many Draws as they like with a minimum of transactions. Additionally, we believe the prizes will be larger as every single DAI will be accruing interest.
If you have any questions, comments, concerns or praise please feel free to reach out! We love hearing from the community.