From d88d4110b9fc927ebad968a14370d06e4ecf9abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Mon, 13 Jan 2025 17:40:34 +0100 Subject: [PATCH 1/8] feat: add OETH Fixed Rate Dripper. --- .../harvest/OETHFixedRateDripper.sol | 14 +++++ contracts/contracts/proxies/Proxies.sol | 7 +++ .../mainnet/117_oeth_fixed_rate_dripper.js | 63 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 contracts/contracts/harvest/OETHFixedRateDripper.sol create mode 100644 contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js diff --git a/contracts/contracts/harvest/OETHFixedRateDripper.sol b/contracts/contracts/harvest/OETHFixedRateDripper.sol new file mode 100644 index 0000000000..fdff74e50b --- /dev/null +++ b/contracts/contracts/harvest/OETHFixedRateDripper.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { FixedRateDripper } from "./FixedRateDripper.sol"; + +/** + * @title OETH FixedRateDripper Contract + * @author Origin Protocol Inc + */ +contract OETHFixedRateDripper is FixedRateDripper { + constructor(address _vault, address _token) + FixedRateDripper(_vault, _token) + {} +} diff --git a/contracts/contracts/proxies/Proxies.sol b/contracts/contracts/proxies/Proxies.sol index 97647718a6..583df1fd3c 100644 --- a/contracts/contracts/proxies/Proxies.sol +++ b/contracts/contracts/proxies/Proxies.sol @@ -358,3 +358,10 @@ contract MorphoGauntletPrimeUSDTStrategyProxy is { } + +/** + * @notice OETHFixedRateDripperProxy delegates calls to a OETHFixedRateDripper implementation + */ +contract OETHFixedRateDripperProxy is InitializeGovernedUpgradeabilityProxy { + +} diff --git a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js new file mode 100644 index 0000000000..511d73fcce --- /dev/null +++ b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js @@ -0,0 +1,63 @@ +const addresses = require("../../utils/addresses"); +const { deploymentWithGovernanceProposal } = require("../../utils/deploy"); + +module.exports = deploymentWithGovernanceProposal( + { + deployName: "117_oeth_fixed_rate_dripper", + forceDeploy: false, + //forceSkip: true, + reduceQueueTime: true, + deployerIsProposer: false, + proposalId: "", + }, + async ({ deployWithConfirmation, withConfirmation }) => { + const cOETHVaultProxy = await ethers.getContractAt( + "VaultAdmin", + addresses.mainnet.OETHVaultProxy + ); + + // Deployer Actions + // ---------------- + const { deployerAddr } = await getNamedAccounts(); + const sDeployer = await ethers.provider.getSigner(deployerAddr); + + // 1. Deploy the Fixed Rate Dripper Proxy + const dOETHFixedRateDripperProxy = await deployWithConfirmation( + "OETHFixedRateDripperProxy" + ); + + const cOETHFixedRateDripperProxy = await ethers.getContract( + "OETHFixedRateDripperProxy" + ); + + // 2. Deploy the OETH Fixed Rate Dripper implementation + const dOETHFixedRateDripper = await deployWithConfirmation( + "OETHFixedRateDripper", + [addresses.mainnet.OETHVaultProxy, addresses.mainnet.WETH] + ); + + // 3. Initialize the Fixed Rate Dripper Proxy + const initFunction = "initialize(address,address,bytes)"; + await withConfirmation( + cOETHFixedRateDripperProxy.connect(sDeployer)[initFunction]( + dOETHFixedRateDripper.address, + addresses.mainnet.Timelock, // governor + "0x" // no init data + ) + ); + + // Governance Actions + // ---------------- + return { + name: "", + actions: [ + // Collect on the current OETH dripper + { + contract: cOETHVaultProxy, + signature: "setDripper(address)", + args: [dOETHFixedRateDripperProxy.address], + }, + ], + }; + } +); From ab5c0e1bc4aed265f182be7e03c0c5607009458b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Mon, 13 Jan 2025 19:24:36 +0100 Subject: [PATCH 2/8] feat: add new function to Dripper. --- contracts/contracts/harvest/Dripper.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contracts/contracts/harvest/Dripper.sol b/contracts/contracts/harvest/Dripper.sol index 060cd27893..8ff6c34887 100644 --- a/contracts/contracts/harvest/Dripper.sol +++ b/contracts/contracts/harvest/Dripper.sol @@ -137,4 +137,13 @@ contract Dripper is Governable { // Send funds IERC20(token).safeTransfer(vault, amountToSend); } + + /// @dev Transfer out all ERC20 held by the contract. Governor only. + /// @param _asset ERC20 token address + function transferAllToken(address _asset) external onlyGovernor { + IERC20(_asset).safeTransfer( + governor(), + IERC20(_asset).balanceOf(address(this)) + ); + } } From 64fedfc8540bda48b4fde79a4cece8de7cd6e1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Mon, 13 Jan 2025 19:24:52 +0100 Subject: [PATCH 3/8] fix: adjust deployment file. --- .../mainnet/117_oeth_fixed_rate_dripper.js | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js index 511d73fcce..60b2bce4e8 100644 --- a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js +++ b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js @@ -21,7 +21,33 @@ module.exports = deploymentWithGovernanceProposal( const { deployerAddr } = await getNamedAccounts(); const sDeployer = await ethers.provider.getSigner(deployerAddr); - // 1. Deploy the Fixed Rate Dripper Proxy + // 1. Upgrade Dripper to the new version (with transferAll token function) + // 2. Deploy OETH fixed rate dripper + // 3. Transfer all funds from old dripper to new dripper + // 4. Set new dripper on the vault + + // --- 1 --- + // 1.a. Get the current OETH Dripper Proxy + + // 1.b. Deploy the new OETH Dripper implementation + const dOETHDripper = await deployWithConfirmation( + "OETHDripper", + [addresses.mainnet.OETHVaultProxy, addresses.mainnet.WETH], + undefined, + true + ); + + const cOETHDripperProxy = await ethers.getContractAt( + "OETHDripperProxy", + dOETHDripper.address + ); + const cOETHDripper = await ethers.getContractAt( + "OETHDripper", + dOETHDripper.address + ); + + // --- 2 --- + // 2.a Deploy the Fixed Rate Dripper Proxy const dOETHFixedRateDripperProxy = await deployWithConfirmation( "OETHFixedRateDripperProxy" ); @@ -30,13 +56,13 @@ module.exports = deploymentWithGovernanceProposal( "OETHFixedRateDripperProxy" ); - // 2. Deploy the OETH Fixed Rate Dripper implementation + // 2.b. Deploy the OETH Fixed Rate Dripper implementation const dOETHFixedRateDripper = await deployWithConfirmation( "OETHFixedRateDripper", [addresses.mainnet.OETHVaultProxy, addresses.mainnet.WETH] ); - // 3. Initialize the Fixed Rate Dripper Proxy + // 2.c. Initialize the Fixed Rate Dripper Proxy const initFunction = "initialize(address,address,bytes)"; await withConfirmation( cOETHFixedRateDripperProxy.connect(sDeployer)[initFunction]( @@ -45,12 +71,24 @@ module.exports = deploymentWithGovernanceProposal( "0x" // no init data ) ); - + // --- 3 & 4 --- // Governance Actions // ---------------- return { name: "", actions: [ + // 1. Upgrade the Dripper to the new version + { + contract: cOETHDripperProxy, + signature: "upgradeTo(address)", + args: [dOETHDripper.address], + }, + // 3. Transfer all funds from the old dripper to the new dripper + { + contract: cOETHDripper, + signature: "transferAllToken(address)", + args: [addresses.mainnet.WETH], + }, // Collect on the current OETH dripper { contract: cOETHVaultProxy, From 1b488bc8ce1c79cb4c6acaa5fb8f195e1b241920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Mon, 13 Jan 2025 19:46:11 +0100 Subject: [PATCH 4/8] fix: allow to transferERC20 to custom receiver. --- contracts/contracts/harvest/Dripper.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/harvest/Dripper.sol b/contracts/contracts/harvest/Dripper.sol index 8ff6c34887..8416b2a031 100644 --- a/contracts/contracts/harvest/Dripper.sol +++ b/contracts/contracts/harvest/Dripper.sol @@ -140,9 +140,9 @@ contract Dripper is Governable { /// @dev Transfer out all ERC20 held by the contract. Governor only. /// @param _asset ERC20 token address - function transferAllToken(address _asset) external onlyGovernor { + function transferAllToken(address _asset, address _receiver) external onlyGovernor { IERC20(_asset).safeTransfer( - governor(), + _receiver, IERC20(_asset).balanceOf(address(this)) ); } From 5f1361e0a24ec21d7211f6d99ebfef4c3893902b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Mon, 13 Jan 2025 19:46:30 +0100 Subject: [PATCH 5/8] prettier. --- contracts/contracts/harvest/Dripper.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/contracts/harvest/Dripper.sol b/contracts/contracts/harvest/Dripper.sol index 8416b2a031..ccb79a9e85 100644 --- a/contracts/contracts/harvest/Dripper.sol +++ b/contracts/contracts/harvest/Dripper.sol @@ -140,7 +140,10 @@ contract Dripper is Governable { /// @dev Transfer out all ERC20 held by the contract. Governor only. /// @param _asset ERC20 token address - function transferAllToken(address _asset, address _receiver) external onlyGovernor { + function transferAllToken(address _asset, address _receiver) + external + onlyGovernor + { IERC20(_asset).safeTransfer( _receiver, IERC20(_asset).balanceOf(address(this)) From e5729d6db2ceb2d7f803b6c6f06457b4294cc3c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Mon, 13 Jan 2025 19:46:57 +0100 Subject: [PATCH 6/8] fix: adjust deployment script. --- .../mainnet/117_oeth_fixed_rate_dripper.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js index 60b2bce4e8..a363e201f0 100644 --- a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js +++ b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js @@ -28,6 +28,10 @@ module.exports = deploymentWithGovernanceProposal( // --- 1 --- // 1.a. Get the current OETH Dripper Proxy + const cOETHDripperProxy = await ethers.getContractAt( + "OETHDripperProxy", + "0xc0F42F73b8f01849a2DD99753524d4ba14317EB3" + ); // 1.b. Deploy the new OETH Dripper implementation const dOETHDripper = await deployWithConfirmation( @@ -37,13 +41,9 @@ module.exports = deploymentWithGovernanceProposal( true ); - const cOETHDripperProxy = await ethers.getContractAt( - "OETHDripperProxy", - dOETHDripper.address - ); const cOETHDripper = await ethers.getContractAt( "OETHDripper", - dOETHDripper.address + "0xc0F42F73b8f01849a2DD99753524d4ba14317EB3" ); // --- 2 --- @@ -86,10 +86,10 @@ module.exports = deploymentWithGovernanceProposal( // 3. Transfer all funds from the old dripper to the new dripper { contract: cOETHDripper, - signature: "transferAllToken(address)", - args: [addresses.mainnet.WETH], + signature: "transferAllToken(address,address)", + args: [addresses.mainnet.WETH, cOETHFixedRateDripperProxy.address], }, - // Collect on the current OETH dripper + // 4. Set new dripper address on the vault { contract: cOETHVaultProxy, signature: "setDripper(address)", From b83647871dc8ed3b96d56a744d695dbc7caab627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Tue, 14 Jan 2025 13:36:23 +0100 Subject: [PATCH 7/8] fix: remove hardcoded addresses. --- contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js index a363e201f0..0eee8bb88a 100644 --- a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js +++ b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js @@ -28,10 +28,7 @@ module.exports = deploymentWithGovernanceProposal( // --- 1 --- // 1.a. Get the current OETH Dripper Proxy - const cOETHDripperProxy = await ethers.getContractAt( - "OETHDripperProxy", - "0xc0F42F73b8f01849a2DD99753524d4ba14317EB3" - ); + const cOETHDripperProxy = await ethers.getContract("OETHDripperProxy"); // 1.b. Deploy the new OETH Dripper implementation const dOETHDripper = await deployWithConfirmation( @@ -43,7 +40,7 @@ module.exports = deploymentWithGovernanceProposal( const cOETHDripper = await ethers.getContractAt( "OETHDripper", - "0xc0F42F73b8f01849a2DD99753524d4ba14317EB3" + cOETHDripperProxy.address ); // --- 2 --- From d6e4165d62b43256b1346fead9f438e1b4935ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Tue, 14 Jan 2025 15:51:14 +0100 Subject: [PATCH 8/8] docs: adjust comments. --- .../mainnet/117_oeth_fixed_rate_dripper.js | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js index 0eee8bb88a..d707a62818 100644 --- a/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js +++ b/contracts/deploy/mainnet/117_oeth_fixed_rate_dripper.js @@ -21,21 +21,22 @@ module.exports = deploymentWithGovernanceProposal( const { deployerAddr } = await getNamedAccounts(); const sDeployer = await ethers.provider.getSigner(deployerAddr); - // 1. Upgrade Dripper to the new version (with transferAll token function) - // 2. Deploy OETH fixed rate dripper - // 3. Transfer all funds from old dripper to new dripper - // 4. Set new dripper on the vault + // 1. Deploy new implementation of OETH Dripper (with transferAllToken function) + // 2. Deploy new OETH fixed rate dripper (proxy + implementation) + // 3. Upgrade Dripper to the new version (with transferAll token function) + // 4. Transfer all funds from old dripper to new dripper + // 5. Set new dripper on the vault // --- 1 --- // 1.a. Get the current OETH Dripper Proxy const cOETHDripperProxy = await ethers.getContract("OETHDripperProxy"); - // 1.b. Deploy the new OETH Dripper implementation + // 1.b. Deploy the new OETH Dripper implementation (with transferAllToken function) const dOETHDripper = await deployWithConfirmation( "OETHDripper", [addresses.mainnet.OETHVaultProxy, addresses.mainnet.WETH], undefined, - true + true // due to changing name from `perBlock` to `perSecond` ); const cOETHDripper = await ethers.getContractAt( @@ -68,25 +69,25 @@ module.exports = deploymentWithGovernanceProposal( "0x" // no init data ) ); - // --- 3 & 4 --- + // --- 3 & 4 & 5 --- // Governance Actions // ---------------- return { name: "", actions: [ - // 1. Upgrade the Dripper to the new version + // 3. Upgrade the Dripper to the new version { contract: cOETHDripperProxy, signature: "upgradeTo(address)", args: [dOETHDripper.address], }, - // 3. Transfer all funds from the old dripper to the new dripper + // 4. Transfer all funds from the old dripper to the new dripper { contract: cOETHDripper, signature: "transferAllToken(address,address)", args: [addresses.mainnet.WETH, cOETHFixedRateDripperProxy.address], }, - // 4. Set new dripper address on the vault + // 5. Set new dripper address on the vault { contract: cOETHVaultProxy, signature: "setDripper(address)",