Skip to content

Commit 9295bcc

Browse files
authored
More accurate method of calculating 3pool balances (#592)
1 parent b2b8ab4 commit 9295bcc

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed

contracts/contracts/mocks/curve/MockCurvePool.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ contract MockCurvePool is ERC20 {
1212
using StableMath for uint256;
1313

1414
address[] public coins;
15+
uint256[3] public balances;
1516
address lpToken;
1617

1718
constructor(address[3] memory _coins, address _lpToken) public {
@@ -34,6 +35,7 @@ contract MockCurvePool is ERC20 {
3435
uint256 assetDecimals = Helpers.getDecimals(coins[i]);
3536
// Convert to 1e18 and add to sum
3637
sum += _amounts[i].scaleBy(int8(18 - assetDecimals));
38+
balances[uint256(i)] = balances[i].add(uint256(_amounts[i]));
3739
}
3840
}
3941
// Hacky way of simulating slippage to check _minAmount
@@ -64,6 +66,7 @@ contract MockCurvePool is ERC20 {
6466
amounts[uint256(_index)] = _amount;
6567
uint256 amount = calc_withdraw_one_coin(_amount, _index);
6668
IERC20(coins[uint256(_index)]).transfer(msg.sender, amount);
69+
balances[uint256(_index)] = balances[uint256(_index)].sub(amount);
6770
}
6871

6972
function get_virtual_price() external view returns (uint256) {
@@ -80,6 +83,7 @@ contract MockCurvePool is ERC20 {
8083
IERC20(coins[i]).balanceOf(address(this))
8184
);
8285
IERC20(coins[i]).transfer(msg.sender, amount);
86+
balances[uint256(i)] = balances[uint256(i)].sub(amount);
8387
}
8488
}
8589
}

contracts/contracts/strategies/ICurvePool.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ interface ICurvePool {
55

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

8+
function balances(uint256) external view returns (uint256);
9+
810
function calc_token_amount(uint256[3] calldata _amounts, bool _deposit)
911
external
1012
returns (uint256);

contracts/contracts/strategies/ThreePoolStrategy.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ contract ThreePoolStrategy is InitializableAbstractStrategy {
264264

265265
uint256 pTokenTotalSupply = IERC20(assetToPToken[_asset]).totalSupply();
266266
if (pTokenTotalSupply > 0) {
267-
uint256 curveBalance = IERC20(_asset).balanceOf(address(curvePool));
267+
uint256 poolCoinIndex = _getPoolCoinIndex(_asset);
268+
uint256 curveBalance = curvePool.balances(poolCoinIndex);
268269
if (curveBalance > 0) {
269270
balance = totalPTokens.mul(curveBalance).div(pTokenTotalSupply);
270271
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
const {
2+
isMainnet,
3+
isFork,
4+
isRinkeby,
5+
isSmokeTest,
6+
} = require("../test/helpers.js");
7+
const {
8+
log,
9+
deployWithConfirmation,
10+
withConfirmation,
11+
executeProposal,
12+
sendProposal,
13+
} = require("../utils/deploy");
14+
const { proposeArgs } = require("../utils/governor");
15+
const { getTxOpts } = require("../utils/tx");
16+
17+
const deployName = "017_3pool_strategy_update";
18+
19+
const runDeployment = async (hre) => {
20+
console.log(`Running ${deployName} deployment...`);
21+
const { governorAddr } = await hre.getNamedAccounts();
22+
23+
// Signers
24+
const sGovernor = await ethers.provider.getSigner(governorAddr);
25+
26+
const cThreePoolStrategyProxy = await ethers.getContract(
27+
"ThreePoolStrategyProxy"
28+
);
29+
30+
// Deploy Updated 3Pool strategy.
31+
const dThreePoolStrategy = await deployWithConfirmation("ThreePoolStrategy");
32+
33+
// Proposal for the governor update the contract
34+
const propDescription = "Update 3pool implementation";
35+
const propArgs = await proposeArgs([
36+
{
37+
contract: cThreePoolStrategyProxy,
38+
signature: "upgradeTo(address)",
39+
args: [dThreePoolStrategy.address],
40+
},
41+
]);
42+
43+
if (isMainnet) {
44+
// On Mainnet, only propose. The enqueue and execution are handled manually via multi-sig.
45+
log("Sending proposal to governor...");
46+
await sendProposal(propArgs, propDescription);
47+
log("Proposal sent.");
48+
} else if (isFork) {
49+
// On Fork we can send the proposal then impersonate the guardian to execute it.
50+
log("Sending and executing proposal...");
51+
await executeProposal(propArgs, propDescription);
52+
log("Proposal executed.");
53+
} else {
54+
// Hardcoding gas estimate on Rinkeby since it fails for an undetermined reason...
55+
const gasLimit = isRinkeby ? 1000000 : null;
56+
await withConfirmation(
57+
cThreePoolStrategyProxy
58+
.connect(sGovernor)
59+
.upgradeTo(dThreePoolStrategy.address, await getTxOpts(gasLimit))
60+
);
61+
log("Switched implementation of ThreePoolStrategy");
62+
}
63+
64+
return true;
65+
};
66+
67+
const main = async (hre) => {
68+
console.log(`Running ${deployName} deployment...`);
69+
if (!hre) {
70+
hre = require("hardhat");
71+
}
72+
await runDeployment(hre);
73+
console.log(`${deployName} deploy done.`);
74+
return true;
75+
};
76+
77+
main.id = deployName;
78+
main.dependencies = ["014_3pool_strategy"];
79+
main.skip = () => !(isMainnet || isRinkeby || isFork) || isSmokeTest;
80+
81+
module.exports = main;

0 commit comments

Comments
 (0)