Skip to content

Commit a0902b7

Browse files
Reallocate by moving funds directly between vault and strategies (#1071)
* Added the withdraw batch function * Added test for withdraw * test against withdrawing multiple assests * New comments on withdraw * Cleaned up for lint * Prettier * clean up the code and tests * add a deploy script and a fork test * prettier * re-introduce back the check * improve documentation and add more checks to tests * minor comment and text changes * update strategy addresses * update brownie abi. Fix deploy script for when the proposal has not yet been submitted. Update metastrategy address * prettier * some refactoring * simplify contract test * prettier * remove only * use depositAll to rather deploy funds more efficiently as the strategy * prettier --------- Co-authored-by: Domen Grabec <[email protected]>
1 parent b7dfd29 commit a0902b7

File tree

11 files changed

+914
-689
lines changed

11 files changed

+914
-689
lines changed

brownie/abi/vault_admin.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

brownie/metastrategy.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@
22
import world
33
import math
44

5-
#CONFIGURATION - unfortunately this address changes until we deploy it to mainnet
6-
OUSD_META_STRATEGY = '0xb12C3410C44854054c217fbF79dFf38ffD1C0676'
7-
BUSD_STRATEGY = '0x6996352570817113965b0325005f868B1Fe2f2e9'
8-
# Define which meta strategy should be set as default USDT asset strategy. Important for
9-
# supplying liquidity when minting using USDT
10-
USDT_DEFAULT_META_STRATEGY = OUSD_META_STRATEGY
11-
#USDT_DEFAULT_META_STRATEGY = BUSD_STRATEGY
12-
#END COFIGURATION
135

146
me = ORIGINTEAM
157
some_gas_price = 100
@@ -30,6 +22,8 @@
3022
DAI_BAGS = '0x40ec5b33f54e0e8a33a975908c5ba1c14e5bbbdf' #polygon bridge
3123
DAI_BAGS_2 = '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643' #this is compound cDai. Don't touch this!
3224
CURVE_FACTORY = '0xB9fC157394Af804a3578134A6585C0dc9cc990d4'
25+
OUSD_META_STRATEGY = '0x89Eb88fEdc50FC77ae8a18aAD1cA0ac27f777a90'
26+
USDT_DEFAULT_META_STRATEGY = OUSD_META_STRATEGY
3327

3428
threepool_lp = load_contract('threepool_lp', THREEPOOL_LP)
3529
ousd_metapool = load_contract('ousd_metapool', OUSD_METAPOOL)
@@ -52,7 +46,6 @@
5246
frax.transfer(me, frax.balanceOf(FRAX_BAGS), {'from': FRAX_BAGS})
5347
busd.transfer(me, busd.balanceOf(BUSD_BAGS), {'from': BUSD_BAGS})
5448
meta_strat = load_contract('convex_strat', OUSD_META_STRATEGY)
55-
busd_strat = load_contract('convex_strat', BUSD_STRATEGY)
5649

5750
# approve ousd and 3poolLp to be used by ousd_metapool
5851
threepool_lp.approve(ousd_metapool, int(0), OPTS)

contracts/contracts/interfaces/IVault.sol

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,18 @@ interface IVault {
113113
uint256[] calldata _amounts
114114
) external;
115115

116+
function withdrawFromStrategy(
117+
address _strategyFromAddress,
118+
address[] calldata _assets,
119+
uint256[] calldata _amounts
120+
) external;
121+
122+
function depositToStrategy(
123+
address _strategyToAddress,
124+
address[] calldata _assets,
125+
uint256[] calldata _amounts
126+
) external;
127+
116128
// VaultCore.sol
117129
function mint(
118130
address _asset,

contracts/contracts/vault/VaultAdmin.sol

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ contract VaultAdmin is VaultStorage {
233233
}
234234

235235
/**
236-
* @notice Move assets from one Strategy to another
236+
* @dev Move assets from one Strategy to another
237237
* @param _strategyFromAddress Address of Strategy to move assets from.
238238
* @param _strategyToAddress Address of Strategy to move assets to.
239239
* @param _assets Array of asset address that will be moved
@@ -246,27 +246,103 @@ contract VaultAdmin is VaultStorage {
246246
uint256[] calldata _amounts
247247
) external onlyGovernorOrStrategist {
248248
require(
249-
strategies[_strategyFromAddress].isSupported,
250-
"Invalid from Strategy"
249+
strategies[_strategyToAddress].isSupported,
250+
"Invalid to Strategy"
251251
);
252+
require(_assets.length == _amounts.length, "Parameter length mismatch");
253+
_withdrawFromStrategy(
254+
_strategyToAddress,
255+
_strategyFromAddress,
256+
_assets,
257+
_amounts
258+
);
259+
260+
IStrategy strategyTo = IStrategy(_strategyToAddress);
261+
for (uint256 i = 0; i < _assets.length; i++) {
262+
require(strategyTo.supportsAsset(_assets[i]), "Asset unsupported");
263+
}
264+
// Tell new Strategy to deposit into protocol
265+
strategyTo.depositAll();
266+
}
267+
268+
/**
269+
* @dev Deposit multiple assets from the vault into the strategy.
270+
* @param _strategyToAddress Address of the Strategy to deposit assets into.
271+
* @param _assets Array of asset address that will be deposited into the strategy.
272+
* @param _amounts Array of amounts of each corresponding asset to deposit.
273+
*/
274+
function depositToStrategy(
275+
address _strategyToAddress,
276+
address[] calldata _assets,
277+
uint256[] calldata _amounts
278+
) external onlyGovernorOrStrategist {
279+
_depositToStrategy(_strategyToAddress, _assets, _amounts);
280+
}
281+
282+
function _depositToStrategy(
283+
address _strategyToAddress,
284+
address[] calldata _assets,
285+
uint256[] calldata _amounts
286+
) internal {
252287
require(
253288
strategies[_strategyToAddress].isSupported,
254289
"Invalid to Strategy"
255290
);
256291
require(_assets.length == _amounts.length, "Parameter length mismatch");
257292

258-
IStrategy strategyFrom = IStrategy(_strategyFromAddress);
259293
IStrategy strategyTo = IStrategy(_strategyToAddress);
260294

261295
for (uint256 i = 0; i < _assets.length; i++) {
262296
require(strategyTo.supportsAsset(_assets[i]), "Asset unsupported");
263-
// Withdraw from Strategy and pass other Strategy as recipient
264-
strategyFrom.withdraw(address(strategyTo), _assets[i], _amounts[i]);
297+
// Send required amount of funds to the strategy
298+
IERC20(_assets[i]).safeTransfer(_strategyToAddress, _amounts[i]);
265299
}
266-
// Tell new Strategy to deposit into protocol
300+
301+
// Deposit all the funds that have been sent to the strategy
267302
strategyTo.depositAll();
268303
}
269304

305+
/**
306+
* @dev Withdraw multiple assets from the strategy to the vault.
307+
* @param _strategyFromAddress Address of the Strategy to withdraw assets from.
308+
* @param _assets Array of asset address that will be withdrawn from the strategy.
309+
* @param _amounts Array of amounts of each corresponding asset to withdraw.
310+
*/
311+
function withdrawFromStrategy(
312+
address _strategyFromAddress,
313+
address[] calldata _assets,
314+
uint256[] calldata _amounts
315+
) external onlyGovernorOrStrategist {
316+
_withdrawFromStrategy(
317+
address(this),
318+
_strategyFromAddress,
319+
_assets,
320+
_amounts
321+
);
322+
}
323+
324+
/**
325+
* @param _recipient can either be a strategy or the Vault
326+
*/
327+
function _withdrawFromStrategy(
328+
address _recipient,
329+
address _strategyFromAddress,
330+
address[] calldata _assets,
331+
uint256[] calldata _amounts
332+
) internal {
333+
require(
334+
strategies[_strategyFromAddress].isSupported,
335+
"Invalid from Strategy"
336+
);
337+
require(_assets.length == _amounts.length, "Parameter length mismatch");
338+
339+
IStrategy strategyFrom = IStrategy(_strategyFromAddress);
340+
for (uint256 i = 0; i < _assets.length; i++) {
341+
// Withdraw from Strategy to the recipient
342+
strategyFrom.withdraw(_recipient, _assets[i], _amounts[i]);
343+
}
344+
}
345+
270346
/**
271347
* @dev Sets the maximum allowable difference between
272348
* total supply and backing assets' value.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
const { deploymentWithProposal } = require("../utils/deploy");
2+
const addresses = require("../utils/addresses");
3+
4+
module.exports = deploymentWithProposal(
5+
{ deployName: "048_deposit_withdraw_tooling", forceDeploy: false },
6+
async ({
7+
assetAddresses,
8+
deployWithConfirmation,
9+
ethers,
10+
getTxOpts,
11+
withConfirmation,
12+
}) => {
13+
const { deployerAddr, governorAddr } = await getNamedAccounts();
14+
const sDeployer = await ethers.provider.getSigner(deployerAddr);
15+
16+
// Current contracts
17+
const cVaultProxy = await ethers.getContract("VaultProxy");
18+
19+
const dVaultAdmin = await deployWithConfirmation("VaultAdmin");
20+
const cVault = await ethers.getContractAt("Vault", cVaultProxy.address);
21+
22+
// Governance Actions
23+
// ----------------
24+
return {
25+
name: "Deploy new withdrawal utils",
26+
actions: [
27+
// 1. Set VaultAdmin implementation
28+
{
29+
contract: cVault,
30+
signature: "setAdminImpl(address)",
31+
args: [dVaultAdmin.address],
32+
},
33+
],
34+
};
35+
}
36+
);

contracts/test/_fixture.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ async function defaultFixture() {
167167
tusd = await ethers.getContractAt(erc20Abi, addresses.mainnet.TUSD);
168168
usdc = await ethers.getContractAt(erc20Abi, addresses.mainnet.USDC);
169169
cusdt = await ethers.getContractAt(erc20Abi, addresses.mainnet.cUSDT);
170+
cdai = await ethers.getContractAt(erc20Abi, addresses.mainnet.cDAI);
170171
cusdc = await ethers.getContractAt(erc20Abi, addresses.mainnet.cUSDC);
171172
comp = await ethers.getContractAt(erc20Abi, addresses.mainnet.COMP);
172173
crv = await ethers.getContractAt(erc20Abi, addresses.mainnet.CRV);

0 commit comments

Comments
 (0)