From bbc690e13d5cf86d55b7c969001d111512506119 Mon Sep 17 00:00:00 2001 From: eccheung4 Date: Wed, 29 Sep 2021 07:35:12 -0700 Subject: [PATCH 1/8] initial: copy of files from mainnet connector --- .../connectors/pooltogether/events.sol | 13 + .../connectors/pooltogether/interface.sol | 26 + .../polygon/connectors/pooltogether/main.sol | 238 +++++ .../pooltogether-polygon/pooltogether.test.js | 811 ++++++++++++++++++ 4 files changed, 1088 insertions(+) create mode 100644 contracts/polygon/connectors/pooltogether/events.sol create mode 100644 contracts/polygon/connectors/pooltogether/interface.sol create mode 100644 contracts/polygon/connectors/pooltogether/main.sol create mode 100644 test/pooltogether-polygon/pooltogether.test.js diff --git a/contracts/polygon/connectors/pooltogether/events.sol b/contracts/polygon/connectors/pooltogether/events.sol new file mode 100644 index 00000000..564b21bc --- /dev/null +++ b/contracts/polygon/connectors/pooltogether/events.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.7.0; + +import { TokenFaucetInterface } from "./interface.sol"; + +contract Events { + event LogDepositTo(address prizePool, address to, uint256 amount, address controlledToken, uint256 getId, uint256 setId); + event LogWithdrawInstantlyFrom(address prizePool, address from, uint256 amount, address controlledToken, uint256 maximumExitFee, uint256 exitFee, uint256 getId, uint256 setId); + event LogClaim(address tokenFaucet, address user, uint256 claimed, uint256 setId); + event LogClaimAll(address tokenFaucetProxyFactory, address user, TokenFaucetInterface[] tokenFaucets); + event LogClaimPodTokenDrop(address podTokenDrop, address user, uint256 claimed, uint256 setId); + event LogDepositToPod(address prizePoolToken, address pod, address to, uint256 amount, uint256 podShare, uint256 getId, uint256 setId); + event LogWithdrawFromPod(address pod, uint256 shareAmount, uint256 tokenAmount, uint256 maxFee, uint256 getId, uint256 setId); +} \ No newline at end of file diff --git a/contracts/polygon/connectors/pooltogether/interface.sol b/contracts/polygon/connectors/pooltogether/interface.sol new file mode 100644 index 00000000..7dd1ae94 --- /dev/null +++ b/contracts/polygon/connectors/pooltogether/interface.sol @@ -0,0 +1,26 @@ +pragma solidity ^0.7.0; + +interface PrizePoolInterface { + function token() external view returns (address); + function depositTo( address to, uint256 amount, address controlledToken, address referrer) external; + function withdrawInstantlyFrom( address from, uint256 amount, address controlledToken, uint256 maximumExitFee) external returns (uint256); +} + +interface PodTokenDropInterface { + function claim(address user) external returns (uint256); +} + +interface TokenFaucetInterface { + function claim( address user) external returns (uint256); +} + +interface TokenFaucetProxyFactoryInterface { + function claimAll(address user, TokenFaucetInterface[] calldata tokenFaucets) external; +} + +interface PodInterface { + function token() external view returns (address); + function depositTo(address to, uint256 tokenAmount) external returns (uint256); + function withdraw(uint256 shareAmount, uint256 maxFee) external returns (uint256); + function balanceOf(address account) external view returns (uint256); +} \ No newline at end of file diff --git a/contracts/polygon/connectors/pooltogether/main.sol b/contracts/polygon/connectors/pooltogether/main.sol new file mode 100644 index 00000000..bb15feac --- /dev/null +++ b/contracts/polygon/connectors/pooltogether/main.sol @@ -0,0 +1,238 @@ +pragma solidity ^0.7.0; + +/** + * @title PoolTogether + * @dev Deposit & Withdraw from PoolTogether + */ + + import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + import { PrizePoolInterface, TokenFaucetInterface, TokenFaucetProxyFactoryInterface, PodInterface, PodTokenDropInterface } from "./interface.sol"; + +import { TokenInterface } from "../../common/interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { Events } from "./events.sol"; +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; + +abstract contract PoolTogetherResolver is Events, DSMath, Basic { + using SafeERC20 for IERC20; + + /** + * @dev Deposit into Prize Pool + * @notice Deposit assets into the Prize Pool in exchange for tokens + * @param prizePool PrizePool address to deposit to + * @param amount The amount of the underlying asset the user wishes to deposit. The Prize Pool contract should have been pre-approved by the caller to transfer the underlying ERC20 tokens. + * @param controlledToken The address of the token that they wish to mint. For our default Prize Strategy this will either be the Ticket address or the Sponsorship address. Those addresses can be looked up on the Prize Strategy. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + + function depositTo( + address prizePool, + uint256 amount, + address controlledToken, + uint256 getId, + uint256 setId + ) external payable returns ( string memory _eventName, bytes memory _eventParam) { + uint _amount = getUint(getId, amount); + + PrizePoolInterface prizePoolContract = PrizePoolInterface(prizePool); + address prizePoolToken = prizePoolContract.token(); + + bool isEth = prizePoolToken == wethAddr; + TokenInterface tokenContract = TokenInterface(prizePoolToken); + + if (isEth) { + _amount = _amount == uint256(-1) ? address(this).balance : _amount; + convertEthToWeth(isEth, tokenContract, _amount); + } else { + _amount = _amount == uint256(-1) ? tokenContract.balanceOf(address(this)) : _amount; + } + + // Approve prizePool + approve(tokenContract, prizePool, _amount); + + prizePoolContract.depositTo(address(this), _amount, controlledToken, address(0)); + + setUint(setId, _amount); + + _eventName = "LogDepositTo(address,address,uint256,address,uint256,uint256)"; + _eventParam = abi.encode(address(prizePool), address(this), _amount, address(controlledToken), getId, setId); + } + + /** + * @dev Withdraw from Prize Pool + * @notice Withdraw assets from the Prize Pool instantly. A fairness fee may be charged for an early exit. + * @param prizePool PrizePool address to withdraw from + * @param amount The amount of tokens to redeem for assets. + * @param controlledToken The address of the token to redeem (i.e. ticket or sponsorship) + * @param maximumExitFee The maximum early exit fee the caller is willing to pay. This prevents the Prize Strategy from changing the fee on the fly. This should be pre-calculated by the calculateExitFee() fxn. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + + function withdrawInstantlyFrom ( + address prizePool, + uint256 amount, + address controlledToken, + uint256 maximumExitFee, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amount = getUint(getId, amount); + + PrizePoolInterface prizePoolContract = PrizePoolInterface(prizePool); + address prizePoolToken = prizePoolContract.token(); + TokenInterface tokenContract = TokenInterface(prizePoolToken); + + TokenInterface ticketToken = TokenInterface(controlledToken); + _amount = _amount == uint256(-1) ? ticketToken.balanceOf(address(this)) : _amount; + + uint exitFee = prizePoolContract.withdrawInstantlyFrom(address(this), _amount, controlledToken, maximumExitFee); + + _amount = _amount - exitFee; + + convertWethToEth(prizePoolToken == wethAddr, tokenContract, _amount); + + setUint(setId, _amount); + + _eventName = "LogWithdrawInstantlyFrom(address,address,uint256,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(address(prizePool), address(this), _amount, address(controlledToken), maximumExitFee, exitFee, getId, setId); + } + + /** + * @dev Claim token from a Token Faucet + * @notice Claim token from a Token Faucet + * @param tokenFaucet TokenFaucet address + * @param setId Set claimed amount at this ID in `InstaMemory` Contract. + */ + function claim ( + address tokenFaucet, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + TokenFaucetInterface tokenFaucetContract = TokenFaucetInterface(tokenFaucet); + + uint256 claimed = tokenFaucetContract.claim(address(this)); + + setUint(setId, claimed); + + _eventName = "LogClaim(address,address, uint256, uint256)"; + _eventParam = abi.encode(address(tokenFaucet), address(this), claimed, setId); + } + + /** + * @dev Runs claim on all passed comptrollers for a user. + * @notice Runs claim on all passed comptrollers for a user. + * @param tokenFaucetProxyFactory The TokenFaucetProxyFactory address + * @param tokenFaucets The tokenFaucets to call claim on. + */ + function claimAll ( + address tokenFaucetProxyFactory, + TokenFaucetInterface[] calldata tokenFaucets + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + TokenFaucetProxyFactoryInterface tokenFaucetProxyFactoryContract = TokenFaucetProxyFactoryInterface(tokenFaucetProxyFactory); + + tokenFaucetProxyFactoryContract.claimAll(address(this), tokenFaucets); + + _eventName = "LogClaimAll(address,address,TokenFaucetInterface[])"; + _eventParam = abi.encode(address(tokenFaucetProxyFactory), address(this), tokenFaucets); + } + + /** + * @dev Claim asset rewards from a Pod TokenDrop + * @notice Claim asset rewards from a TokenDrop + * @param podTokenDrop Pod TokenDrop address + * @param setId Set claimed amount at this ID in `InstaMemory` Contract. + */ + function claimPodTokenDrop ( + address podTokenDrop, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + PodTokenDropInterface podTokenDropContract = PodTokenDropInterface(podTokenDrop); + + uint256 claimed = podTokenDropContract.claim(address(this)); + + setUint(setId, claimed); + + _eventName = "LogClaimPodTokenDrop(address,address,uint256,uint256)"; + _eventParam = abi.encode(address(podTokenDrop), address(this), claimed, setId); + } + + /** + * @dev Deposit into Pod + * @notice Deposit assets into the Pod in exchange for share tokens + * @param prizePoolToken Prize Pool Token Address + * @param pod Pod address to deposit to + * @param tokenAmount The amount of tokens to deposit. These are the same tokens used to deposit into the underlying prize pool. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function depositToPod( + address prizePoolToken, + address pod, + uint256 tokenAmount, + uint256 getId, + uint256 setId + ) external payable returns ( string memory _eventName, bytes memory _eventParam) { + uint _tokenAmount= getUint(getId, tokenAmount); + + PodInterface podContract = PodInterface(pod); + + bool isEth = prizePoolToken == wethAddr; + + // Approve pod + TokenInterface tokenContract = TokenInterface(prizePoolToken); + if (isEth) { + _tokenAmount = _tokenAmount == uint256(-1) ? address(this).balance : _tokenAmount; + convertEthToWeth(isEth, tokenContract, _tokenAmount); + } else { + _tokenAmount = _tokenAmount == uint256(-1) ? tokenContract.balanceOf(address(this)) : _tokenAmount; + } + approve(tokenContract, pod, _tokenAmount); + + uint256 _podShare = podContract.depositTo(address(this), _tokenAmount); + + setUint(setId, _podShare); + + _eventName = "LogDepositToPod(address,address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(address(prizePoolToken), address(pod), address(this), _tokenAmount, _podShare, getId, setId); + } + + /** + * @dev Withdraw from shares from Pod + * @notice Withdraws a users share of the prize pool. + * @dev The function should first withdraw from the 'float'; i.e. the funds that have not yet been deposited. + * @param pod Pod address + * @param shareAmount The number of Pod shares to burn. + * @param maxFee Max fee amount for withdrawl if amount isn't available in float. + * @param getId Get token amount at this ID from `InstaMemory` Contract. + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + + function withdrawFromPod ( + address pod, + uint256 shareAmount, + uint256 maxFee, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _shareAmount = getUint(getId, shareAmount); + + PodInterface podContract = PodInterface(pod); + _shareAmount = _shareAmount == uint256(-1) ? podContract.balanceOf(address(this)) : _shareAmount; + + uint256 _tokenAmount = podContract.withdraw(_shareAmount, maxFee); + + convertWethToEth(address(podContract.token()) == wethAddr, TokenInterface(podContract.token()), _tokenAmount); + + setUint(setId, _tokenAmount); + + _eventName = "LogWithdrawFromPod(address,uint256,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(address(pod), _shareAmount, _tokenAmount, maxFee, getId, setId); + } +} + +contract ConnectV2PoolTogether is PoolTogetherResolver { + string public constant name = "PoolTogether-v1"; +} \ No newline at end of file diff --git a/test/pooltogether-polygon/pooltogether.test.js b/test/pooltogether-polygon/pooltogether.test.js new file mode 100644 index 00000000..6dc2697b --- /dev/null +++ b/test/pooltogether-polygon/pooltogether.test.js @@ -0,0 +1,811 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { web3, deployments, waffle, ethers } = hre; +const { provider, deployContract } = waffle + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); +const constants = require("../../scripts/constant/constant"); +const tokens = require("../../scripts/constant/tokens"); + +const connectV2CompoundArtifacts = require("../../artifacts/contracts/mainnet/connectors/compound/main.sol/ConnectV2Compound.json") +const connectV2PoolTogetherArtifacts = require("../../artifacts/contracts/mainnet/connectors/pooltogether/main.sol/ConnectV2PoolTogether.json") +const connectV2UniswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/uniswap/main.sol/ConnectV2UniswapV2.json") + +const DAI_TOKEN_ADDR = tokens.dai.address // DAI Token + +// PoolTogether Address: https://docs.pooltogether.com/resources/networks/ethereum +const DAI_PRIZE_POOL_ADDR = "0xEBfb47A7ad0FD6e57323C8A42B2E5A6a4F68fc1a" // DAI Prize Pool +const PT_DAI_TICKET_ADDR = "0x334cBb5858417Aee161B53Ee0D5349cCF54514CF" // PT DAI Ticket +const DAI_POOL_FAUCET_ADDR = "0xF362ce295F2A4eaE4348fFC8cDBCe8d729ccb8Eb" // DAI POOL Faucet +const POOL_TOKEN_ADDRESS = "0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e" // POOL Tocken +const TOKEN_FAUCET_PROXY_FACTORY_ADDR = "0xE4E9cDB3E139D7E8a41172C20b6Ed17b6750f117" // TokenFaucetProxyFactory for claimAll +const DAI_POD_ADDR = "0x2f994e2E4F3395649eeE8A89092e63Ca526dA829" // DAI Pod +const UNISWAP_POOLETHLP_PRIZE_POOL_ADDR = "0x3AF7072D29Adde20FC7e173a7CB9e45307d2FB0A" // Uniswap Pool/ETH LP PrizePool +const UNISWAP_POOLETHLP_FAUCET_ADDR = "0x9A29401EF1856b669f55Ae5b24505b3B6fAEb370" // Uniswap Pool/ETH LP Faucet +const UNISWAP_POOLETHLP_TOKEN_ADDR = "0x85cb0bab616fe88a89a35080516a8928f38b518b" // Uniswap Pool/ETH Token +const PT_UNISWAP_POOLETHLP_TICKET_ADDR = "0xeb8928ee92efb06c44d072a24c2bcb993b61e543" // Pool Together Uniswap Pool/ETH LP Ticket +const POOL_PRIZE_POOL_ADDR = "0x396b4489da692788e327e2e4b2b0459a5ef26791" // POOL Prize Pool +const PT_POOL_TICKET_ADDR = "0x27d22a7648e955e510a40bdb058333e9190d12d4" // Pool Together POOL Ticket +const WETH_ADDR = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" // WETH +const DAI_POD_TOKEN_DROP = "0xc5209623E3dFdf9C0cCbe497c8012883C4147731" + +// Community WETH Prize Pool (Rari): https://reference-app.pooltogether.com/pools/mainnet/0xa88ca010b32a54d446fc38091ddbca55750cbfc3/manage#stats +const WETH_PRIZE_POOL_ADDR = "0xa88ca010b32a54d446fc38091ddbca55750cbfc3" // Community WETH Prize Pool (Rari) +const WETH_POOL_TICKET_ADDR = "0x9b5c30aeb9ce2a6a121cea9a85bc0d662f6d9b40" // Community WETH Prize Pool Ticket (Rari) + +const prizePoolABI = [ + "function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)" +] + +const podABI = [ + "function getEarlyExitFee(uint256 amount) external returns (uint256)", + "function balanceOfUnderlying(address user) external view returns (uint256 amount)", + "function drop() public returns (uint256)", + "function balanceOf(address account) external view returns (uint256)" +] + +const POD_FACTORY_ADDRESS = "0x4e3a9f9fbafb2ec49727cffa2a411f7a0c1c4ce1" +const podFactoryABI = [ + "function create( address _prizePool, address _ticket, address _faucet, address _manager, uint8 _decimals) external returns (address pod)" +] + +const tokenDropABI = [ + "function claim(address user) external returns (uint256)", +] + +describe("PoolTogether", function () { + const connectorName = "COMPOUND-TEST-A" + const uniswapConnectorName = "UNISWAP-TEST-A" + const ptConnectorName = "POOLTOGETHER-TEST-A" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + let ptConnector; + let uniswapConnector; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + + // Deploy and enable Compound Connector + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2CompoundArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + + // Deploy and enable Pool Together Connector + ptConnector = await deployAndEnableConnector({ + connectorName: ptConnectorName, + contractArtifact: connectV2PoolTogetherArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + + // Deploy and enable Uniswap Connector + uniswapConnector = await deployAndEnableConnector({ + connectorName: uniswapConnectorName, + contractArtifact: connectV2UniswapArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!ptConnector.address).to.be.true; + expect(!!uniswapConnector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit 10 ETH into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main - DAI Prize Pool Test", function () { + + it("Should deposit 1 ETH in Compound", async function () { + const amount = ethers.utils.parseEther("1") // 1 ETH + const spells = [ + { + connector: connectorName, + method: "deposit", + args: ["ETH-A", amount, 0, 0] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + }); + + it("Should borrow 100 DAI from Compound and deposit DAI into DAI Prize Pool", async function () { + const amount = ethers.utils.parseEther("100") // 100 DAI + const setId = "83478237" + const spells = [ + { + connector: connectorName, + method: "borrow", + args: ["DAI-A", amount, 0, setId] + }, + { + connector: ptConnectorName, + method: "depositTo", + args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, setId, 0] + } + ] + // Before Spell + let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) + let daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI balance is 0`).to.be.eq(ethers.utils.parseEther("0")); + + let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR) + const balance = await cToken.balanceOf(dsaWallet0.address) + expect(balance,`PoolTogether DAI Ticket balance is 0`).to.be.eq(0); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `Expect DAI balance to still equal 0 since it was deposited into Prize Pool`).to.be.eq(0); + + const balanceAfter = await cToken.balanceOf(dsaWallet0.address) + expect(balanceAfter, `PoolTogether DAI Ticket balance equals 100`).to.be.eq(ethers.utils.parseEther("100")); + + // ETH used for transaction + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + }); + + it("Should wait 11 days, withdraw all PrizePool, get back 100 DAI, and claim POOL", async function () { + const amount = ethers.utils.parseEther("100") // 100 DAI + + let prizePoolContract = new ethers.Contract(DAI_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider); + let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); + expect(earlyExitFee.exitFee, "Exit Fee equal to 1 DAI because starts at 10%").to.be.eq(ethers.utils.parseEther("1")); + + const spells = [ + { + connector: ptConnectorName, + method: "withdrawInstantlyFrom", + args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, earlyExitFee.exitFee, 0, 0] + }, + { + connector: ptConnectorName, + method: "claim", + args: [DAI_POOL_FAUCET_ADDR, 0] + } + ] + + // Before spell + let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) + let daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI balance equals 0`).to.be.eq(ethers.utils.parseEther("0")); + + let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR) + const balance = await cToken.balanceOf(dsaWallet0.address) + expect(balance, `PoolTogether Dai Ticket is 100`).to.be.eq(ethers.utils.parseEther("100")); + + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `POOL Token equals 0`).to.be.eq(ethers.utils.parseEther("0")); + + // Increase time by 11 days so we get back all DAI without early withdrawal fee + await ethers.provider.send("evm_increaseTime", [11*24*60*60]); + await ethers.provider.send("evm_mine"); + + earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); + expect(earlyExitFee.exitFee, "Exit Fee equal to 0 DAI because past 10 days").to.be.eq(0); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, + `DAI balance to be equal to 100, because of no early withdrawal fee` + ).to.be.eq(ethers.utils.parseEther("100")); + + const balanceAfter = await cToken.balanceOf(dsaWallet0.address) + expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0); + + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalanceAfter, `POOL Token Balance to be greater than 0`).to.be.gt(ethers.utils.parseEther("0")); + }); + + it("Should deposit and withdraw all PrizePool, get back less than 100 DAI", async function() { + const amount = ethers.utils.parseEther("100") // 100 DAI + const exitFee = ethers.utils.parseEther("1") // 1 DAI is 10% of 100 DAI + const spells = [ + { + connector: ptConnectorName, + method: "depositTo", + args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0] + }, + { + connector: ptConnectorName, + method: "withdrawInstantlyFrom", + args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, exitFee, 0, 0] + } + ] + + // Before spell + let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) + let daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI Balance equals 0`).to.be.eq(ethers.utils.parseEther("100")); + + let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR) + const balance = await cToken.balanceOf(dsaWallet0.address) + expect(balance, `PoolTogether DAI Ticket equals 0`).to.be.eq(0); + + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `PoolTogether Token greater than 0`).to.be.gt(0); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, + `DAI balance to be less than 100, because of early withdrawal fee` + ).to.be.lt(ethers.utils.parseEther("100")); + + const balanceAfter = await cToken.balanceOf(dsaWallet0.address) + expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0); + + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalanceAfter, `POOL Token Balance to greater than 0`).to.be.gt(ethers.utils.parseEther("0")); + + }); + + it("Should deposit, wait 11 days, and withdraw all PrizePool, get 99 DAI, and claim all POOL using claimAll", async function() { + const amount = ethers.utils.parseEther("99") // 99 DAI + const depositSpells = [ + { + connector: ptConnectorName, + method: "depositTo", + args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0] + } + ] + + // Before spell + let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) + let daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI balance less than 100`).to.be.lt(ethers.utils.parseEther("100")); + + let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR) + const balance = await cToken.balanceOf(dsaWallet0.address) + expect(balance, `PoolTogether DAI Ticket equal 0`).to.be.eq(0); + + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `POOL Token is greater than 0`).to.be.gt(ethers.utils.parseEther("0")); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpells), wallet1.address) + const receipt = await tx.wait() + + const prizePoolContract = new ethers.Contract(DAI_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider); + let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); + expect(earlyExitFee.exitFee, "Exit Fee equal to .99 DAI because starts at 10%").to.be.eq(ethers.utils.parseEther(".99")); + + + // Increase time by 11 days so we get back all DAI without early withdrawal fee + await ethers.provider.send("evm_increaseTime", [11*24*60*60]); + await ethers.provider.send("evm_mine"); + + earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); + expect(earlyExitFee.exitFee, "Exit Fee equal to 0 DAI because past 10 days").to.be.eq(0); + + const withdrawSpells = [ + { + connector: ptConnectorName, + method: "withdrawInstantlyFrom", + args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, earlyExitFee.exitFee, 0, 0] + }, + { + connector: ptConnectorName, + method: "claimAll", + args: [TOKEN_FAUCET_PROXY_FACTORY_ADDR, [DAI_POOL_FAUCET_ADDR]] + } + ] + + // Run spell transaction + const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpells), wallet1.address) + const receipt2 = await tx2.wait() + + // After spell + daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI balance equals 99`).to.be.eq(ethers.utils.parseEther("99")); + + const balanceAfter = await cToken.balanceOf(dsaWallet0.address) + expect(balanceAfter, `PoolTogether DAI Ticket equal 0`).to.be.eq(0); + + // Expect + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalanceAfter, `Pool Token to be greateir than 0`).to.be.gt(ethers.utils.parseEther("0")); + }); + }) + + describe("Main - DAI Pod Test", function() { + it("Should deposit 99 DAI in DAI Pod", async function() { + const amount = ethers.utils.parseEther("99") // 99 DAI + const spells = [ + { + connector: ptConnectorName, + method: "depositToPod", + args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0] + } + ] + + // Before spell + let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) + let daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI balance equals 99`).to.be.eq(ethers.utils.parseEther("99")); + + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); + + let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR) + const podBalance = await podToken.balanceOf(dsaWallet0.address) + expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI equals 0`).to.be.eq(0); + + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalanceAfter, `POOL Token greater than 0`).to.be.gt(0); + + const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address) + expect(podBalanceAfter, `Pod DAI token greater than 0`).to.be.eq(ethers.utils.parseEther("99")); + }); + + it("Should claim rewards from pod token drop", async function() { + const spells = [ + { + connector: ptConnectorName, + method: "claimPodTokenDrop", + args: [DAI_POD_TOKEN_DROP, 0] + } + ] + + const tokenDropContract = new ethers.Contract(DAI_POD_TOKEN_DROP, tokenDropABI, ethers.provider); + const podContract = new ethers.Contract(DAI_POD_ADDR, podABI, masterSigner); + + // drop(): Claim TokenDrop asset for PrizePool Pod and transfers token(s) to external Pod TokenDrop + // dropt() also calls batch which, Deposit Pod float into PrizePool. Deposits the current float + // amount into the PrizePool and claims current POOL rewards. + const dropTx = await podContract.drop(); + await dropTx.wait(); + + // POOL Rewards able to claim from Pod Token Drop + let claimAmount = await tokenDropContract.callStatic["claim"](dsaWallet0.address); + + // Before spell + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + const total = claimAmount.add(poolBalance); + expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq(total); + }); + + it("Should wait 11 days, withdraw all podTokens, get back 99 DAI", async function () { + const amount = ethers.utils.parseEther("99") // 99 DAI + + const podContract = new ethers.Contract(DAI_POD_ADDR, podABI, ethers.provider); + let maxFee = await podContract.callStatic["getEarlyExitFee"](amount); + // maxFee depends on if token has been deposited to PrizePool yet + // since we called drop in previous test case, the tokens were deposited to PrizePool + expect(maxFee, "Exit Fee equal to .99 DAI because token still in float").to.be.eq(ethers.utils.parseEther(".99")); + + const spells = [ + { + connector: ptConnectorName, + method: "withdrawFromPod", + args: [DAI_POD_ADDR, amount, maxFee, 0, 0] + } + ] + + // Before spell + let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) + let daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI Balance equals 0`).to.be.eq(0); + + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `POOL Token balance greater than 0`).to.be.gt(0); + + let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR) + const podBalance = await podToken.balanceOf(dsaWallet0.address) + expect(podBalance, `Pod DAI Token equals 99`).to.be.eq(ethers.utils.parseEther("99")); + + // Increase time by 11 days so we get back all DAI without early withdrawal fee + await ethers.provider.send("evm_increaseTime", [11*24*60*60]); + await ethers.provider.send("evm_mine"); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, + `DAI balance equals 99, because of no early withdrawal fee` + ).to.be.eq(ethers.utils.parseEther("99")); + + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalanceAfter, `POOL Token to be greater than 0`).to.be.gt(0); + + const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address) + expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq(0); + }); + + + + + it("Should deposit and withdraw from pod, get back same amount of 99 DAI", async function() { + const amount = ethers.utils.parseEther("99") + const maxFee = 0; // maxFee 0 since it doesn't give chance for Pod to actually deposit into PrizePool + + const spells = [ + { + connector: ptConnectorName, + method: "depositToPod", + args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0] + }, + { + connector: ptConnectorName, + method: "withdrawFromPod", + args: [DAI_POD_ADDR, amount, maxFee, 0, 0] + } + ] + + // Before spell + let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) + let daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, `DAI equals 99`).to.be.eq(ethers.utils.parseEther("99")); + + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); + + // PodToken is 0 + let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR) + const podBalance = await podToken.balanceOf(dsaWallet0.address) + expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + daiBalance = await daiToken.balanceOf(dsaWallet0.address); + expect(daiBalance, + `DAI balance to be equal to 99, because funds still in 'float` + ).to.be.eq(ethers.utils.parseEther("99")); + + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq(poolBalance); + + // Expect Pod Token Balance to equal 0 + const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address) + expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq(ethers.utils.parseEther("0")); + }); + }) + + describe("Main - UNISWAP POOL/ETH Prize Pool Test", function () { + it("Should use uniswap to swap ETH for POOL, deposit to POOL/ETH LP, deposit POOL/ETH LP to PrizePool", async function () { + const amount = ethers.utils.parseEther("100") // 100 POOL + const slippage = ethers.utils.parseEther("0.03"); + const setId = "83478237" + + const UniswapV2Router02ABI = [ + "function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)" + ]; + + // Get amount of ETH for 100 POOL from Uniswap + const UniswapV2Router02 = await ethers.getContractAt(UniswapV2Router02ABI, "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"); + const amounts = await UniswapV2Router02.getAmountsOut(amount, [POOL_TOKEN_ADDRESS, WETH_ADDR]); + const unitAmount = ethers.utils.parseEther(((amounts[1]*1.03)/amounts[0]).toString()); + + const spells = [ + { + connector: uniswapConnectorName, + method: "buy", + args: [POOL_TOKEN_ADDRESS, tokens.eth.address, amount, unitAmount, 0, setId] + }, + { + connector: uniswapConnectorName, + method: "deposit", + args: [POOL_TOKEN_ADDRESS, tokens.eth.address, amount, unitAmount, slippage, 0, setId] + }, + { + connector: ptConnectorName, + method: "depositTo", + args: [UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, 0, PT_UNISWAP_POOLETHLP_TICKET_ADDR, setId, 0] + } + ] + + // Before Spell + let ethBalance = await ethers.provider.getBalance(dsaWallet0.address); + expect(ethBalance, `ETH Balance equals 9`).to.be.eq(ethers.utils.parseEther("9")); + + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); + + let uniswapLPToken = await ethers.getContractAt(abis.basic.erc20, UNISWAP_POOLETHLP_TOKEN_ADDR) + const uniswapPoolEthBalance = await uniswapLPToken.balanceOf(dsaWallet0.address) + expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); + + let ptUniswapPoolEthToken = await ethers.getContractAt(abis.basic.erc20, PT_UNISWAP_POOLETHLP_TICKET_ADDR) + const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address) + expect(ptUniswapPoolEthBalance, `PoolTogether Uniswap POOL?ETH LP equals 0`).to.be.eq(0); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + ethBalance = await ethers.provider.getBalance(dsaWallet0.address); + expect(ethBalance, `ETH Balance less than 9`).to.be.lt(ethers.utils.parseEther("9")); + + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalanceAfter, `POOL Token to be same after spell`).to.be.eq(poolBalance); + + const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf(dsaWallet0.address) + expect(uniswapPoolEthBalanceAfter, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); + + const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address) + expect(ptUniswapPoolEthBalanceAfter, `PT Uniswap POOL/ETH LP to greater than 0`).to.be.gt(0); + }); + + it("Should withdraw all PrizePool, get back Uniswap LP, claim POOL, deposit claimed POOL into Pool PrizePool", async function () { + let ptUniswapPoolEthToken = await ethers.getContractAt(abis.basic.erc20, PT_UNISWAP_POOLETHLP_TICKET_ADDR) + const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address) + const setId = "83478237" + + let uniswapPrizePoolContract = new ethers.Contract(UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider); + let earlyExitFee = await uniswapPrizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_UNISWAP_POOLETHLP_TICKET_ADDR, ptUniswapPoolEthBalance); + expect(earlyExitFee.exitFee, "Exit Fee equals 0 because no early exit fee for this prize pool").to.be.eq(0); + + const spells = [ + { + connector: ptConnectorName, + method: "withdrawInstantlyFrom", + args: [UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, ptUniswapPoolEthBalance, PT_UNISWAP_POOLETHLP_TICKET_ADDR, earlyExitFee.exitFee, 0, 0] + }, + { + connector: ptConnectorName, + method: "claim", + args: [UNISWAP_POOLETHLP_FAUCET_ADDR , setId] + }, + { + connector: ptConnectorName, + method: "depositTo", + args: [POOL_PRIZE_POOL_ADDR, 0, PT_POOL_TICKET_ADDR, setId, 0] + } + ] + + // Before spell + let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) + const poolBalance = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); + + // Uniswap POOL/ETH LP is 0 + let uniswapLPToken = await ethers.getContractAt(abis.basic.erc20, UNISWAP_POOLETHLP_TOKEN_ADDR) + const uniswapPoolEthBalance = await uniswapLPToken.balanceOf(dsaWallet0.address) + expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); + + expect(ptUniswapPoolEthBalance, `PT Uniswap POOL/ETH LP greater than 0`).to.be.gt(0); + + let poolPoolTicket = await ethers.getContractAt(abis.basic.erc20, PT_POOL_TICKET_ADDR) + const poolPoolTicketBalance = await poolPoolTicket.balanceOf(dsaWallet0.address) + expect(poolPoolTicketBalance, `PoolTogether POOL Ticket equals 0`).to.be.eq(0); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + expect(poolBalanceAfter, `Pool Token Balance equal to balance before spell`).to.be.eq(poolBalance); + + const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf(dsaWallet0.address) + expect(uniswapPoolEthBalanceAfter, `Uniswap POOL/ETH LP to greater than 0`).to.be.gt(0); + + const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address) + expect(ptUniswapPoolEthBalanceAfter, `PT Uniswap POOL/ETH LP equal 0`).to.be.eq(0); + + const poolPoolTicketBalanceAfter = await poolPoolTicket.balanceOf(dsaWallet0.address) + expect(poolPoolTicketBalanceAfter, `PoolTogether POOL Ticket greater than 0`).to.be.gt(0); + }); + }) + + describe("Main - WETH Prize Pool Test", function () { + it("Deposit 1 ETH into WETH Prize Pool and withdraw immediately", async function () { + const amount = ethers.utils.parseEther("1") // 1 ETH + const setId = "83478237" + const spells = [ + { + connector: ptConnectorName, + method: "depositTo", + args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, setId] + }, + { + connector: ptConnectorName, + method: "withdrawInstantlyFrom", + args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, setId, 0] + }, + ] + // Before Spell + const ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After spell + const ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); + + // ETH used for transaction + expect(ethBalanceAfter, `ETH Balance less than before spell because of early withdrawal fee`).to.be.lte(ethBalanceBefore); + }); + + it("Deposit 1 ETH into WETH Prize Pool, wait 14 days, then withdraw", async function () { + const amount = ethers.utils.parseEther("1") // 1 ETH + const depositSpell = [ + { + connector: ptConnectorName, + method: "depositTo", + args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, 0] + } + ] + + const withdrawSpell = [ + { + connector: ptConnectorName, + method: "withdrawInstantlyFrom", + args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, 0, 0] + } + ] + + // Before Deposit Spell + let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); + + // Run deposit spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpell), wallet1.address) + const receipt = await tx.wait() + + // After Deposit spell + let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); + + expect(ethBalanceAfter, `ETH Balance less than before spell`).to.be.lte(ethBalanceBefore); + + // Increase time by 11 days so we get back all ETH without early withdrawal fee + await ethers.provider.send("evm_increaseTime", [14*24*60*60]); + await ethers.provider.send("evm_mine"); + + // Run withdraw spell transaction + const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpell), wallet1.address) + const receipt2 = await tx.wait() + + // After Deposit spell + ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); + + expect(ethBalanceAfter, `ETH Balance equal to before spell because no early exit fee`).to.be.eq(ethBalanceBefore); + }); + }); + + describe("Main - WETH Pod Test", function() { + let podAddress + it("Should deposit 1 ETH in WETH Pod and get Pod Ticket", async function() { + const amount = ethers.utils.parseEther("1") + + // Create Pod for WETH Prize Pool (Rari) + const podFactoryContract = new ethers.Contract(POD_FACTORY_ADDRESS, podFactoryABI, masterSigner) + podAddress = await podFactoryContract.callStatic.create(WETH_PRIZE_POOL_ADDR, WETH_POOL_TICKET_ADDR, constants.address_zero, wallet0.address, 18) + await podFactoryContract.create(WETH_PRIZE_POOL_ADDR, WETH_POOL_TICKET_ADDR, constants.address_zero, wallet0.address, 18) + + const spells = [ + { + connector: ptConnectorName, + method: "depositToPod", + args: [WETH_ADDR, podAddress, amount, 0, 0] + } + ] + + // Before Deposit Spell + const podContract = new ethers.Contract(podAddress, podABI, ethers.provider); + let podBalanceBefore = await podContract.balanceOfUnderlying(dsaWallet0.address) + expect(podBalanceBefore, `Pod balance equal to 0`).to.be.eq(0); + + let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After Deposit spell + let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); + expect(ethBalanceAfter, `ETH balance less than before`).to.be.lt(ethBalanceBefore); + + podBalanceAfter = await podContract.balanceOfUnderlying(dsaWallet0.address) + expect(podBalanceAfter, `Pod balance equal to 1`).to.be.eq(ethers.utils.parseEther("1")); + }); + + it("Should withdraw 1 Ticket from WETH Pod and get back ETH", async function() { + const amount = ethers.utils.parseEther("1") + + const podContract = new ethers.Contract(podAddress, podABI, ethers.provider); + let maxFee = await podContract.callStatic["getEarlyExitFee"](amount); + expect(maxFee, "Exit Fee equal to 0 DAI because token still in float").to.be.eq(0); + // maxFee depends on if token has been deposited to PrizePool yet + + const spells = [ + { + connector: ptConnectorName, + method: "withdrawFromPod", + args: [podAddress, amount, maxFee, 0, 0] + } + ] + + // Before Deposit Spell + let podBalanceBefore = await podContract.balanceOfUnderlying(dsaWallet0.address) + expect(podBalanceBefore, `Pod balance equal to 1`).to.be.eq(ethers.utils.parseEther("1")); + + let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); + + // Run spell transaction + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const receipt = await tx.wait() + + // After Deposit spell + let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); + expect(ethBalanceAfter, `ETH balance greater than before`).to.be.gt(ethBalanceBefore); + + podBalanceAfter = await podContract.balanceOfUnderlying(dsaWallet0.address) + expect(podBalanceAfter, `Pod balance equal to 0`).to.be.eq(ethers.utils.parseEther("0")); + }); + }); +}) \ No newline at end of file From 220e826e018c3d92e0543fb285a19313be311d24 Mon Sep 17 00:00:00 2001 From: eccheung4 Date: Wed, 29 Sep 2021 07:38:03 -0700 Subject: [PATCH 2/8] fix: remove code for PODs --- .../connectors/pooltogether/events.sol | 3 - .../connectors/pooltogether/interface.sol | 11 - .../polygon/connectors/pooltogether/main.sol | 95 +------ .../pooltogether-polygon/pooltogether.test.js | 269 ------------------ 4 files changed, 1 insertion(+), 377 deletions(-) diff --git a/contracts/polygon/connectors/pooltogether/events.sol b/contracts/polygon/connectors/pooltogether/events.sol index 564b21bc..02b106c8 100644 --- a/contracts/polygon/connectors/pooltogether/events.sol +++ b/contracts/polygon/connectors/pooltogether/events.sol @@ -7,7 +7,4 @@ contract Events { event LogWithdrawInstantlyFrom(address prizePool, address from, uint256 amount, address controlledToken, uint256 maximumExitFee, uint256 exitFee, uint256 getId, uint256 setId); event LogClaim(address tokenFaucet, address user, uint256 claimed, uint256 setId); event LogClaimAll(address tokenFaucetProxyFactory, address user, TokenFaucetInterface[] tokenFaucets); - event LogClaimPodTokenDrop(address podTokenDrop, address user, uint256 claimed, uint256 setId); - event LogDepositToPod(address prizePoolToken, address pod, address to, uint256 amount, uint256 podShare, uint256 getId, uint256 setId); - event LogWithdrawFromPod(address pod, uint256 shareAmount, uint256 tokenAmount, uint256 maxFee, uint256 getId, uint256 setId); } \ No newline at end of file diff --git a/contracts/polygon/connectors/pooltogether/interface.sol b/contracts/polygon/connectors/pooltogether/interface.sol index 7dd1ae94..c82d1b8b 100644 --- a/contracts/polygon/connectors/pooltogether/interface.sol +++ b/contracts/polygon/connectors/pooltogether/interface.sol @@ -6,21 +6,10 @@ interface PrizePoolInterface { function withdrawInstantlyFrom( address from, uint256 amount, address controlledToken, uint256 maximumExitFee) external returns (uint256); } -interface PodTokenDropInterface { - function claim(address user) external returns (uint256); -} - interface TokenFaucetInterface { function claim( address user) external returns (uint256); } interface TokenFaucetProxyFactoryInterface { function claimAll(address user, TokenFaucetInterface[] calldata tokenFaucets) external; -} - -interface PodInterface { - function token() external view returns (address); - function depositTo(address to, uint256 tokenAmount) external returns (uint256); - function withdraw(uint256 shareAmount, uint256 maxFee) external returns (uint256); - function balanceOf(address account) external view returns (uint256); } \ No newline at end of file diff --git a/contracts/polygon/connectors/pooltogether/main.sol b/contracts/polygon/connectors/pooltogether/main.sol index bb15feac..e763e78e 100644 --- a/contracts/polygon/connectors/pooltogether/main.sol +++ b/contracts/polygon/connectors/pooltogether/main.sol @@ -7,7 +7,7 @@ pragma solidity ^0.7.0; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - import { PrizePoolInterface, TokenFaucetInterface, TokenFaucetProxyFactoryInterface, PodInterface, PodTokenDropInterface } from "./interface.sol"; + import { PrizePoolInterface, TokenFaucetInterface, TokenFaucetProxyFactoryInterface } from "./interface.sol"; import { TokenInterface } from "../../common/interfaces.sol"; import { Stores } from "../../common/stores.sol"; @@ -138,99 +138,6 @@ abstract contract PoolTogetherResolver is Events, DSMath, Basic { _eventName = "LogClaimAll(address,address,TokenFaucetInterface[])"; _eventParam = abi.encode(address(tokenFaucetProxyFactory), address(this), tokenFaucets); } - - /** - * @dev Claim asset rewards from a Pod TokenDrop - * @notice Claim asset rewards from a TokenDrop - * @param podTokenDrop Pod TokenDrop address - * @param setId Set claimed amount at this ID in `InstaMemory` Contract. - */ - function claimPodTokenDrop ( - address podTokenDrop, - uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - PodTokenDropInterface podTokenDropContract = PodTokenDropInterface(podTokenDrop); - - uint256 claimed = podTokenDropContract.claim(address(this)); - - setUint(setId, claimed); - - _eventName = "LogClaimPodTokenDrop(address,address,uint256,uint256)"; - _eventParam = abi.encode(address(podTokenDrop), address(this), claimed, setId); - } - - /** - * @dev Deposit into Pod - * @notice Deposit assets into the Pod in exchange for share tokens - * @param prizePoolToken Prize Pool Token Address - * @param pod Pod address to deposit to - * @param tokenAmount The amount of tokens to deposit. These are the same tokens used to deposit into the underlying prize pool. - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - function depositToPod( - address prizePoolToken, - address pod, - uint256 tokenAmount, - uint256 getId, - uint256 setId - ) external payable returns ( string memory _eventName, bytes memory _eventParam) { - uint _tokenAmount= getUint(getId, tokenAmount); - - PodInterface podContract = PodInterface(pod); - - bool isEth = prizePoolToken == wethAddr; - - // Approve pod - TokenInterface tokenContract = TokenInterface(prizePoolToken); - if (isEth) { - _tokenAmount = _tokenAmount == uint256(-1) ? address(this).balance : _tokenAmount; - convertEthToWeth(isEth, tokenContract, _tokenAmount); - } else { - _tokenAmount = _tokenAmount == uint256(-1) ? tokenContract.balanceOf(address(this)) : _tokenAmount; - } - approve(tokenContract, pod, _tokenAmount); - - uint256 _podShare = podContract.depositTo(address(this), _tokenAmount); - - setUint(setId, _podShare); - - _eventName = "LogDepositToPod(address,address,address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(address(prizePoolToken), address(pod), address(this), _tokenAmount, _podShare, getId, setId); - } - - /** - * @dev Withdraw from shares from Pod - * @notice Withdraws a users share of the prize pool. - * @dev The function should first withdraw from the 'float'; i.e. the funds that have not yet been deposited. - * @param pod Pod address - * @param shareAmount The number of Pod shares to burn. - * @param maxFee Max fee amount for withdrawl if amount isn't available in float. - * @param getId Get token amount at this ID from `InstaMemory` Contract. - * @param setId Set token amount at this ID in `InstaMemory` Contract. - */ - - function withdrawFromPod ( - address pod, - uint256 shareAmount, - uint256 maxFee, - uint256 getId, - uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _shareAmount = getUint(getId, shareAmount); - - PodInterface podContract = PodInterface(pod); - _shareAmount = _shareAmount == uint256(-1) ? podContract.balanceOf(address(this)) : _shareAmount; - - uint256 _tokenAmount = podContract.withdraw(_shareAmount, maxFee); - - convertWethToEth(address(podContract.token()) == wethAddr, TokenInterface(podContract.token()), _tokenAmount); - - setUint(setId, _tokenAmount); - - _eventName = "LogWithdrawFromPod(address,uint256,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(address(pod), _shareAmount, _tokenAmount, maxFee, getId, setId); - } } contract ConnectV2PoolTogether is PoolTogetherResolver { diff --git a/test/pooltogether-polygon/pooltogether.test.js b/test/pooltogether-polygon/pooltogether.test.js index 6dc2697b..4441f1bf 100644 --- a/test/pooltogether-polygon/pooltogether.test.js +++ b/test/pooltogether-polygon/pooltogether.test.js @@ -25,7 +25,6 @@ const PT_DAI_TICKET_ADDR = "0x334cBb5858417Aee161B53Ee0D5349cCF54514CF" // PT DA const DAI_POOL_FAUCET_ADDR = "0xF362ce295F2A4eaE4348fFC8cDBCe8d729ccb8Eb" // DAI POOL Faucet const POOL_TOKEN_ADDRESS = "0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e" // POOL Tocken const TOKEN_FAUCET_PROXY_FACTORY_ADDR = "0xE4E9cDB3E139D7E8a41172C20b6Ed17b6750f117" // TokenFaucetProxyFactory for claimAll -const DAI_POD_ADDR = "0x2f994e2E4F3395649eeE8A89092e63Ca526dA829" // DAI Pod const UNISWAP_POOLETHLP_PRIZE_POOL_ADDR = "0x3AF7072D29Adde20FC7e173a7CB9e45307d2FB0A" // Uniswap Pool/ETH LP PrizePool const UNISWAP_POOLETHLP_FAUCET_ADDR = "0x9A29401EF1856b669f55Ae5b24505b3B6fAEb370" // Uniswap Pool/ETH LP Faucet const UNISWAP_POOLETHLP_TOKEN_ADDR = "0x85cb0bab616fe88a89a35080516a8928f38b518b" // Uniswap Pool/ETH Token @@ -33,7 +32,6 @@ const PT_UNISWAP_POOLETHLP_TICKET_ADDR = "0xeb8928ee92efb06c44d072a24c2bcb993b61 const POOL_PRIZE_POOL_ADDR = "0x396b4489da692788e327e2e4b2b0459a5ef26791" // POOL Prize Pool const PT_POOL_TICKET_ADDR = "0x27d22a7648e955e510a40bdb058333e9190d12d4" // Pool Together POOL Ticket const WETH_ADDR = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" // WETH -const DAI_POD_TOKEN_DROP = "0xc5209623E3dFdf9C0cCbe497c8012883C4147731" // Community WETH Prize Pool (Rari): https://reference-app.pooltogether.com/pools/mainnet/0xa88ca010b32a54d446fc38091ddbca55750cbfc3/manage#stats const WETH_PRIZE_POOL_ADDR = "0xa88ca010b32a54d446fc38091ddbca55750cbfc3" // Community WETH Prize Pool (Rari) @@ -43,22 +41,6 @@ const prizePoolABI = [ "function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)" ] -const podABI = [ - "function getEarlyExitFee(uint256 amount) external returns (uint256)", - "function balanceOfUnderlying(address user) external view returns (uint256 amount)", - "function drop() public returns (uint256)", - "function balanceOf(address account) external view returns (uint256)" -] - -const POD_FACTORY_ADDRESS = "0x4e3a9f9fbafb2ec49727cffa2a411f7a0c1c4ce1" -const podFactoryABI = [ - "function create( address _prizePool, address _ticket, address _faucet, address _manager, uint8 _decimals) external returns (address pod)" -] - -const tokenDropABI = [ - "function claim(address user) external returns (uint256)", -] - describe("PoolTogether", function () { const connectorName = "COMPOUND-TEST-A" const uniswapConnectorName = "UNISWAP-TEST-A" @@ -354,185 +336,6 @@ describe("PoolTogether", function () { }); }) - describe("Main - DAI Pod Test", function() { - it("Should deposit 99 DAI in DAI Pod", async function() { - const amount = ethers.utils.parseEther("99") // 99 DAI - const spells = [ - { - connector: ptConnectorName, - method: "depositToPod", - args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0] - } - ] - - // Before spell - let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance equals 99`).to.be.eq(ethers.utils.parseEther("99")); - - let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) - const poolBalance = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR) - const podBalance = await podToken.balanceOf(dsaWallet0.address) - expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI equals 0`).to.be.eq(0); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalanceAfter, `POOL Token greater than 0`).to.be.gt(0); - - const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address) - expect(podBalanceAfter, `Pod DAI token greater than 0`).to.be.eq(ethers.utils.parseEther("99")); - }); - - it("Should claim rewards from pod token drop", async function() { - const spells = [ - { - connector: ptConnectorName, - method: "claimPodTokenDrop", - args: [DAI_POD_TOKEN_DROP, 0] - } - ] - - const tokenDropContract = new ethers.Contract(DAI_POD_TOKEN_DROP, tokenDropABI, ethers.provider); - const podContract = new ethers.Contract(DAI_POD_ADDR, podABI, masterSigner); - - // drop(): Claim TokenDrop asset for PrizePool Pod and transfers token(s) to external Pod TokenDrop - // dropt() also calls batch which, Deposit Pod float into PrizePool. Deposits the current float - // amount into the PrizePool and claims current POOL rewards. - const dropTx = await podContract.drop(); - await dropTx.wait(); - - // POOL Rewards able to claim from Pod Token Drop - let claimAmount = await tokenDropContract.callStatic["claim"](dsaWallet0.address); - - // Before spell - let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) - const poolBalance = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() - - // After spell - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) - const total = claimAmount.add(poolBalance); - expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq(total); - }); - - it("Should wait 11 days, withdraw all podTokens, get back 99 DAI", async function () { - const amount = ethers.utils.parseEther("99") // 99 DAI - - const podContract = new ethers.Contract(DAI_POD_ADDR, podABI, ethers.provider); - let maxFee = await podContract.callStatic["getEarlyExitFee"](amount); - // maxFee depends on if token has been deposited to PrizePool yet - // since we called drop in previous test case, the tokens were deposited to PrizePool - expect(maxFee, "Exit Fee equal to .99 DAI because token still in float").to.be.eq(ethers.utils.parseEther(".99")); - - const spells = [ - { - connector: ptConnectorName, - method: "withdrawFromPod", - args: [DAI_POD_ADDR, amount, maxFee, 0, 0] - } - ] - - // Before spell - let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI Balance equals 0`).to.be.eq(0); - - let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) - const poolBalance = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalance, `POOL Token balance greater than 0`).to.be.gt(0); - - let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR) - const podBalance = await podToken.balanceOf(dsaWallet0.address) - expect(podBalance, `Pod DAI Token equals 99`).to.be.eq(ethers.utils.parseEther("99")); - - // Increase time by 11 days so we get back all DAI without early withdrawal fee - await ethers.provider.send("evm_increaseTime", [11*24*60*60]); - await ethers.provider.send("evm_mine"); - - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, - `DAI balance equals 99, because of no early withdrawal fee` - ).to.be.eq(ethers.utils.parseEther("99")); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalanceAfter, `POOL Token to be greater than 0`).to.be.gt(0); - - const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address) - expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq(0); - }); - - - - - it("Should deposit and withdraw from pod, get back same amount of 99 DAI", async function() { - const amount = ethers.utils.parseEther("99") - const maxFee = 0; // maxFee 0 since it doesn't give chance for Pod to actually deposit into PrizePool - - const spells = [ - { - connector: ptConnectorName, - method: "depositToPod", - args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0] - }, - { - connector: ptConnectorName, - method: "withdrawFromPod", - args: [DAI_POD_ADDR, amount, maxFee, 0, 0] - } - ] - - // Before spell - let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI equals 99`).to.be.eq(ethers.utils.parseEther("99")); - - let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) - const poolBalance = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - // PodToken is 0 - let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR) - const podBalance = await podToken.balanceOf(dsaWallet0.address) - expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, - `DAI balance to be equal to 99, because funds still in 'float` - ).to.be.eq(ethers.utils.parseEther("99")); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq(poolBalance); - - // Expect Pod Token Balance to equal 0 - const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address) - expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq(ethers.utils.parseEther("0")); - }); - }) - describe("Main - UNISWAP POOL/ETH Prize Pool Test", function () { it("Should use uniswap to swap ETH for POOL, deposit to POOL/ETH LP, deposit POOL/ETH LP to PrizePool", async function () { const amount = ethers.utils.parseEther("100") // 100 POOL @@ -736,76 +539,4 @@ describe("PoolTogether", function () { expect(ethBalanceAfter, `ETH Balance equal to before spell because no early exit fee`).to.be.eq(ethBalanceBefore); }); }); - - describe("Main - WETH Pod Test", function() { - let podAddress - it("Should deposit 1 ETH in WETH Pod and get Pod Ticket", async function() { - const amount = ethers.utils.parseEther("1") - - // Create Pod for WETH Prize Pool (Rari) - const podFactoryContract = new ethers.Contract(POD_FACTORY_ADDRESS, podFactoryABI, masterSigner) - podAddress = await podFactoryContract.callStatic.create(WETH_PRIZE_POOL_ADDR, WETH_POOL_TICKET_ADDR, constants.address_zero, wallet0.address, 18) - await podFactoryContract.create(WETH_PRIZE_POOL_ADDR, WETH_POOL_TICKET_ADDR, constants.address_zero, wallet0.address, 18) - - const spells = [ - { - connector: ptConnectorName, - method: "depositToPod", - args: [WETH_ADDR, podAddress, amount, 0, 0] - } - ] - - // Before Deposit Spell - const podContract = new ethers.Contract(podAddress, podABI, ethers.provider); - let podBalanceBefore = await podContract.balanceOfUnderlying(dsaWallet0.address) - expect(podBalanceBefore, `Pod balance equal to 0`).to.be.eq(0); - - let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); - - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() - - // After Deposit spell - let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - expect(ethBalanceAfter, `ETH balance less than before`).to.be.lt(ethBalanceBefore); - - podBalanceAfter = await podContract.balanceOfUnderlying(dsaWallet0.address) - expect(podBalanceAfter, `Pod balance equal to 1`).to.be.eq(ethers.utils.parseEther("1")); - }); - - it("Should withdraw 1 Ticket from WETH Pod and get back ETH", async function() { - const amount = ethers.utils.parseEther("1") - - const podContract = new ethers.Contract(podAddress, podABI, ethers.provider); - let maxFee = await podContract.callStatic["getEarlyExitFee"](amount); - expect(maxFee, "Exit Fee equal to 0 DAI because token still in float").to.be.eq(0); - // maxFee depends on if token has been deposited to PrizePool yet - - const spells = [ - { - connector: ptConnectorName, - method: "withdrawFromPod", - args: [podAddress, amount, maxFee, 0, 0] - } - ] - - // Before Deposit Spell - let podBalanceBefore = await podContract.balanceOfUnderlying(dsaWallet0.address) - expect(podBalanceBefore, `Pod balance equal to 1`).to.be.eq(ethers.utils.parseEther("1")); - - let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); - - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() - - // After Deposit spell - let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - expect(ethBalanceAfter, `ETH balance greater than before`).to.be.gt(ethBalanceBefore); - - podBalanceAfter = await podContract.balanceOfUnderlying(dsaWallet0.address) - expect(podBalanceAfter, `Pod balance equal to 0`).to.be.eq(ethers.utils.parseEther("0")); - }); - }); }) \ No newline at end of file From b8aab9db5a317f403a72e30db09d7f3bef09b096 Mon Sep 17 00:00:00 2001 From: eccheung4 Date: Wed, 29 Sep 2021 08:22:42 -0700 Subject: [PATCH 3/8] fix: convert isEth and Weth to isMatic and Wmatic --- contracts/polygon/connectors/pooltogether/main.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/polygon/connectors/pooltogether/main.sol b/contracts/polygon/connectors/pooltogether/main.sol index e763e78e..854e34e4 100644 --- a/contracts/polygon/connectors/pooltogether/main.sol +++ b/contracts/polygon/connectors/pooltogether/main.sol @@ -40,12 +40,12 @@ abstract contract PoolTogetherResolver is Events, DSMath, Basic { PrizePoolInterface prizePoolContract = PrizePoolInterface(prizePool); address prizePoolToken = prizePoolContract.token(); - bool isEth = prizePoolToken == wethAddr; + bool isMatic = prizePoolToken == wmaticAddr; TokenInterface tokenContract = TokenInterface(prizePoolToken); - if (isEth) { + if (isMatic) { _amount = _amount == uint256(-1) ? address(this).balance : _amount; - convertEthToWeth(isEth, tokenContract, _amount); + convertMaticToWmatic(isMatic, tokenContract, _amount); } else { _amount = _amount == uint256(-1) ? tokenContract.balanceOf(address(this)) : _amount; } @@ -93,7 +93,7 @@ abstract contract PoolTogetherResolver is Events, DSMath, Basic { _amount = _amount - exitFee; - convertWethToEth(prizePoolToken == wethAddr, tokenContract, _amount); + convertWmaticToMatic(prizePoolToken == wmaticAddr, tokenContract, _amount); setUint(setId, _amount); From e503aac91c3066b36fbb76b922c68fe9fe49ad73 Mon Sep 17 00:00:00 2001 From: eccheung4 Date: Sun, 3 Oct 2021 07:02:56 -0700 Subject: [PATCH 4/8] Add: Initial copy of test files for mainnet --- scripts/polygon/buildDSAv2.js | 15 +++++++++++++ scripts/polygon/constant/addresses.js | 11 +++++++++ scripts/polygon/constant/constant.js | 5 +++++ scripts/polygon/constant/tokens.js | 23 +++++++++++++++++++ scripts/polygon/deployAndEnableConnector.js | 19 ++++++++++++++++ scripts/polygon/encodeSpells.js | 18 +++++++++++++++ scripts/polygon/getMasterSigner.js | 25 +++++++++++++++++++++ 7 files changed, 116 insertions(+) create mode 100644 scripts/polygon/buildDSAv2.js create mode 100644 scripts/polygon/constant/addresses.js create mode 100644 scripts/polygon/constant/constant.js create mode 100644 scripts/polygon/constant/tokens.js create mode 100644 scripts/polygon/deployAndEnableConnector.js create mode 100644 scripts/polygon/encodeSpells.js create mode 100644 scripts/polygon/getMasterSigner.js diff --git a/scripts/polygon/buildDSAv2.js b/scripts/polygon/buildDSAv2.js new file mode 100644 index 00000000..0f56a8c3 --- /dev/null +++ b/scripts/polygon/buildDSAv2.js @@ -0,0 +1,15 @@ +const hre = require("hardhat"); +const { ethers } = hre; +const addresses = require("./constant/addresses"); +const abis = require("./constant/abis"); + +const instaImplementations_m1 = require("../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json") + +module.exports = async function (owner) { + const instaIndex = await ethers.getContractAt(abis.core.instaIndex, addresses.core.instaIndex) + + const tx = await instaIndex.build(owner, 2, owner); + const receipt = await tx.wait() + const event = receipt.events.find(a => a.event === "LogAccountCreated") + return await ethers.getContractAt(instaImplementations_m1.abi, event.args.account) +}; diff --git a/scripts/polygon/constant/addresses.js b/scripts/polygon/constant/addresses.js new file mode 100644 index 00000000..77ee389e --- /dev/null +++ b/scripts/polygon/constant/addresses.js @@ -0,0 +1,11 @@ +module.exports = { + connectors: { + basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6", + auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9", + "INSTAPOOL-A": "0x5806af7ab22e2916fa582ff05731bf7c682387b2", + }, + core: { + connectorsV2: "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11", + instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723", + }, +}; diff --git a/scripts/polygon/constant/constant.js b/scripts/polygon/constant/constant.js new file mode 100644 index 00000000..1201972b --- /dev/null +++ b/scripts/polygon/constant/constant.js @@ -0,0 +1,5 @@ +module.exports = { + address_zero: "0x0000000000000000000000000000000000000000", + eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + max_value: "115792089237316195423570985008687907853269984665640564039457584007913129639935" +}; diff --git a/scripts/polygon/constant/tokens.js b/scripts/polygon/constant/tokens.js new file mode 100644 index 00000000..78c07fda --- /dev/null +++ b/scripts/polygon/constant/tokens.js @@ -0,0 +1,23 @@ +module.exports = { + "eth": { + "type": "token", + "symbol": "ETH", + "name": "Ethereum", + "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "decimals": 18 + }, + "dai": { + "type": "token", + "symbol": "DAI", + "name": "DAI Stable", + "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "decimals": 18 + }, + "usdc": { + "type": "token", + "symbol": "USDC", + "name": "USD Coin", + "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "decimals": 6 + } +} \ No newline at end of file diff --git a/scripts/polygon/deployAndEnableConnector.js b/scripts/polygon/deployAndEnableConnector.js new file mode 100644 index 00000000..42d331d1 --- /dev/null +++ b/scripts/polygon/deployAndEnableConnector.js @@ -0,0 +1,19 @@ +const abis = require("./constant/abis"); +const addresses = require("./constant/addresses"); + +const hre = require("hardhat"); +const { ethers, waffle } = hre; +const { deployContract } = waffle; +const fs = require("fs") + + +module.exports = async function ({connectorName, contractArtifact, signer, connectors}) { + const connectorInstanace = await deployContract(signer, contractArtifact, []); + + await connectors.connect(signer).addConnectors([connectorName], [connectorInstanace.address]) + + addresses.connectors[connectorName] = connectorInstanace.address + abis.connectors[connectorName] = contractArtifact.abi; + + return connectorInstanace; +}; diff --git a/scripts/polygon/encodeSpells.js b/scripts/polygon/encodeSpells.js new file mode 100644 index 00000000..719ca8be --- /dev/null +++ b/scripts/polygon/encodeSpells.js @@ -0,0 +1,18 @@ +const abis = require("./constant/abis"); +const addresses = require("./constant/addresses"); +const { web3 } = hre; + +module.exports = function (spells) { + const targets = spells.map(a => a.connector) + const calldatas = spells.map(a => { + const functionName = a.method; + // console.log(functionName) + const abi = abis.connectors[a.connector].find(b => { + return b.name === functionName + }); + // console.log(functionName) + if (!abi) throw new Error("Couldn't find function") + return web3.eth.abi.encodeFunctionCall(abi, a.args) + }) + return [targets, calldatas] +}; diff --git a/scripts/polygon/getMasterSigner.js b/scripts/polygon/getMasterSigner.js new file mode 100644 index 00000000..d0c19d6a --- /dev/null +++ b/scripts/polygon/getMasterSigner.js @@ -0,0 +1,25 @@ +const hre = require("hardhat"); +const { ethers } = hre; +const addresses = require("./constant/addresses"); +const abis = require("./constant/abis"); + +module.exports = async function() { + const [_, __, ___, wallet3] = await ethers.getSigners(); + const instaIndex = new ethers.Contract( + addresses.core.instaIndex, + abis.core.instaIndex, + wallet3 + ); + + const masterAddress = await instaIndex.master(); // TODO: make it constant? + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [masterAddress], + }); + await wallet3.sendTransaction({ + to: masterAddress, + value: ethers.utils.parseEther("10"), + }); + + return await ethers.getSigner(masterAddress); +}; From 4873bbf25f48f4d70f524dcff28a91c87382f47d Mon Sep 17 00:00:00 2001 From: eccheung4 Date: Mon, 4 Oct 2021 13:37:30 -0700 Subject: [PATCH 5/8] fix: update tests for polygon and use AAVE and USDC sponsor pool --- scripts/polygon/buildDSAv2.js | 4 +- scripts/polygon/constant/addresses.js | 9 +- scripts/polygon/constant/constant.js | 10 +- scripts/polygon/constant/tokens.js | 49 +- scripts/polygon/deployAndEnableConnector.js | 2 +- scripts/polygon/encodeSpells.js | 2 +- scripts/polygon/getMasterSigner.js | 2 +- .../pooltogether-polygon/pooltogether.test.js | 504 +++++++----------- 8 files changed, 234 insertions(+), 348 deletions(-) diff --git a/scripts/polygon/buildDSAv2.js b/scripts/polygon/buildDSAv2.js index 0f56a8c3..967d879f 100644 --- a/scripts/polygon/buildDSAv2.js +++ b/scripts/polygon/buildDSAv2.js @@ -1,9 +1,9 @@ const hre = require("hardhat"); const { ethers } = hre; const addresses = require("./constant/addresses"); -const abis = require("./constant/abis"); +const abis = require("../constant/abis"); -const instaImplementations_m1 = require("../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json") +const instaImplementations_m1 = require("../../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json") module.exports = async function (owner) { const instaIndex = await ethers.getContractAt(abis.core.instaIndex, addresses.core.instaIndex) diff --git a/scripts/polygon/constant/addresses.js b/scripts/polygon/constant/addresses.js index 77ee389e..baaaa3da 100644 --- a/scripts/polygon/constant/addresses.js +++ b/scripts/polygon/constant/addresses.js @@ -1,11 +1,10 @@ module.exports = { connectors: { - basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6", - auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9", - "INSTAPOOL-A": "0x5806af7ab22e2916fa582ff05731bf7c682387b2", + basic: "0x1cAF5EC802ca602E98139AD96A8f2B7BC524264E", + auth: "0xf6474aD0dA75A0dE15D2c915e601D9f754B9e6fe", }, core: { - connectorsV2: "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11", - instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723", + connectorsV2: "0x2A00684bFAb9717C21271E0751BCcb7d2D763c88", + instaIndex: "0xA9B99766E6C676Cf1975c0D3166F96C0848fF5ad", }, }; diff --git a/scripts/polygon/constant/constant.js b/scripts/polygon/constant/constant.js index 1201972b..62933314 100644 --- a/scripts/polygon/constant/constant.js +++ b/scripts/polygon/constant/constant.js @@ -1,5 +1,7 @@ module.exports = { - address_zero: "0x0000000000000000000000000000000000000000", - eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - max_value: "115792089237316195423570985008687907853269984665640564039457584007913129639935" -}; + address_zero: "0x0000000000000000000000000000000000000000", + eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + matic_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + max_value: "115792089237316195423570985008687907853269984665640564039457584007913129639935" + }; + \ No newline at end of file diff --git a/scripts/polygon/constant/tokens.js b/scripts/polygon/constant/tokens.js index 78c07fda..55946203 100644 --- a/scripts/polygon/constant/tokens.js +++ b/scripts/polygon/constant/tokens.js @@ -1,23 +1,30 @@ module.exports = { - "eth": { - "type": "token", - "symbol": "ETH", - "name": "Ethereum", - "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "decimals": 18 - }, - "dai": { - "type": "token", - "symbol": "DAI", - "name": "DAI Stable", - "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F", - "decimals": 18 - }, - "usdc": { - "type": "token", - "symbol": "USDC", - "name": "USD Coin", - "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "decimals": 6 - } + "matic": { + "type": "token", + "symbol": "MATIC", + "name": "Matic", + "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "decimals": 18 + }, + "eth": { + "type": "token", + "symbol": "ETH", + "name": "Ethereum", + "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "decimals": 18 + }, + "dai": { + "type": "token", + "symbol": "DAI", + "name": "DAI Stable", + "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + "decimals": 18 + }, + "usdc": { + "type": "token", + "symbol": "USDC", + "name": "USD Coin", + "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + "decimals": 6 + } } \ No newline at end of file diff --git a/scripts/polygon/deployAndEnableConnector.js b/scripts/polygon/deployAndEnableConnector.js index 42d331d1..52d80b5e 100644 --- a/scripts/polygon/deployAndEnableConnector.js +++ b/scripts/polygon/deployAndEnableConnector.js @@ -1,4 +1,4 @@ -const abis = require("./constant/abis"); +const abis = require("../constant/abis"); const addresses = require("./constant/addresses"); const hre = require("hardhat"); diff --git a/scripts/polygon/encodeSpells.js b/scripts/polygon/encodeSpells.js index 719ca8be..ba1cddcb 100644 --- a/scripts/polygon/encodeSpells.js +++ b/scripts/polygon/encodeSpells.js @@ -1,4 +1,4 @@ -const abis = require("./constant/abis"); +const abis = require("../constant/abis"); const addresses = require("./constant/addresses"); const { web3 } = hre; diff --git a/scripts/polygon/getMasterSigner.js b/scripts/polygon/getMasterSigner.js index d0c19d6a..9edb0417 100644 --- a/scripts/polygon/getMasterSigner.js +++ b/scripts/polygon/getMasterSigner.js @@ -1,7 +1,7 @@ const hre = require("hardhat"); const { ethers } = hre; const addresses = require("./constant/addresses"); -const abis = require("./constant/abis"); +const abis = require("../constant/abis"); module.exports = async function() { const [_, __, ___, wallet3] = await ethers.getSigners(); diff --git a/test/pooltogether-polygon/pooltogether.test.js b/test/pooltogether-polygon/pooltogether.test.js index 4441f1bf..358d5dc4 100644 --- a/test/pooltogether-polygon/pooltogether.test.js +++ b/test/pooltogether-polygon/pooltogether.test.js @@ -3,66 +3,75 @@ const hre = require("hardhat"); const { web3, deployments, waffle, ethers } = hre; const { provider, deployContract } = waffle -const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") -const buildDSAv2 = require("../../scripts/buildDSAv2") -const encodeSpells = require("../../scripts/encodeSpells.js") -const getMasterSigner = require("../../scripts/getMasterSigner") +const ALCHEMY_ID = process.env.ALCHEMY_ID; -const addresses = require("../../scripts/constant/addresses"); +const deployAndEnableConnector = require("../../scripts/polygon/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/polygon/buildDSAv2") +const encodeSpells = require("../../scripts/polygon/encodeSpells.js") +const getMasterSigner = require("../../scripts/polygon/getMasterSigner") + +const addresses = require("../../scripts/polygon/constant/addresses"); const abis = require("../../scripts/constant/abis"); -const constants = require("../../scripts/constant/constant"); -const tokens = require("../../scripts/constant/tokens"); +const constants = require("../../scripts/polygon/constant/constant"); +const tokens = require("../../scripts/polygon/constant/tokens"); -const connectV2CompoundArtifacts = require("../../artifacts/contracts/mainnet/connectors/compound/main.sol/ConnectV2Compound.json") -const connectV2PoolTogetherArtifacts = require("../../artifacts/contracts/mainnet/connectors/pooltogether/main.sol/ConnectV2PoolTogether.json") -const connectV2UniswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/uniswap/main.sol/ConnectV2UniswapV2.json") +const connectV2AaveV2Artifacts = require("../../artifacts/contracts/polygon/connectors/aave/v2/main.sol/ConnectV2AaveV2Polygon.json") +const connectV2PoolTogetherArtifacts = require("../../artifacts/contracts/polygon/connectors/pooltogether/main.sol/ConnectV2PoolTogether.json") const DAI_TOKEN_ADDR = tokens.dai.address // DAI Token - -// PoolTogether Address: https://docs.pooltogether.com/resources/networks/ethereum -const DAI_PRIZE_POOL_ADDR = "0xEBfb47A7ad0FD6e57323C8A42B2E5A6a4F68fc1a" // DAI Prize Pool -const PT_DAI_TICKET_ADDR = "0x334cBb5858417Aee161B53Ee0D5349cCF54514CF" // PT DAI Ticket -const DAI_POOL_FAUCET_ADDR = "0xF362ce295F2A4eaE4348fFC8cDBCe8d729ccb8Eb" // DAI POOL Faucet -const POOL_TOKEN_ADDRESS = "0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e" // POOL Tocken -const TOKEN_FAUCET_PROXY_FACTORY_ADDR = "0xE4E9cDB3E139D7E8a41172C20b6Ed17b6750f117" // TokenFaucetProxyFactory for claimAll -const UNISWAP_POOLETHLP_PRIZE_POOL_ADDR = "0x3AF7072D29Adde20FC7e173a7CB9e45307d2FB0A" // Uniswap Pool/ETH LP PrizePool -const UNISWAP_POOLETHLP_FAUCET_ADDR = "0x9A29401EF1856b669f55Ae5b24505b3B6fAEb370" // Uniswap Pool/ETH LP Faucet -const UNISWAP_POOLETHLP_TOKEN_ADDR = "0x85cb0bab616fe88a89a35080516a8928f38b518b" // Uniswap Pool/ETH Token -const PT_UNISWAP_POOLETHLP_TICKET_ADDR = "0xeb8928ee92efb06c44d072a24c2bcb993b61e543" // Pool Together Uniswap Pool/ETH LP Ticket -const POOL_PRIZE_POOL_ADDR = "0x396b4489da692788e327e2e4b2b0459a5ef26791" // POOL Prize Pool -const PT_POOL_TICKET_ADDR = "0x27d22a7648e955e510a40bdb058333e9190d12d4" // Pool Together POOL Ticket -const WETH_ADDR = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" // WETH +// PoolTogether Address: https://docs.pooltogether.com/resources/networks/matic +const USDC_PRIZE_POOL_ADDR = "0xEE06AbE9e2Af61cabcb13170e01266Af2DEFa946" // USDC Prize Pool +const PT_USDC_TICKET_ADDR = "0x473E484c722EF9ec6f63B509b07Bb9cfB258820b" // PT USDC Ticket +const PT_USDC_SPONGSOR_TICKET_ADDR = "0x19c0e557ee5a9b456f613ba3d025a4dc45b52c35" // PT USDC Sponsor Ticket +const USDC_POOL_FAUCET_ADDR = "0x6cbc003fE015D753180f072d904bA841b2415498" // USDC POOL Faucet +const POOL_TOKEN_ADDRESS = "0x25788a1a171ec66Da6502f9975a15B609fF54CF6" // POOL Tocken +const TOKEN_FAUCET_PROXY_FACTORY_ADDR = "0xeaa636304a7C8853324B6b603dCdE55F92dfbab1" // TokenFaucetProxyFactory for claimAll // Community WETH Prize Pool (Rari): https://reference-app.pooltogether.com/pools/mainnet/0xa88ca010b32a54d446fc38091ddbca55750cbfc3/manage#stats const WETH_PRIZE_POOL_ADDR = "0xa88ca010b32a54d446fc38091ddbca55750cbfc3" // Community WETH Prize Pool (Rari) const WETH_POOL_TICKET_ADDR = "0x9b5c30aeb9ce2a6a121cea9a85bc0d662f6d9b40" // Community WETH Prize Pool Ticket (Rari) const prizePoolABI = [ - "function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)" + "function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)", + "function creditPlanOf( address controlledToken) external view returns ( uint128 creditLimitMantissa, uint128 creditRateMantissa)" +] + +const connectorsABI = [ + "function isConnectors(string[] calldata connectorNames) external view returns (bool, address[] memory)" ] describe("PoolTogether", function () { - const connectorName = "COMPOUND-TEST-A" - const uniswapConnectorName = "UNISWAP-TEST-A" + const connectorName = "AAVEV2-TEST-A" const ptConnectorName = "POOLTOGETHER-TEST-A" - + let dsaWallet0 let masterSigner; let instaConnectorsV2; let connector; let ptConnector; - let uniswapConnector; const wallets = provider.getWallets() const [wallet0, wallet1, wallet2, wallet3] = wallets before(async () => { - masterSigner = await getMasterSigner(wallet3) + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: `https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_ID}`, + blockNumber: 18717337, + }, + }, + ], + }); + + masterSigner = await getMasterSigner() instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); // Deploy and enable Compound Connector connector = await deployAndEnableConnector({ connectorName, - contractArtifact: connectV2CompoundArtifacts, + contractArtifact: connectV2AaveV2Artifacts, signer: masterSigner, connectors: instaConnectorsV2 }) @@ -74,21 +83,12 @@ describe("PoolTogether", function () { signer: masterSigner, connectors: instaConnectorsV2 }) - - // Deploy and enable Uniswap Connector - uniswapConnector = await deployAndEnableConnector({ - connectorName: uniswapConnectorName, - contractArtifact: connectV2UniswapArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) }) it("Should have contracts deployed.", async function () { expect(!!instaConnectorsV2.address).to.be.true; expect(!!connector.address).to.be.true; expect(!!ptConnector.address).to.be.true; - expect(!!uniswapConnector.address).to.be.true; expect(!!masterSigner.address).to.be.true; }); @@ -98,152 +98,159 @@ describe("PoolTogether", function () { expect(!!dsaWallet0.address).to.be.true; }); - it("Deposit 10 ETH into DSA wallet", async function () { + it("Deposit 1000 MATIC into DSA wallet", async function () { await wallet0.sendTransaction({ to: dsaWallet0.address, - value: ethers.utils.parseEther("10") + value: ethers.utils.parseEther("1000") }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("1000")); }); }); - describe("Main - DAI Prize Pool Test", function () { + describe("Main - USDC Prize Pool Test", function () { - it("Should deposit 1 ETH in Compound", async function () { - const amount = ethers.utils.parseEther("1") // 1 ETH + it("Should deposit 100 MATIC in AAVE V2", async function () { + const amount = ethers.utils.parseEther("100") // 100 MATIC const spells = [ { connector: connectorName, method: "deposit", - args: ["ETH-A", amount, 0, 0] + args: [tokens.matic.address, amount, 0, 0] } ] - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + const tx = await dsaWallet0.cast(...encodeSpells(spells), wallet1.address) const receipt = await tx.wait() - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("900")); }); - it("Should borrow 100 DAI from Compound and deposit DAI into DAI Prize Pool", async function () { - const amount = ethers.utils.parseEther("100") // 100 DAI + it("Should borrow 10 USDC from AAVE V2 and deposit USDC into USDC Prize Pool", async function () { + const amount = ethers.utils.parseUnits("10", 6) // 10 USDC const setId = "83478237" const spells = [ { connector: connectorName, method: "borrow", - args: ["DAI-A", amount, 0, setId] + args: [tokens.usdc.address, amount, 2, 0, setId] }, { connector: ptConnectorName, method: "depositTo", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, setId, 0] + args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_SPONGSOR_TICKET_ADDR, setId, 0] } ] // Before Spell - let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance is 0`).to.be.eq(ethers.utils.parseEther("0")); + let usdcToken = await ethers.getContractAt(abis.basic.erc20, tokens.usdc.address) + let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address); + expect(usdcBalance, `USDC balance is 0`).to.be.eq(ethers.utils.parseUnits("0", 6)); - let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR) + let cToken = await ethers.getContractAt(abis.basic.erc20, PT_USDC_SPONGSOR_TICKET_ADDR) const balance = await cToken.balanceOf(dsaWallet0.address) - expect(balance,`PoolTogether DAI Ticket balance is 0`).to.be.eq(0); + expect(balance,`PoolTogether USDC Ticket balance is 0`).to.be.eq(0); // Run spell transaction const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) const receipt = await tx.wait() // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `Expect DAI balance to still equal 0 since it was deposited into Prize Pool`).to.be.eq(0); + usdcBalance = await usdcToken.balanceOf(dsaWallet0.address); + expect(usdcBalance, `Expect USDC balance to still equal 0 since it was deposited into Prize Pool`).to.be.eq(0); const balanceAfter = await cToken.balanceOf(dsaWallet0.address) - expect(balanceAfter, `PoolTogether DAI Ticket balance equals 100`).to.be.eq(ethers.utils.parseEther("100")); + expect(balanceAfter, `PoolTogether USDC Ticket balance equals 10`).to.be.eq(ethers.utils.parseUnits("10", 6)); // ETH used for transaction - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("900")); }); - it("Should wait 11 days, withdraw all PrizePool, get back 100 DAI, and claim POOL", async function () { - const amount = ethers.utils.parseEther("100") // 100 DAI + it("Should wait 11 days, withdraw all PrizePool, get back 10 USDC, and claim POOL", async function () { + const amount = ethers.utils.parseUnits("10", 6) // 10 USDC - let prizePoolContract = new ethers.Contract(DAI_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider); - let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); - expect(earlyExitFee.exitFee, "Exit Fee equal to 1 DAI because starts at 10%").to.be.eq(ethers.utils.parseEther("1")); + let prizePoolContract = new ethers.Contract(USDC_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider); + // const { creditLimitMantissa, creditRateMantissa } = await prizePoolContract.creditPlanOf(PT_USDC_TICKET_ADDR); + // console.log("CreditLimitMantiss: ", creditLimitMantissa.toString()); + // console.log("CreditRateMantiss: ", creditRateMantissa.toString()); + let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount); + expect(earlyExitFee.exitFee, "Exit Fee equal to 0 USDC because 0% fee for sponsorship ticket").to.be.eq(ethers.utils.parseUnits("0", 6)); const spells = [ { connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, earlyExitFee.exitFee, 0, 0] + method: "claim", + args: [USDC_POOL_FAUCET_ADDR, 0] }, { - connector: ptConnectorName, - method: "claim", - args: [DAI_POOL_FAUCET_ADDR, 0] - } + connector: ptConnectorName, + method: "withdrawInstantlyFrom", + args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_SPONGSOR_TICKET_ADDR, earlyExitFee.exitFee, 0, 0] + } + ] // Before spell - let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance equals 0`).to.be.eq(ethers.utils.parseEther("0")); + let usdcToken = await ethers.getContractAt(abis.basic.erc20, tokens.usdc.address) + let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address); + expect(usdcBalance, `USDC balance equals 0`).to.be.eq(ethers.utils.parseEther("0")); - let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR) + let cToken = await ethers.getContractAt(abis.basic.erc20, PT_USDC_SPONGSOR_TICKET_ADDR) const balance = await cToken.balanceOf(dsaWallet0.address) - expect(balance, `PoolTogether Dai Ticket is 100`).to.be.eq(ethers.utils.parseEther("100")); + expect(balance, `PoolTogether USDC Ticket is 10`).to.be.eq(ethers.utils.parseUnits("10", 6)); let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) const poolBalance = await poolToken.balanceOf(dsaWallet0.address) expect(poolBalance, `POOL Token equals 0`).to.be.eq(ethers.utils.parseEther("0")); - // Increase time by 11 days so we get back all DAI without early withdrawal fee - await ethers.provider.send("evm_increaseTime", [11*24*60*60]); + // Increase time by 11 days so we get back all USDC without early withdrawal fee + await ethers.provider.send("evm_increaseTime", [15*24*60*60]); await ethers.provider.send("evm_mine"); - earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); - expect(earlyExitFee.exitFee, "Exit Fee equal to 0 DAI because past 10 days").to.be.eq(0); + earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount); + expect(earlyExitFee.exitFee, "Exit Fee equal to 0 DAI because past 14 days").to.be.eq(0); // Run spell transaction const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) const receipt = await tx.wait() // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, - `DAI balance to be equal to 100, because of no early withdrawal fee` - ).to.be.eq(ethers.utils.parseEther("100")); + usdcBalance = await usdcToken.balanceOf(dsaWallet0.address); + console.log("USDC BALANCE: ", usdcBalance.toString()); + console.log("USDC BALANCE: ", ethers.utils.parseUnits("10", 6).toString()); + expect(usdcBalance, + `USDC balance to be equal to 10, because of no early withdrawal fee` + ).to.be.eq(ethers.utils.parseUnits("10", 6)); const balanceAfter = await cToken.balanceOf(dsaWallet0.address) - expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0); + expect(balanceAfter, `PoolTogether USDC Ticket to equal 0`).to.be.eq(0); const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) + console.log("POOL BALANCE AFTER:" ,poolBalanceAfter.toString()); expect(poolBalanceAfter, `POOL Token Balance to be greater than 0`).to.be.gt(ethers.utils.parseEther("0")); }); - it("Should deposit and withdraw all PrizePool, get back less than 100 DAI", async function() { - const amount = ethers.utils.parseEther("100") // 100 DAI - const exitFee = ethers.utils.parseEther("1") // 1 DAI is 10% of 100 DAI + it("Should deposit and withdraw all PrizePool, get back less than 10 USDC", async function() { + const amount = ethers.utils.parseUnits("10", 6) // 10 USDC + const exitFee = ethers.utils.parseUnits(".1", 6) // 1 USDC is 1% of 100 USDC const spells = [ { connector: ptConnectorName, method: "depositTo", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0] + args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_TICKET_ADDR, 0, 0] }, { connector: ptConnectorName, method: "withdrawInstantlyFrom", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, exitFee, 0, 0] + args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_TICKET_ADDR, exitFee, 0, 0] } ] // Before spell - let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI Balance equals 0`).to.be.eq(ethers.utils.parseEther("100")); + let usdcToken = await ethers.getContractAt(abis.basic.erc20, tokens.usdc.address) + let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address); + expect(usdcBalance, `USDC Balance equals 100`).to.be.eq(ethers.utils.parseUnits("10", 6)); - let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR) + let cToken = await ethers.getContractAt(abis.basic.erc20, PT_USDC_TICKET_ADDR) const balance = await cToken.balanceOf(dsaWallet0.address) - expect(balance, `PoolTogether DAI Ticket equals 0`).to.be.eq(0); + expect(balance, `PoolTogether USDC Ticket equals 0`).to.be.eq(0); let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) const poolBalance = await poolToken.balanceOf(dsaWallet0.address) @@ -254,37 +261,39 @@ describe("PoolTogether", function () { const receipt = await tx.wait() // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, - `DAI balance to be less than 100, because of early withdrawal fee` - ).to.be.lt(ethers.utils.parseEther("100")); + usdcBalance = await usdcToken.balanceOf(dsaWallet0.address); + expect(usdcBalance, + `USDC balance to be less than 10, because of early withdrawal fee` + ).to.be.lt(ethers.utils.parseUnits("10",6)); + + console.log("USDC BALANCE AFTER:", usdcBalance.toString()); const balanceAfter = await cToken.balanceOf(dsaWallet0.address) - expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0); + expect(balanceAfter, `PoolTogether USDC Ticket to equal 0`).to.be.eq(0); const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) expect(poolBalanceAfter, `POOL Token Balance to greater than 0`).to.be.gt(ethers.utils.parseEther("0")); }); - it("Should deposit, wait 11 days, and withdraw all PrizePool, get 99 DAI, and claim all POOL using claimAll", async function() { - const amount = ethers.utils.parseEther("99") // 99 DAI + it("Should deposit, wait 11 days, and withdraw all PrizePool, get 10 USDC, and claim all POOL using claimAll", async function() { + const amount = ethers.utils.parseUnits("9.9", 6) // 9 USDC const depositSpells = [ { connector: ptConnectorName, method: "depositTo", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0] + args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_SPONGSOR_TICKET_ADDR, 0, 0] } ] // Before spell - let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR) - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance less than 100`).to.be.lt(ethers.utils.parseEther("100")); + let usdcToken = await ethers.getContractAt(abis.basic.erc20, tokens.usdc.address) + let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address); + expect(usdcBalance, `USDC balance less than 10`).to.be.lt(ethers.utils.parseUnits("10", 6)); - let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR) + let cToken = await ethers.getContractAt(abis.basic.erc20, PT_USDC_SPONGSOR_TICKET_ADDR) const balance = await cToken.balanceOf(dsaWallet0.address) - expect(balance, `PoolTogether DAI Ticket equal 0`).to.be.eq(0); + expect(balance, `PoolTogether USDC Ticket equal 0`).to.be.eq(0); let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) const poolBalance = await poolToken.balanceOf(dsaWallet0.address) @@ -294,28 +303,24 @@ describe("PoolTogether", function () { const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpells), wallet1.address) const receipt = await tx.wait() - const prizePoolContract = new ethers.Contract(DAI_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider); - let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); - expect(earlyExitFee.exitFee, "Exit Fee equal to .99 DAI because starts at 10%").to.be.eq(ethers.utils.parseEther(".99")); - + const prizePoolContract = new ethers.Contract(USDC_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider); + let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount); + expect(earlyExitFee.exitFee, "Exit Fee equal to 0 USDC because fee 0%").to.be.eq(0); // Increase time by 11 days so we get back all DAI without early withdrawal fee await ethers.provider.send("evm_increaseTime", [11*24*60*60]); await ethers.provider.send("evm_mine"); - earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); - expect(earlyExitFee.exitFee, "Exit Fee equal to 0 DAI because past 10 days").to.be.eq(0); - const withdrawSpells = [ { connector: ptConnectorName, method: "withdrawInstantlyFrom", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, earlyExitFee.exitFee, 0, 0] + args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_SPONGSOR_TICKET_ADDR, earlyExitFee.exitFee, 0, 0] }, { connector: ptConnectorName, method: "claimAll", - args: [TOKEN_FAUCET_PROXY_FACTORY_ADDR, [DAI_POOL_FAUCET_ADDR]] + args: [TOKEN_FAUCET_PROXY_FACTORY_ADDR, [USDC_POOL_FAUCET_ADDR]] } ] @@ -324,219 +329,92 @@ describe("PoolTogether", function () { const receipt2 = await tx2.wait() // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance equals 99`).to.be.eq(ethers.utils.parseEther("99")); + usdcBalance = await usdcToken.balanceOf(dsaWallet0.address); + expect(usdcBalance, `USDC balance equals 9.9`).to.be.eq(ethers.utils.parseUnits("9.9", 6)); const balanceAfter = await cToken.balanceOf(dsaWallet0.address) - expect(balanceAfter, `PoolTogether DAI Ticket equal 0`).to.be.eq(0); + expect(balanceAfter, `PoolTogether USDC Ticket equal 0`).to.be.eq(0); // Expect const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalanceAfter, `Pool Token to be greateir than 0`).to.be.gt(ethers.utils.parseEther("0")); + console.log("POOL BALANCE AFTER:" ,poolBalanceAfter.toString()); + expect(poolBalanceAfter, `Pool Token to be greater than before`).to.be.gt(poolBalance); }); - }) + // }) - describe("Main - UNISWAP POOL/ETH Prize Pool Test", function () { - it("Should use uniswap to swap ETH for POOL, deposit to POOL/ETH LP, deposit POOL/ETH LP to PrizePool", async function () { - const amount = ethers.utils.parseEther("100") // 100 POOL - const slippage = ethers.utils.parseEther("0.03"); - const setId = "83478237" +// NO WMATIC POOLS: https://reference-app.pooltogether.com/pools/polygon +// describe("Main - WETH Prize Pool Test", function () { +// it("Deposit 1 ETH into WETH Prize Pool and withdraw immediately", async function () { +// const amount = ethers.utils.parseEther("1") // 1 ETH +// const setId = "83478237" +// const spells = [ +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, setId] +// }, +// { +// connector: ptConnectorName, +// method: "withdrawInstantlyFrom", +// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, setId, 0] +// }, +// ] +// // Before Spell +// const ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); - const UniswapV2Router02ABI = [ - "function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)" - ]; +// // Run spell transaction +// const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) +// const receipt = await tx.wait() - // Get amount of ETH for 100 POOL from Uniswap - const UniswapV2Router02 = await ethers.getContractAt(UniswapV2Router02ABI, "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"); - const amounts = await UniswapV2Router02.getAmountsOut(amount, [POOL_TOKEN_ADDRESS, WETH_ADDR]); - const unitAmount = ethers.utils.parseEther(((amounts[1]*1.03)/amounts[0]).toString()); +// // After spell +// const ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - const spells = [ - { - connector: uniswapConnectorName, - method: "buy", - args: [POOL_TOKEN_ADDRESS, tokens.eth.address, amount, unitAmount, 0, setId] - }, - { - connector: uniswapConnectorName, - method: "deposit", - args: [POOL_TOKEN_ADDRESS, tokens.eth.address, amount, unitAmount, slippage, 0, setId] - }, - { - connector: ptConnectorName, - method: "depositTo", - args: [UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, 0, PT_UNISWAP_POOLETHLP_TICKET_ADDR, setId, 0] - } - ] +// // ETH used for transaction +// expect(ethBalanceAfter, `ETH Balance less than before spell because of early withdrawal fee`).to.be.lte(ethBalanceBefore); +// }); - // Before Spell - let ethBalance = await ethers.provider.getBalance(dsaWallet0.address); - expect(ethBalance, `ETH Balance equals 9`).to.be.eq(ethers.utils.parseEther("9")); +// it("Deposit 1 ETH into WETH Prize Pool, wait 14 days, then withdraw", async function () { +// const amount = ethers.utils.parseEther("1") // 1 ETH +// const depositSpell = [ +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, 0] +// } +// ] - let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) - const poolBalance = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); +// const withdrawSpell = [ +// { +// connector: ptConnectorName, +// method: "withdrawInstantlyFrom", +// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, 0, 0] +// } +// ] - let uniswapLPToken = await ethers.getContractAt(abis.basic.erc20, UNISWAP_POOLETHLP_TOKEN_ADDR) - const uniswapPoolEthBalance = await uniswapLPToken.balanceOf(dsaWallet0.address) - expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); +// // Before Deposit Spell +// let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); - let ptUniswapPoolEthToken = await ethers.getContractAt(abis.basic.erc20, PT_UNISWAP_POOLETHLP_TICKET_ADDR) - const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address) - expect(ptUniswapPoolEthBalance, `PoolTogether Uniswap POOL?ETH LP equals 0`).to.be.eq(0); +// // Run deposit spell transaction +// const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpell), wallet1.address) +// const receipt = await tx.wait() - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() +// // After Deposit spell +// let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - // After spell - ethBalance = await ethers.provider.getBalance(dsaWallet0.address); - expect(ethBalance, `ETH Balance less than 9`).to.be.lt(ethers.utils.parseEther("9")); +// expect(ethBalanceAfter, `ETH Balance less than before spell`).to.be.lte(ethBalanceBefore); - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalanceAfter, `POOL Token to be same after spell`).to.be.eq(poolBalance); +// // Increase time by 11 days so we get back all ETH without early withdrawal fee +// await ethers.provider.send("evm_increaseTime", [14*24*60*60]); +// await ethers.provider.send("evm_mine"); - const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf(dsaWallet0.address) - expect(uniswapPoolEthBalanceAfter, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); +// // Run withdraw spell transaction +// const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpell), wallet1.address) +// const receipt2 = await tx.wait() - const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address) - expect(ptUniswapPoolEthBalanceAfter, `PT Uniswap POOL/ETH LP to greater than 0`).to.be.gt(0); - }); +// // After Deposit spell +// ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - it("Should withdraw all PrizePool, get back Uniswap LP, claim POOL, deposit claimed POOL into Pool PrizePool", async function () { - let ptUniswapPoolEthToken = await ethers.getContractAt(abis.basic.erc20, PT_UNISWAP_POOLETHLP_TICKET_ADDR) - const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address) - const setId = "83478237" - - let uniswapPrizePoolContract = new ethers.Contract(UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider); - let earlyExitFee = await uniswapPrizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_UNISWAP_POOLETHLP_TICKET_ADDR, ptUniswapPoolEthBalance); - expect(earlyExitFee.exitFee, "Exit Fee equals 0 because no early exit fee for this prize pool").to.be.eq(0); - - const spells = [ - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, ptUniswapPoolEthBalance, PT_UNISWAP_POOLETHLP_TICKET_ADDR, earlyExitFee.exitFee, 0, 0] - }, - { - connector: ptConnectorName, - method: "claim", - args: [UNISWAP_POOLETHLP_FAUCET_ADDR , setId] - }, - { - connector: ptConnectorName, - method: "depositTo", - args: [POOL_PRIZE_POOL_ADDR, 0, PT_POOL_TICKET_ADDR, setId, 0] - } - ] - - // Before spell - let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS) - const poolBalance = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - // Uniswap POOL/ETH LP is 0 - let uniswapLPToken = await ethers.getContractAt(abis.basic.erc20, UNISWAP_POOLETHLP_TOKEN_ADDR) - const uniswapPoolEthBalance = await uniswapLPToken.balanceOf(dsaWallet0.address) - expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); - - expect(ptUniswapPoolEthBalance, `PT Uniswap POOL/ETH LP greater than 0`).to.be.gt(0); - - let poolPoolTicket = await ethers.getContractAt(abis.basic.erc20, PT_POOL_TICKET_ADDR) - const poolPoolTicketBalance = await poolPoolTicket.balanceOf(dsaWallet0.address) - expect(poolPoolTicketBalance, `PoolTogether POOL Ticket equals 0`).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() - - // After spell - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address) - expect(poolBalanceAfter, `Pool Token Balance equal to balance before spell`).to.be.eq(poolBalance); - - const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf(dsaWallet0.address) - expect(uniswapPoolEthBalanceAfter, `Uniswap POOL/ETH LP to greater than 0`).to.be.gt(0); - - const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address) - expect(ptUniswapPoolEthBalanceAfter, `PT Uniswap POOL/ETH LP equal 0`).to.be.eq(0); - - const poolPoolTicketBalanceAfter = await poolPoolTicket.balanceOf(dsaWallet0.address) - expect(poolPoolTicketBalanceAfter, `PoolTogether POOL Ticket greater than 0`).to.be.gt(0); - }); - }) - - describe("Main - WETH Prize Pool Test", function () { - it("Deposit 1 ETH into WETH Prize Pool and withdraw immediately", async function () { - const amount = ethers.utils.parseEther("1") // 1 ETH - const setId = "83478237" - const spells = [ - { - connector: ptConnectorName, - method: "depositTo", - args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, setId] - }, - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, setId, 0] - }, - ] - // Before Spell - const ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); - - // Run spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - const receipt = await tx.wait() - - // After spell - const ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - - // ETH used for transaction - expect(ethBalanceAfter, `ETH Balance less than before spell because of early withdrawal fee`).to.be.lte(ethBalanceBefore); - }); - - it("Deposit 1 ETH into WETH Prize Pool, wait 14 days, then withdraw", async function () { - const amount = ethers.utils.parseEther("1") // 1 ETH - const depositSpell = [ - { - connector: ptConnectorName, - method: "depositTo", - args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, 0] - } - ] - - const withdrawSpell = [ - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, 0, 0] - } - ] - - // Before Deposit Spell - let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address); - - // Run deposit spell transaction - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpell), wallet1.address) - const receipt = await tx.wait() - - // After Deposit spell - let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - - expect(ethBalanceAfter, `ETH Balance less than before spell`).to.be.lte(ethBalanceBefore); - - // Increase time by 11 days so we get back all ETH without early withdrawal fee - await ethers.provider.send("evm_increaseTime", [14*24*60*60]); - await ethers.provider.send("evm_mine"); - - // Run withdraw spell transaction - const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpell), wallet1.address) - const receipt2 = await tx.wait() - - // After Deposit spell - ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - - expect(ethBalanceAfter, `ETH Balance equal to before spell because no early exit fee`).to.be.eq(ethBalanceBefore); - }); +// expect(ethBalanceAfter, `ETH Balance equal to before spell because no early exit fee`).to.be.eq(ethBalanceBefore); +// }); }); }) \ No newline at end of file From 3cce1ec319494c56e7b89e59c86bebaef557cb1b Mon Sep 17 00:00:00 2001 From: eccheung4 Date: Mon, 4 Oct 2021 13:38:05 -0700 Subject: [PATCH 6/8] fix: update AAVE to polygon addresses --- contracts/polygon/connectors/aave/v2/helpers.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/polygon/connectors/aave/v2/helpers.sol b/contracts/polygon/connectors/aave/v2/helpers.sol index 7d5b9836..3d97d0a0 100644 --- a/contracts/polygon/connectors/aave/v2/helpers.sol +++ b/contracts/polygon/connectors/aave/v2/helpers.sol @@ -9,12 +9,12 @@ abstract contract Helpers is DSMath, Basic { /** * @dev Aave Lending Pool Provider */ - AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); + AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xd05e3E715d945B59290df0ae8eF85c1BdB684744); /** * @dev Aave Protocol Data Provider */ - AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); + AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x7551b5D2763519d4e37e8B81929D336De671d46d); /** * @dev Aave Referral Code From cb218493668c53b67d0c12ac92cce48cbf336aad Mon Sep 17 00:00:00 2001 From: Edwin Cheung <1091173+eccheung4@users.noreply.github.com> Date: Wed, 6 Oct 2021 13:08:31 -0700 Subject: [PATCH 7/8] fix: Update to ConnectV2PoolTogetherPolygon Co-authored-by: Thrilok kumar --- contracts/polygon/connectors/pooltogether/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/polygon/connectors/pooltogether/main.sol b/contracts/polygon/connectors/pooltogether/main.sol index 854e34e4..eb120527 100644 --- a/contracts/polygon/connectors/pooltogether/main.sol +++ b/contracts/polygon/connectors/pooltogether/main.sol @@ -140,6 +140,6 @@ abstract contract PoolTogetherResolver is Events, DSMath, Basic { } } -contract ConnectV2PoolTogether is PoolTogetherResolver { +contract ConnectV2PoolTogetherPolygon is PoolTogetherResolver { string public constant name = "PoolTogether-v1"; } \ No newline at end of file From 5224f45d5c865d2695e4db19ca71fb495de6ce51 Mon Sep 17 00:00:00 2001 From: eccheung4 Date: Tue, 12 Oct 2021 06:16:25 -0700 Subject: [PATCH 8/8] fix: update test for renaming of ConnectV2PoolTogetherPolygon --- test/pooltogether-polygon/pooltogether.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pooltogether-polygon/pooltogether.test.js b/test/pooltogether-polygon/pooltogether.test.js index 358d5dc4..fc6cc971 100644 --- a/test/pooltogether-polygon/pooltogether.test.js +++ b/test/pooltogether-polygon/pooltogether.test.js @@ -16,7 +16,7 @@ const constants = require("../../scripts/polygon/constant/constant"); const tokens = require("../../scripts/polygon/constant/tokens"); const connectV2AaveV2Artifacts = require("../../artifacts/contracts/polygon/connectors/aave/v2/main.sol/ConnectV2AaveV2Polygon.json") -const connectV2PoolTogetherArtifacts = require("../../artifacts/contracts/polygon/connectors/pooltogether/main.sol/ConnectV2PoolTogether.json") +const connectV2PoolTogetherArtifacts = require("../../artifacts/contracts/polygon/connectors/pooltogether/main.sol/ConnectV2PoolTogetherPolygon.json") const DAI_TOKEN_ADDR = tokens.dai.address // DAI Token // PoolTogether Address: https://docs.pooltogether.com/resources/networks/matic