Skip to content

Commit

Permalink
More accurate method of calculating 3pool balances (#592)
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielVF authored May 17, 2021
1 parent b2b8ab4 commit 9295bcc
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 1 deletion.
4 changes: 4 additions & 0 deletions contracts/contracts/mocks/curve/MockCurvePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ contract MockCurvePool is ERC20 {
using StableMath for uint256;

address[] public coins;
uint256[3] public balances;
address lpToken;

constructor(address[3] memory _coins, address _lpToken) public {
Expand All @@ -34,6 +35,7 @@ contract MockCurvePool is ERC20 {
uint256 assetDecimals = Helpers.getDecimals(coins[i]);
// Convert to 1e18 and add to sum
sum += _amounts[i].scaleBy(int8(18 - assetDecimals));
balances[uint256(i)] = balances[i].add(uint256(_amounts[i]));
}
}
// Hacky way of simulating slippage to check _minAmount
Expand Down Expand Up @@ -64,6 +66,7 @@ contract MockCurvePool is ERC20 {
amounts[uint256(_index)] = _amount;
uint256 amount = calc_withdraw_one_coin(_amount, _index);
IERC20(coins[uint256(_index)]).transfer(msg.sender, amount);
balances[uint256(_index)] = balances[uint256(_index)].sub(amount);
}

function get_virtual_price() external view returns (uint256) {
Expand All @@ -80,6 +83,7 @@ contract MockCurvePool is ERC20 {
IERC20(coins[i]).balanceOf(address(this))
);
IERC20(coins[i]).transfer(msg.sender, amount);
balances[uint256(i)] = balances[uint256(i)].sub(amount);
}
}
}
2 changes: 2 additions & 0 deletions contracts/contracts/strategies/ICurvePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ interface ICurvePool {

function add_liquidity(uint256[3] calldata _amounts, uint256 _min) external;

function balances(uint256) external view returns (uint256);

function calc_token_amount(uint256[3] calldata _amounts, bool _deposit)
external
returns (uint256);
Expand Down
3 changes: 2 additions & 1 deletion contracts/contracts/strategies/ThreePoolStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ contract ThreePoolStrategy is InitializableAbstractStrategy {

uint256 pTokenTotalSupply = IERC20(assetToPToken[_asset]).totalSupply();
if (pTokenTotalSupply > 0) {
uint256 curveBalance = IERC20(_asset).balanceOf(address(curvePool));
uint256 poolCoinIndex = _getPoolCoinIndex(_asset);
uint256 curveBalance = curvePool.balances(poolCoinIndex);
if (curveBalance > 0) {
balance = totalPTokens.mul(curveBalance).div(pTokenTotalSupply);
}
Expand Down
81 changes: 81 additions & 0 deletions contracts/deploy/017_3pool_strategy_update.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const {
isMainnet,
isFork,
isRinkeby,
isSmokeTest,
} = require("../test/helpers.js");
const {
log,
deployWithConfirmation,
withConfirmation,
executeProposal,
sendProposal,
} = require("../utils/deploy");
const { proposeArgs } = require("../utils/governor");
const { getTxOpts } = require("../utils/tx");

const deployName = "017_3pool_strategy_update";

const runDeployment = async (hre) => {
console.log(`Running ${deployName} deployment...`);
const { governorAddr } = await hre.getNamedAccounts();

// Signers
const sGovernor = await ethers.provider.getSigner(governorAddr);

const cThreePoolStrategyProxy = await ethers.getContract(
"ThreePoolStrategyProxy"
);

// Deploy Updated 3Pool strategy.
const dThreePoolStrategy = await deployWithConfirmation("ThreePoolStrategy");

// Proposal for the governor update the contract
const propDescription = "Update 3pool implementation";
const propArgs = await proposeArgs([
{
contract: cThreePoolStrategyProxy,
signature: "upgradeTo(address)",
args: [dThreePoolStrategy.address],
},
]);

if (isMainnet) {
// On Mainnet, only propose. The enqueue and execution are handled manually via multi-sig.
log("Sending proposal to governor...");
await sendProposal(propArgs, propDescription);
log("Proposal sent.");
} else if (isFork) {
// On Fork we can send the proposal then impersonate the guardian to execute it.
log("Sending and executing proposal...");
await executeProposal(propArgs, propDescription);
log("Proposal executed.");
} else {
// Hardcoding gas estimate on Rinkeby since it fails for an undetermined reason...
const gasLimit = isRinkeby ? 1000000 : null;
await withConfirmation(
cThreePoolStrategyProxy
.connect(sGovernor)
.upgradeTo(dThreePoolStrategy.address, await getTxOpts(gasLimit))
);
log("Switched implementation of ThreePoolStrategy");
}

return true;
};

const main = async (hre) => {
console.log(`Running ${deployName} deployment...`);
if (!hre) {
hre = require("hardhat");
}
await runDeployment(hre);
console.log(`${deployName} deploy done.`);
return true;
};

main.id = deployName;
main.dependencies = ["014_3pool_strategy"];
main.skip = () => !(isMainnet || isRinkeby || isFork) || isSmokeTest;

module.exports = main;

0 comments on commit 9295bcc

Please sign in to comment.