Skip to content

Commit d2231cd

Browse files
author
Franck
authored
Deploy and configure trustee fee collection (#543)
* configuration for the trustee * remove test goof up * Add deploy 13 * Add hardhat yield task * Add OUSDReset to ignore list for etherscan verify; fix deploy 13 dependency
1 parent 68ff1ad commit d2231cd

File tree

5 files changed

+184
-2
lines changed

5 files changed

+184
-2
lines changed

contracts/deploy/013_trustee.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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 = "013_upgrades";
18+
19+
/**
20+
* Deploys the vault trustee feature:
21+
* - upgrade VaultCore
22+
* - set trusteeAdress and trusteeFeeBps
23+
* @returns {Promise<boolean>}
24+
*/
25+
const trustee = async (hre) => {
26+
console.log(`Running ${deployName} deployment...`);
27+
28+
const { governorAddr } = await hre.getNamedAccounts();
29+
30+
// Signers
31+
const sGovernor = await ethers.provider.getSigner(governorAddr);
32+
33+
const cVaultProxy = await ethers.getContract("VaultProxy");
34+
const cvaultAdmin = await ethers.getContractAt(
35+
"VaultAdmin",
36+
cVaultProxy.address
37+
);
38+
39+
// Deploy a new VaultCore contract.
40+
const dVaultCore = await deployWithConfirmation("VaultCore");
41+
42+
// Proposal for the governor to do the upgrades.
43+
const propDescription = "Trustee deploy and config";
44+
const trusteeAddress = "0xF14BBdf064E3F67f51cd9BD646aE3716aD938FDC"; // Strategist multi-sig
45+
const trusteeFeeBps = 1000; // 1000 bps = 10%
46+
const propArgs = await proposeArgs([
47+
{
48+
contract: cVaultProxy,
49+
signature: "upgradeTo(address)",
50+
args: [dVaultCore.address],
51+
},
52+
{
53+
contract: cvaultAdmin,
54+
signature: "setTrusteeAddress(address)",
55+
args: [trusteeAddress],
56+
},
57+
{
58+
contract: cvaultAdmin,
59+
signature: "setTrusteeFeeBps(uint256)",
60+
args: [trusteeFeeBps],
61+
},
62+
]);
63+
64+
if (isMainnet) {
65+
// On Mainnet, only propose. The enqueue and execution are handled manually via multi-sig.
66+
log("Sending proposal to governor...");
67+
await sendProposal(propArgs, propDescription);
68+
log("Proposal sent.");
69+
} else if (isFork) {
70+
// On Fork we can send the proposal then impersonate the guardian to execute it.
71+
log("Sending and executing proposal...");
72+
await executeProposal(propArgs, propDescription);
73+
log("Proposal executed.");
74+
} else {
75+
// Hardcoding gas estimate on Rinkeby since it fails for an undetermined reason...
76+
const gasLimit = isRinkeby ? 1000000 : null;
77+
78+
await withConfirmation(
79+
cVaultProxy
80+
.connect(sGovernor)
81+
.upgradeTo(dVaultCore.address, await getTxOpts(gasLimit))
82+
);
83+
log("Upgraded VaultCore to new implementation");
84+
85+
await withConfirmation(
86+
cvaultAdmin
87+
.connect(sGovernor)
88+
.setTrusteeAddress(trusteeAddress, await getTxOpts(gasLimit))
89+
);
90+
log("Trustee address set");
91+
92+
await withConfirmation(
93+
cvaultAdmin
94+
.connect(sGovernor)
95+
.setTrusteeFeeBps(trusteeFeeBps, await getTxOpts(gasLimit))
96+
);
97+
log("Trustee fee bps set");
98+
}
99+
100+
return true;
101+
};
102+
103+
const main = async (hre) => {
104+
console.log(`Running ${deployName} deployment...`);
105+
if (!hre) {
106+
hre = require("hardhat");
107+
}
108+
await trustee(hre);
109+
console.log(`${deployName} deploy done.`);
110+
return true;
111+
};
112+
113+
main.id = deployName;
114+
main.dependencies = ["012_upgrades"];
115+
main.skip = () => !(isMainnet || isRinkeby || isFork) || isSmokeTest;
116+
117+
module.exports = main;

contracts/hardhat.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const {
3232
harvest,
3333
reallocate,
3434
rebase,
35+
yield,
3536
} = require("./tasks/vault");
3637

3738
const MAINNET_DEPLOYER = "0x71F78361537A6f7B6818e7A760c8bC0146D93f50";
@@ -87,6 +88,7 @@ task("allocate", "Call allocate() on the Vault", allocate);
8788
task("capital", "Set the Vault's pauseCapital flag", capital);
8889
task("harvest", "Call harvest() on Vault", harvest);
8990
task("rebase", "Call rebase() on the Vault", rebase);
91+
task("yield", "Artificially generate yield on the Vault", yield);
9092
task("reallocate", "Allocate assets from one Strategy to another")
9193
.addParam("from", "Address to withdraw asset from")
9294
.addParam("to", "Address to deposit asset to")

contracts/scripts/etherscan/etherscanVerify.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const deprecatedContractNames = [
4848
"MinuteTimelock",
4949
"OpenUniswapOracle",
5050
"RebaseHooks",
51+
"OUSDReset",
5152
];
5253

5354
function logError(...args) {

contracts/tasks/debug.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ async function debug(taskArguments, hre) {
224224
//
225225
const rebasePaused = await vault.rebasePaused();
226226
const capitalPaused = await vault.capitalPaused();
227-
const redeemFeeBps = await vault.redeemFeeBps();
227+
const redeemFeeBps = Number(await vault.redeemFeeBps());
228+
const trusteeFeeBps = Number(await vault.trusteeFeeBps());
228229
const vaultBuffer = await vault.vaultBuffer();
229230
const autoAllocateThreshold = await vault.autoAllocateThreshold();
230231
const rebaseThreshold = await vault.rebaseThreshold();
@@ -233,12 +234,14 @@ async function debug(taskArguments, hre) {
233234
const strategyCount = await vault.getStrategyCount();
234235
const assetCount = await vault.getAssetCount();
235236
const strategistAddress = await vault.strategistAddr();
237+
const trusteeAddress = await vault.trusteeAddress();
236238

237239
console.log("\nVault Settings");
238240
console.log("================");
239241
console.log("rebasePaused:\t\t\t", rebasePaused);
240242
console.log("capitalPaused:\t\t\t", capitalPaused);
241-
console.log("redeemFeeBps:\t\t\t", redeemFeeBps.toString());
243+
console.log(`redeemFeeBps:\t\t\t ${redeemFeeBps} (${redeemFeeBps / 100}%)`);
244+
console.log(`trusteeFeeBps:\t\t\t ${trusteeFeeBps} (${trusteeFeeBps / 100}%)`);
242245
console.log("vaultBuffer:\t\t\t", formatUnits(vaultBuffer.toString(), 18));
243246
console.log(
244247
"autoAllocateThreshold (USD):\t",
@@ -254,6 +257,7 @@ async function debug(taskArguments, hre) {
254257
console.log("Strategy count:\t\t\t", Number(strategyCount));
255258
console.log("Asset count:\t\t\t", Number(assetCount));
256259
console.log("Strategist address:\t\t", strategistAddress);
260+
console.log("Trustee address:\t\t", trusteeAddress)
257261

258262
const assets = [
259263
{

contracts/tasks/vault.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,63 @@ async function rebase(taskArguments, hre) {
6969
console.log("Rebase transaction confirmed");
7070
}
7171

72+
/**
73+
* Artificially generate yield on the vault by sending it USDT.
74+
*/
75+
async function yield(taskArguments, hre) {
76+
const usdtAbi = require("../test/abi/usdt.json").abi;
77+
const {
78+
ousdUnitsFormat,
79+
usdtUnits,
80+
usdtUnitsFormat,
81+
isFork,
82+
isLocalhost
83+
} = require("../test/helpers");
84+
if (!isFork && !isLocalhost) {
85+
throw new Error('Task can only be used on local or fork')
86+
}
87+
88+
let richSigner, usdt;
89+
if (isFork) {
90+
await hre.network.provider.request({
91+
method: "hardhat_impersonateAccount",
92+
params: [addresses.mainnet.Binance],
93+
});
94+
richSigner = await hre.ethers.provider.getSigner(
95+
addresses.mainnet.Binance
96+
);
97+
usdt = await hre.ethers.getContractAt(usdtAbi, addresses.mainnet.USDT);
98+
} else {
99+
const signers = await hre.ethers.getSigners();
100+
richSigner = signers
101+
usdt = await hre.ethers.getContract("MockUSDT");
102+
}
103+
104+
const vaultProxy = await ethers.getContract("VaultProxy");
105+
const vault = await ethers.getContractAt("IVault", vaultProxy.address);
106+
107+
const ousdProxy = await ethers.getContract("OUSDProxy");
108+
const ousd = await ethers.getContractAt("OUSD", ousdProxy.address);
109+
110+
console.log("Sending yield to vault")
111+
let usdtBalance = await usdt.balanceOf(vaultProxy.address)
112+
console.log("USDT vault balance", usdtUnitsFormat(usdtBalance))
113+
let vaultValue = await vault.totalValue()
114+
console.log("Vault value", ousdUnitsFormat(vaultValue))
115+
let supply = await ousd.totalSupply();
116+
console.log("OUSD supply", ousdUnitsFormat(supply))
117+
118+
// Transfer 100k USDT to the vault.
119+
await usdt.connect(richSigner).transfer(vaultProxy.address, usdtUnits("100000"));
120+
121+
usdtBalance = await usdt.balanceOf(vaultProxy.address)
122+
console.log("USDT vault balance", usdtUnitsFormat(usdtBalance))
123+
vaultValue = await vault.totalValue()
124+
console.log("Vault value", ousdUnitsFormat(vaultValue))
125+
supply = await ousd.totalSupply();
126+
console.log("OUSD supply", ousdUnitsFormat(supply))
127+
}
128+
72129
/**
73130
* Call the Vault's admin pauseCapital method.
74131
*/
@@ -231,4 +288,5 @@ module.exports = {
231288
harvest,
232289
reallocate,
233290
rebase,
291+
yield,
234292
}

0 commit comments

Comments
 (0)