PoolTogether is a prize-linked savings account built on Ethereum. This project contains the Ethereum smart contracts that power the protocol. The protocol is described in detail in the article Inside PoolTogether v2.0.
If you want to run PoolTogether locally in an isolated test environment check out the PoolTogether Mock project
PoolTogether V2 is an upgradeable system. Each deployed contract is actually a "Proxy" that points to an "Implementation" contract. When making calls on any contract make sure to use the Proxy address, not the implementation.
Contract | Address | Version |
---|---|---|
Pool Sai | 0xb7896fce748396EcFC240F5a0d3Cc92ca42D7d84 | MCDAwarePool v0.2.12 |
Pool Sai Token (plSai) | 0xfE6892654CBB05eB73d28DCc1Ff938f59666Fe9f | RecipientWhitelistPoolToken v0.2.12 |
Pool Dai | 0x29fe7D60DdF151E5b52e5FAB4f1325da6b2bD958 | MCDAwarePool v0.2.12 |
Pool Dai Token (plDai) | 0x49d716DFe60b37379010A75329ae09428f17118d | RecipientWhitelistPoolToken v0.2.12 |
Pool Usdc | 0x0034Ea9808E620A0EF79261c51AF20614B742B24 | MCDAwarePool v0.2.12 |
Pool Usdc Token (plUsdc) | 0xBD87447F48ad729C5c4b8bcb503e1395F62e8B98 | RecipientWhitelistPoolTokenDecimals v0.2.12 |
Contract | Address (proxy) | Address (implementation) |
---|---|---|
PoolSai | 0x9B80beA68835e8E39b9CeaeF83B7b49e9D41661C | 0x11149E1B3C8e334a889FC697230b377F47Fa32Ca |
PoolSaiToken | 0xC9689253a545D0C4dc733620281bBdCbb9FA4A4D | 0x55d462dB374D0D96EDB3aa603a4D8B8617bBdAA1 |
PoolDai | 0xC3a62C8Af55c59642071bC171Ebd05Eb2479B663 | 0x662Aa47D4b9B4CFC4DB8f6dac0381fFFd2faC342 |
PoolDaiToken | 0x1237a9f1664895bc30cfe9eCD1e3f6C2A83700AD | 0xAe2065e2298C6940d5bd59cD1c7bB6264c772c6A |
PoolUsdc | 0xa0B2A98d0B769886ec06562ee9bB3572Fa4f3aAb | 0xa05a7065a257DF3A0531298dc15CBCb0Ce5a3Ff5 |
PoolUsdcToken | 0xf08d73ABC5E46811649380cCb02bF1aDCc37E59c | 0x6C5492664df0ED36f29D654Fd62e9C3A3F6279A3 |
Clone the repo and then install dependencies:
$ yarn
To run the entire test suite:
$ yarn test
To run tests with coverage:
$ yarn coverage
A prize-linked savings account is one in which interest payments are distributed as prizes. PoolTogether uses Compound to generate interest on pooled deposits and distributes the interest in prize draws.
- An administrator opens a new draw by committing the hash of a secret and salt.
- A user deposits tokens into the Pool. The Pool transfers the tokens to the Compound CToken contract and adds the deposit to the currently open draw.
- Time passes. Interest accrues.
- An administrator executes the "reward" function, which:
- If there is a committed draw it is "rewarded": the admin reveals the previously committed secret and uses it to select a winner for the currently accrued interest on the pool deposits. The interest is added to the open draw to increase the user's eligibility.
- The open draw is "committed", meaning it will no longer receive deposits.
- A new draw is opened to receive deposits. The admin commits a hash of a secret and salt.
- A user withdraws. The Pool will withdraw from the Compound CToken all of the user's deposits and winnings. Any amounts across open, committed, or rewarded draws will be withdrawn.
As you can see, prizes are awarded in rolling draws. In this way, we can ensure users will contribute fairly to a prize. The open period allows users to queue up their deposits for the committed period, then once the committed period is over the interest accrued is awarded to one of the participants.
You can visualize the rolling draws like so:
Step | Draw 1 | Draw 2 | Draw 3 | Draw 4 | Draw ... |
---|---|---|---|---|---|
1 | Open | ||||
2 | Committed | Open | |||
3 | Rewarded | Committed | Open | ||
4 | Rewarded | Committed | Open | ||
5 | Rewarded | Committed | |||
... | Rewarded |
When a Pool administrator opens a new draw, they commit a hash of a secret and salt. When the Pool administrator rewards a draw, they reveal the secret and salt. The secret is then hashed and used to randomly select a winner.
Decentralizing this portion of the protocol is very high on our to-do list.
The project includes a CLI tool to make working with forks much easier. To see what commands the tool offers, enter:
$ yarn fork -h
The fork command will allow you to spin up a fork of mainnet and run transactions using unlocked accounts. The first 10 largest accounts from the subgraph are automatically unlocked.
To upgrade all proxies in the fork by doing a simple implementation address change (i.e. using upgrade
vs upgradeAndCall
) you can use the yarn fork upgrade
command. Just make sure to yarn fork push
the new contracts first.
For example:
# starts the fork
$ yarn fork start
# Ensures the necessary accounts have Eth and tokens
$ yarn fork pay
# Pushes the latest contract implementations to the fork
$ yarn fork push
# Upgrades the deployed proxies to their latest implementations
$ yarn fork upgrade
There are a few pre-baked actions that can be performed to test the fork.
# For the top ten users, withdraw and then deposit back into the pool.
$ yarn fork withdraw-deposit
# Rewards the pool
$ yarn fork reward