diff --git a/contracts/contracts/poolBooster/AbstractPoolBoosterFactory.sol b/contracts/contracts/poolBooster/AbstractPoolBoosterFactory.sol index 754256764f..146882f3d6 100644 --- a/contracts/contracts/poolBooster/AbstractPoolBoosterFactory.sol +++ b/contracts/contracts/poolBooster/AbstractPoolBoosterFactory.sol @@ -16,8 +16,8 @@ contract AbstractPoolBoosterFactory is Governable { IPoolBoostCentralRegistry.PoolBoosterType boosterType; } - // @notice address of Origin Sonic - address public immutable oSonic; + // @notice address of Origin Token + address public immutable oToken; // @notice Central registry contract IPoolBoostCentralRegistry public immutable centralRegistry; @@ -26,22 +26,22 @@ contract AbstractPoolBoosterFactory is Governable { // @notice mapping of AMM pool to pool booster mapping(address => PoolBoosterEntry) public poolBoosterFromPool; - // @param address _oSonic address of the OSonic token + // @param address _oToken address of the OToken token // @param address _governor address governor // @param address _centralRegistry address of the central registry constructor( - address _oSonic, + address _oToken, address _governor, address _centralRegistry ) { - require(_oSonic != address(0), "Invalid oSonic address"); + require(_oToken != address(0), "Invalid oToken address"); require(_governor != address(0), "Invalid governor address"); require( _centralRegistry != address(0), "Invalid central registry address" ); - oSonic = _oSonic; + oToken = _oToken; centralRegistry = IPoolBoostCentralRegistry(_centralRegistry); _setGovernor(_governor); } diff --git a/contracts/contracts/poolBooster/PoolBoosterFactoryMerkl.sol b/contracts/contracts/poolBooster/PoolBoosterFactoryMerkl.sol index bd1ed748fc..25c48d4e8b 100644 --- a/contracts/contracts/poolBooster/PoolBoosterFactoryMerkl.sol +++ b/contracts/contracts/poolBooster/PoolBoosterFactoryMerkl.sol @@ -18,17 +18,17 @@ contract PoolBoosterFactoryMerkl is AbstractPoolBoosterFactory { event MerklDistributorUpdated(address newDistributor); /** - * @param _oSonic address of the OSonic token + * @param _oToken address of the OToken token * @param _governor address governor * @param _centralRegistry address of the central registry * @param _merklDistributor address of the Merkl distributor */ constructor( - address _oSonic, + address _oToken, address _governor, address _centralRegistry, address _merklDistributor - ) AbstractPoolBoosterFactory(_oSonic, _governor, _centralRegistry) { + ) AbstractPoolBoosterFactory(_oToken, _governor, _centralRegistry) { _setMerklDistributor(_merklDistributor); } @@ -64,7 +64,7 @@ contract PoolBoosterFactoryMerkl is AbstractPoolBoosterFactory { abi.encodePacked( type(PoolBoosterMerkl).creationCode, abi.encode( - oSonic, + oToken, merklDistributor, _campaignDuration, _campaignType, @@ -111,7 +111,7 @@ contract PoolBoosterFactoryMerkl is AbstractPoolBoosterFactory { abi.encodePacked( type(PoolBoosterMerkl).creationCode, abi.encode( - oSonic, + oToken, merklDistributor, _campaignDuration, _campaignType, diff --git a/contracts/contracts/poolBooster/PoolBoosterFactoryMetropolis.sol b/contracts/contracts/poolBooster/PoolBoosterFactoryMetropolis.sol index 03907a1781..86e6482d32 100644 --- a/contracts/contracts/poolBooster/PoolBoosterFactoryMetropolis.sol +++ b/contracts/contracts/poolBooster/PoolBoosterFactoryMetropolis.sol @@ -13,18 +13,18 @@ contract PoolBoosterFactoryMetropolis is AbstractPoolBoosterFactory { address public immutable rewardFactory; address public immutable voter; - // @param address _oSonic address of the OSonic token + // @param address _oToken address of the OToken token // @param address _governor address governor // @param address _centralRegistry address of the central registry // @param address _rewardFactory address of the Metropolis reward factory // @param address _voter address of the Metropolis voter constructor( - address _oSonic, + address _oToken, address _governor, address _centralRegistry, address _rewardFactory, address _voter - ) AbstractPoolBoosterFactory(_oSonic, _governor, _centralRegistry) { + ) AbstractPoolBoosterFactory(_oToken, _governor, _centralRegistry) { rewardFactory = _rewardFactory; voter = _voter; } @@ -49,7 +49,7 @@ contract PoolBoosterFactoryMetropolis is AbstractPoolBoosterFactory { address poolBoosterAddress = _deployContract( abi.encodePacked( type(PoolBoosterMetropolis).creationCode, - abi.encode(oSonic, rewardFactory, _ammPoolAddress, voter) + abi.encode(oToken, rewardFactory, _ammPoolAddress, voter) ), _salt ); @@ -83,7 +83,7 @@ contract PoolBoosterFactoryMetropolis is AbstractPoolBoosterFactory { _computeAddress( abi.encodePacked( type(PoolBoosterMetropolis).creationCode, - abi.encode(oSonic, rewardFactory, _ammPoolAddress, voter) + abi.encode(oToken, rewardFactory, _ammPoolAddress, voter) ), _salt ); diff --git a/contracts/contracts/poolBooster/PoolBoosterFactorySwapxDouble.sol b/contracts/contracts/poolBooster/PoolBoosterFactorySwapxDouble.sol index 3679749c00..5cd9a7d469 100644 --- a/contracts/contracts/poolBooster/PoolBoosterFactorySwapxDouble.sol +++ b/contracts/contracts/poolBooster/PoolBoosterFactorySwapxDouble.sol @@ -12,14 +12,14 @@ import { AbstractPoolBoosterFactory, IPoolBoostCentralRegistry } from "./Abstrac contract PoolBoosterFactorySwapxDouble is AbstractPoolBoosterFactory { uint256 public constant version = 1; - // @param address _oSonic address of the OSonic token + // @param address _oToken address of the OToken token // @param address _governor address governor // @param address _centralRegistry address of the central registry constructor( - address _oSonic, + address _oToken, address _governor, address _centralRegistry - ) AbstractPoolBoosterFactory(_oSonic, _governor, _centralRegistry) {} + ) AbstractPoolBoosterFactory(_oToken, _governor, _centralRegistry) {} /** * @dev Create a Pool Booster for SwapX Ichi vault based pool where 2 Bribe contracts need to be @@ -49,7 +49,7 @@ contract PoolBoosterFactorySwapxDouble is AbstractPoolBoosterFactory { address poolBoosterAddress = _deployContract( abi.encodePacked( type(PoolBoosterSwapxDouble).creationCode, - abi.encode(_bribeAddressOS, _bribeAddressOther, oSonic, _split) + abi.encode(_bribeAddressOS, _bribeAddressOther, oToken, _split) ), _salt ); @@ -92,7 +92,7 @@ contract PoolBoosterFactorySwapxDouble is AbstractPoolBoosterFactory { abi.encode( _bribeAddressOS, _bribeAddressOther, - oSonic, + oToken, _split ) ), diff --git a/contracts/contracts/poolBooster/PoolBoosterFactorySwapxSingle.sol b/contracts/contracts/poolBooster/PoolBoosterFactorySwapxSingle.sol index d717c513b1..47c9f1f936 100644 --- a/contracts/contracts/poolBooster/PoolBoosterFactorySwapxSingle.sol +++ b/contracts/contracts/poolBooster/PoolBoosterFactorySwapxSingle.sol @@ -13,14 +13,14 @@ import { AbstractPoolBoosterFactory, IPoolBoostCentralRegistry } from "./Abstrac contract PoolBoosterFactorySwapxSingle is AbstractPoolBoosterFactory { uint256 public constant version = 1; - // @param address _oSonic address of the OSonic token + // @param address _oToken address of the OToken token // @param address _governor address governor // @param address _centralRegistry address of the central registry constructor( - address _oSonic, + address _oToken, address _governor, address _centralRegistry - ) AbstractPoolBoosterFactory(_oSonic, _governor, _centralRegistry) {} + ) AbstractPoolBoosterFactory(_oToken, _governor, _centralRegistry) {} /** * @dev Create a Pool Booster for SwapX classic volatile or classic stable pools where @@ -45,7 +45,7 @@ contract PoolBoosterFactorySwapxSingle is AbstractPoolBoosterFactory { address poolBoosterAddress = _deployContract( abi.encodePacked( type(PoolBoosterSwapxSingle).creationCode, - abi.encode(_bribeAddress, oSonic) + abi.encode(_bribeAddress, oToken) ), _salt ); @@ -81,7 +81,7 @@ contract PoolBoosterFactorySwapxSingle is AbstractPoolBoosterFactory { _computeAddress( abi.encodePacked( type(PoolBoosterSwapxSingle).creationCode, - abi.encode(_bribeAddress, oSonic) + abi.encode(_bribeAddress, oToken) ), _salt ); diff --git a/contracts/deploy/mainnet/152_pool_booster_setup.js b/contracts/deploy/mainnet/152_pool_booster_setup.js new file mode 100644 index 0000000000..cc01fffe0a --- /dev/null +++ b/contracts/deploy/mainnet/152_pool_booster_setup.js @@ -0,0 +1,95 @@ +const addresses = require("../../utils/addresses"); +const { deploymentWithGovernanceProposal } = require("../../utils/deploy"); + +module.exports = deploymentWithGovernanceProposal( + { + deployName: "152_pool_booster_setup", + forceDeploy: false, + reduceQueueTime: true, + deployerIsProposer: false, + proposalId: "", + }, + async ({ deployWithConfirmation, withConfirmation }) => { + const { deployerAddr } = await getNamedAccounts(); + const sDeployer = await ethers.provider.getSigner(deployerAddr); + + const oethProxy = await ethers.getContract("OETHProxy"); + const oeth = await ethers.getContractAt("OETH", oethProxy.address); + + // --------------------------------------------------------------------------------------------------------- + // --- + // --- Deploy PoolBoostCentralRegistry + // --- + // --------------------------------------------------------------------------------------------------------- + + await deployWithConfirmation("PoolBoostCentralRegistryProxy"); + const cPoolBoostCentralRegistryProxy = await ethers.getContract( + "PoolBoostCentralRegistryProxy" + ); + + console.log( + `Pool boost central registry proxy deployed: ${cPoolBoostCentralRegistryProxy.address}` + ); + + const dPoolBoostCentralRegistry = await deployWithConfirmation( + "PoolBoostCentralRegistry", + [] + ); + console.log( + `Deployed Pool Boost Central Registry to ${dPoolBoostCentralRegistry.address}` + ); + + const cPoolBoostCentralRegistry = await ethers.getContractAt( + "PoolBoostCentralRegistry", + cPoolBoostCentralRegistryProxy.address + ); + + // prettier-ignore + await withConfirmation( + cPoolBoostCentralRegistryProxy + .connect(sDeployer)["initialize(address,address,bytes)"]( + dPoolBoostCentralRegistry.address, + addresses.mainnet.Timelock, + "0x" + ) + ); + console.log( + "Initialized PoolBoostCentralRegistry proxy and implementation" + ); + + // --------------------------------------------------------------------------------------------------------- + // --- + // --- Deploy PoolBoosterFactoryMerkl + // --- + // --------------------------------------------------------------------------------------------------------- + const dPoolBoosterFactoryMerkl = await deployWithConfirmation( + "PoolBoosterFactoryMerkl", + [ + oeth.address, + // so we can create a Merkl pool booster fast via a multichain strategist and kick off yield forwarding + addresses.multichainStrategist, + cPoolBoostCentralRegistryProxy.address, + addresses.mainnet.CampaignCreator, + ] + ); + const cPoolBoosterMerklFactory = await ethers.getContract( + "PoolBoosterFactoryMerkl" + ); + + console.log( + `Pool Booster Merkl Factory deployed to ${cPoolBoosterMerklFactory.address}` + ); + + return { + name: "Upgrade PoolBoosterCentralRegistry and deploy PoolBoosterFactoryMerkl", + actions: [ + { + // set the factory as an approved one + contract: cPoolBoostCentralRegistry, + signature: "approveFactory(address)", + args: [dPoolBoosterFactoryMerkl.address], + }, + ], + }; + } +); diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 8e61777177..bff702f557 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -38,6 +38,7 @@ const morphoLensAbi = require("./abi/morphoLens.json"); const crvMinterAbi = require("./abi/crvMinter.json"); const susdsAbi = require("./abi/sUSDS.json"); const metamorphoAbi = require("./abi/metamorpho.json"); +const merklDistributorAbi = require("./abi/merklDistributor.json"); // const curveFactoryAbi = require("./abi/curveFactory.json") const ousdMetapoolAbi = require("./abi/ousdMetapool.json"); @@ -779,7 +780,10 @@ const defaultFixture = deployments.createFixture(async () => { mock1InchSwapRouter, convexEthMetaStrategy, vaultValueChecker, - oethVaultValueChecker; + oethVaultValueChecker, + poolBoosterCentralRegistry, + poolBoosterMerklFactory, + merklDistributor; if (isFork) { usdt = await ethers.getContractAt(usdtAbi, addresses.mainnet.USDT); @@ -908,6 +912,21 @@ const defaultFixture = deployments.createFixture(async () => { vaultValueChecker = await ethers.getContract("VaultValueChecker"); oethVaultValueChecker = await ethers.getContract("OETHVaultValueChecker"); + + poolBoosterCentralRegistry = await ethers.getContractAt( + "PoolBoostCentralRegistry", + ( + await ethers.getContract("PoolBoostCentralRegistryProxy") + ).address + ); + poolBoosterMerklFactory = await ethers.getContract( + "PoolBoosterFactoryMerkl" + ); + + merklDistributor = await ethers.getContractAt( + merklDistributorAbi, + addresses.mainnet.CampaignCreator + ); } else { usdt = await ethers.getContract("MockUSDT"); usds = await ethers.getContract("MockUSDS"); @@ -1152,6 +1171,9 @@ const defaultFixture = deployments.createFixture(async () => { morphoToken, legacyMorphoToken, + poolBoosterCentralRegistry, + poolBoosterMerklFactory, + merklDistributor, }; }); diff --git a/contracts/test/poolBooster/poolBooster.mainnet.fork-test.js b/contracts/test/poolBooster/poolBooster.mainnet.fork-test.js new file mode 100644 index 0000000000..4487f2c0d1 --- /dev/null +++ b/contracts/test/poolBooster/poolBooster.mainnet.fork-test.js @@ -0,0 +1,49 @@ +const { createFixtureLoader, defaultFixture } = require("../_fixture"); +const { expect } = require("chai"); +const { oethUnits } = require("../helpers"); +const addresses = require("../../utils/addresses"); + +const sonicFixture = createFixtureLoader(defaultFixture); + +describe("ForkTest: Merkl Pool Booster", function () { + //const INCENTIVISE_BORROWING_TYPE = 45; + //const DEFAULT_DURATION = 86400 * 7; // a week + //const MOPRHO_CAMPAIGN_DATA = "0xb8fef900b383db2dbbf4458c7f46acf5b140f26d603a6d1829963f241b82510e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + let fixture, poolBoosterMerklFactory, merklDistributor, oeth; + beforeEach(async () => { + fixture = await sonicFixture(); + oeth = fixture.oeth; + poolBoosterMerklFactory = fixture.poolBoosterMerklFactory; + merklDistributor = fixture.merklDistributor; + }); + + it("Should have correct deployment params", async () => { + expect(await poolBoosterMerklFactory.merklDistributor()).to.equal( + addresses.mainnet.CampaignCreator + ); + + // Uncomment once the pool booster is deployed + // const poolBooster = await poolBoosterMerklFactory.poolBoosters(0) + // expect(await poolBooster.campaignType()).to.equal( + // INCENTIVISE_BORROWING_TYPE + // ); + + // expect(await poolBooster.duration()).to.equal( + // DEFAULT_DURATION + // ); + + // expect(await poolBooster.campaignData()).to.equal( + // MOPRHO_CAMPAIGN_DATA + // ); + + // expect(await poolBooster.rewardToken()).to.equal(oeth.address); + // expect(await poolBooster.merklDistributor()).to.equal(merklDistributor.address); + }); + + it("Should have OETH token supported by Merkl Distributor", async () => { + expect(await merklDistributor.rewardTokenMinAmounts(oeth.address)).to.equal( + oethUnits("0.00001") + ); + }); +}); diff --git a/contracts/utils/addresses.js b/contracts/utils/addresses.js index 8769419c3e..1a7cf8418c 100644 --- a/contracts/utils/addresses.js +++ b/contracts/utils/addresses.js @@ -349,6 +349,15 @@ addresses.mainnet.passthrough.uniswap.OETH_OGN = addresses.mainnet.passthrough.uniswap.OETH_WETH = "0x216dEBBF25e5e67e6f5B2AD59c856Fc364478A6A"; +// Mainnet Merkl +addresses.mainnet.CampaignCreator = + "0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd"; + +// Morpho Markets +// OETH is supply asset - USDC borrowing asset +addresses.mainnet.MorphoOethUsdcMarket = + "0xb8fef900b383db2dbbf4458c7f46acf5b140f26d603a6d1829963f241b82510e"; + // Arbitrum One addresses.arbitrumOne = {}; addresses.arbitrumOne.WOETHProxy = "0xD8724322f44E5c58D7A815F542036fb17DbbF839";