All Pie DAO smart pools are upgradeable because they use a proxy contract. At PieDAO we use our implementation of a simple proxy contract called pie-proxy.
Upgrading a contract is done by setting the implementation address on the proxy contract to the address of the new logic contract. Using this pattern allows smart pools to be upgraded while keeping the old storage.
Clone the pie-smart-pools repository and checkout master. Master contains the latest release which is considered stable and audited for mainnet use.
copy the contents of
env.example to a new file called
.env and edit the relevant values inside. DO NOT share this file with anyone as it will contain sensitive data.
Install all dependencies:
Build the project
To deploy the implementation contract run the following command replacing the impl-name value with the name you would like to give to the implementation contract and the --network value with whichever network you want to deploy the contract to.
npx buidler deploy-smart-pool-implementation-complete --impl-name [IMPL-NAME] --network kovan
In your terminal you will see the address of the implementation, copy this for the next step.
The pie-proxy instance has a proxyOwner address, only this address is capable of changing the implementation contract by calling
The smart pools are currently controlled by a multisig wallet. To change the implementation you should do the following steps.
Go to multi sig UI
Connect your wallet.
Add a transaction.
Set destination to pool address.
Set contract name.
Set ABI (can be found on Etherscan).
Select setImplementation method.
Fill in the implementation address in the input.
Send multi sig tx.
Get enough confirmations by other multi sig owners.
Enjoy your upgraded contract.
Because Pie smart pools deal with real value it is important to take extra precaution when upgrading them to minimize the risk to users funds.
For BTC++ there is a private testing pool on mainnet at: 0x21909429c586fb739653e8e0b913b23fe30bacfa.
Before upgrading any pool we do a test run using this pool first. To do this we take the following steps:
Deploy implementation (described above).
Set cap to zero.
Set implementation (described above).
Set Controller to testing address.
The automated test tests this functionality on mainnet:
Check the controller.
Check if the cap is zero.
Exiting the pool.
Check if cap is enforced.
Setting the cap.
Joining the pool.
Setting cap to zero
Setting public swap from non public swap setter (should fail).
Setting public swap setter from controller.
Setting public swap to true.
Setting public swap to false.
Setting the tokenBinder
Unbinding token from non tokenBinder address (should fail).
Binding token from non tokenBinder address (should fail)
Rebinding token from non tokenBinderAddress (should fail).
Rebinding token from tokenBinderAddress.
Binding token from tokenBinder address.
Unbinding token from tokenBinder address.
Setting token binder to 0x000...0000.
Binding a token (should fail).
To run this test execute the following command:
POOL=[POOL_ADDRESS] npx buidler test ./mainnet-test/test.ts --network [rinkeby|mainnet]
This command will throw an error if something is not as expected.
Only AFTER these tests should the implementation be set on the actual smart pool contract. See above on how to do this.