Skip to content

Commit

Permalink
SuperOETH Harvester (#2398)
Browse files Browse the repository at this point in the history
* Cherrypick harvester changes

* Store dripper locally
  • Loading branch information
shahthepro authored Feb 14, 2025
1 parent 3873d86 commit 83b8790
Show file tree
Hide file tree
Showing 9 changed files with 339 additions and 95 deletions.
22 changes: 14 additions & 8 deletions contracts/contracts/harvest/OETHHarvesterSimple.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import { Strategizable } from "../governance/Strategizable.sol";
Expand All @@ -16,8 +16,8 @@ contract OETHHarvesterSimple is Initializable, Strategizable {
////////////////////////////////////////////////////
/// --- CONSTANTS & IMMUTABLES
////////////////////////////////////////////////////
/// @notice WETH address
address public immutable WETH;
/// @notice wrapped native token address (WETH or wS)
address public immutable wrappedNativeToken;

////////////////////////////////////////////////////
/// --- STORAGE
Expand Down Expand Up @@ -46,8 +46,8 @@ contract OETHHarvesterSimple is Initializable, Strategizable {
////////////////////////////////////////////////////
/// --- CONSTRUCTOR
////////////////////////////////////////////////////
constructor(address _WETH) {
WETH = _WETH;
constructor(address _wrappedNativeToken) {
wrappedNativeToken = _wrappedNativeToken;
}

/// @notice Initialize the contract
Expand Down Expand Up @@ -82,10 +82,14 @@ contract OETHHarvesterSimple is Initializable, Strategizable {
}

/// @notice Internal logic to harvest rewards from a strategy
function _harvestAndTransfer(address _strategy) internal {
function _harvestAndTransfer(address _strategy) internal virtual {
// Ensure strategy is supported
require(supportedStrategies[_strategy], "Strategy not supported");

// Store locally for some gas savings
address _strategist = strategistAddr;
address _dripper = dripper;

// Harvest rewards
IStrategy(_strategy).collectRewardTokens();

Expand All @@ -100,10 +104,12 @@ contract OETHHarvesterSimple is Initializable, Strategizable {
uint256 balance = IERC20(token).balanceOf(address(this));
if (balance > 0) {
// Determine receiver
address receiver = token == WETH ? dripper : strategistAddr;
address receiver = token == wrappedNativeToken
? _dripper
: _strategist;
require(receiver != address(0), "Invalid receiver");

// Transfer to strategist
// Transfer to the Strategist or the Dripper
IERC20(token).safeTransfer(receiver, balance);
emit Harvested(_strategy, token, balance, receiver);
}
Expand Down
40 changes: 40 additions & 0 deletions contracts/contracts/harvest/SuperOETHHarvester.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import { OETHHarvesterSimple, IERC20, IStrategy, SafeERC20 } from "./OETHHarvesterSimple.sol";

contract SuperOETHHarvester is OETHHarvesterSimple {
using SafeERC20 for IERC20;

constructor(address _wrappedNativeToken)
OETHHarvesterSimple(_wrappedNativeToken)
{}

/// @inheritdoc OETHHarvesterSimple
function _harvestAndTransfer(address _strategy) internal virtual override {
// Ensure strategy is supported
require(supportedStrategies[_strategy], "Strategy not supported");

address receiver = strategistAddr;
require(receiver != address(0), "Invalid receiver");

// Harvest rewards
IStrategy(_strategy).collectRewardTokens();

// Cache reward tokens
address[] memory rewardTokens = IStrategy(_strategy)
.getRewardTokenAddresses();

uint256 len = rewardTokens.length;
for (uint256 i = 0; i < len; i++) {
// Cache balance
address token = rewardTokens[i];
uint256 balance = IERC20(token).balanceOf(address(this));
if (balance > 0) {
// Transfer everything to the strategist
IERC20(token).safeTransfer(receiver, balance);
emit Harvested(_strategy, token, balance, receiver);
}
}
}
}
67 changes: 67 additions & 0 deletions contracts/contracts/proxies/BaseProxies.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import { InitializeGovernedUpgradeabilityProxy } from "./InitializeGovernedUpgradeabilityProxy.sol";

/**
* @notice BridgedBaseWOETHProxy delegates calls to BridgedWOETH implementation
*/
contract BridgedBaseWOETHProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseVaultProxy delegates calls to OETHBaseVault implementation
*/
contract OETHBaseVaultProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseProxy delegates calls to OETH implementation
*/
contract OETHBaseProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice WOETHBaseProxy delegates calls to WOETH implementation
*/
contract WOETHBaseProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseDripperProxy delegates calls to a FixedRateDripper implementation
*/
contract OETHBaseDripperProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice AerodromeAMOStrategyProxy delegates calls to AerodromeAMOStrategy implementation
*/
contract AerodromeAMOStrategyProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice BridgedWOETHStrategyProxy delegates calls to BridgedWOETHStrategy implementation
*/
contract BridgedWOETHStrategyProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseHarvesterProxy delegates calls to a SuperOETHHarvester implementation
*/
contract OETHBaseHarvesterProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseCurveAMOProxy delegates calls to a OETHBaseCurveAMO implementation
*/
contract OETHBaseCurveAMOProxy is InitializeGovernedUpgradeabilityProxy {

}
65 changes: 1 addition & 64 deletions contracts/contracts/proxies/Proxies.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import { InitializeGovernedUpgradeabilityProxy } from "./InitializeGovernedUpgradeabilityProxy.sol";
Expand Down Expand Up @@ -271,69 +271,13 @@ contract LidoWithdrawalStrategyProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice BridgedBaseWOETHProxy delegates calls to BridgedWOETH implementation
*/
contract BridgedBaseWOETHProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseVaultProxy delegates calls to OETHBaseVault implementation
*/
contract OETHBaseVaultProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseProxy delegates calls to OETH implementation
*/
contract OETHBaseProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice WOETHBaseProxy delegates calls to WOETH implementation
*/
contract WOETHBaseProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseDripperProxy delegates calls to a OETHDripper implementation
*/
contract OETHBaseDripperProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice AerodromeAMOStrategyProxy delegates calls to AerodromeAMOStrategy implementation
*/
contract AerodromeAMOStrategyProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice BridgedWOETHStrategyProxy delegates calls to BridgedWOETHStrategy implementation
*/
contract BridgedWOETHStrategyProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice MetaMorphoStrategyProxy delegates calls to a Generalized4626Strategy implementation
*/
contract MetaMorphoStrategyProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseHarvesterProxy delegates calls to a OETHBaseHarvester implementation
*/
contract OETHBaseHarvesterProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice ARMBuybackProxy delegates calls to Buyback implementation
*/
Expand Down Expand Up @@ -373,13 +317,6 @@ contract OETHFixedRateDripperProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHBaseCurveAMOProxy delegates calls to a OETHBaseCurveAMO implementation
*/
contract OETHBaseCurveAMOProxy is InitializeGovernedUpgradeabilityProxy {

}

/**
* @notice OETHSimpleHarvesterProxy delegates calls to a OETHSimpleHarvester implementation
*/
Expand Down
2 changes: 1 addition & 1 deletion contracts/contracts/proxies/SonicProxies.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ contract SonicStakingStrategyProxy is InitializeGovernedUpgradeabilityProxy {
}

/**
* @notice OSonicHarvesterProxy delegates calls to a OSonicHarvester implementation
* @notice OSonicHarvesterProxy delegates calls to a OETHHarvesterSimple implementation
*/
contract OSonicHarvesterProxy is InitializeGovernedUpgradeabilityProxy {

Expand Down
73 changes: 73 additions & 0 deletions contracts/deploy/base/026_harvester_v2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const addresses = require("../../utils/addresses");
const { deployWithConfirmation } = require("../../utils/deploy");
const { deployOnBase } = require("../../utils/deploy-l2");

module.exports = deployOnBase(
{
deployName: "026_harvester_v2",
},
async ({ ethers }) => {
const cHarvesterProxy = await ethers.getContract("OETHBaseHarvesterProxy");
const cAMOStrategyProxy = await ethers.getContract(
"AerodromeAMOStrategyProxy"
);
const cCurveAMOStrategyProxy = await ethers.getContract(
"OETHBaseCurveAMOProxy"
);
const cCurveAMOStrategy = await ethers.getContractAt(
"BaseCurveAMOStrategy",
cCurveAMOStrategyProxy.address
);

const dHarvester = await deployWithConfirmation("SuperOETHHarvester", [
addresses.base.WETH,
]);
console.log("SuperOETHHarvester deployed at", dHarvester.address);

const cHarvester = await ethers.getContractAt(
"SuperOETHHarvester",
cHarvesterProxy.address
);

const cDripperProxy = await ethers.getContract("OETHBaseDripperProxy");

return {
actions: [
{
// Upgrade the harvester
contract: cHarvesterProxy,
signature: "upgradeTo(address)",
args: [dHarvester.address],
},
{
// Upgrade the harvester
contract: cHarvester,
signature: "initialize(address,address,address)",
args: [
addresses.base.timelock,
addresses.multichainStrategist,
cDripperProxy.address,
],
},
{
// Mark Aerodome AMO strategy as supported
contract: cHarvester,
signature: "setSupportedStrategy(address,bool)",
args: [cAMOStrategyProxy.address, true],
},
{
// Mark Curve AMO strategy as supported
contract: cHarvester,
signature: "setSupportedStrategy(address,bool)",
args: [cCurveAMOStrategyProxy.address, true],
},
{
// Set the harvester address on the Curve AMO strategy
contract: cCurveAMOStrategy,
signature: "setHarvesterAddress(address)",
args: [cHarvesterProxy.address],
},
],
};
}
);
57 changes: 57 additions & 0 deletions contracts/deploy/sonic/009_harvester.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const addresses = require("../../utils/addresses.js");
const { deployOnSonic } = require("../../utils/deploy-l2.js");
const {
deployWithConfirmation,
withConfirmation,
} = require("../../utils/deploy.js");

module.exports = deployOnSonic(
{
deployName: "009_harvester",
},
async ({ ethers }) => {
const { deployerAddr, strategistAddr } = await getNamedAccounts();

const sDeployer = await ethers.provider.getSigner(deployerAddr);
await deployWithConfirmation("OSonicHarvesterProxy");

await deployWithConfirmation("OETHHarvesterSimple", [addresses.sonic.wS]);
const dHarvester = await ethers.getContract("OETHHarvesterSimple");

const cHarvesterProxy = await ethers.getContract("OSonicHarvesterProxy");
const cHarvester = await ethers.getContractAt(
"OETHHarvesterSimple",
cHarvesterProxy.address
);

const cDripperProxy = await ethers.getContract("OSonicDripperProxy");

// const cStakingStrategyProxy = await ethers.getContract("SonicStakingStrategyProxy");

const initSonicStakingStrategy = cHarvester.interface.encodeFunctionData(
"initialize(address,address,address)",
[addresses.sonic.timelock, strategistAddr, cDripperProxy.address]
);

// prettier-ignore
await withConfirmation(
cHarvesterProxy
.connect(sDeployer)["initialize(address,address,bytes)"](
dHarvester.address,
addresses.sonic.timelock,
initSonicStakingStrategy
)
);

return {
actions: [
// TODO: Enable for Curve AMO after it has been deployed
// {
// contract: cHarvesterProxy,
// signature: "setSupportedStrategy(address,bool)",
// args: [cStakingStrategyProxy.address, true],
// },
],
};
}
);
Loading

0 comments on commit 83b8790

Please sign in to comment.