-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Morpho cbBTC/USDC Mainnet Integration. (#1209)
* copy test file * update test * copy deploy script * update deploy script --------- Co-authored-by: Jonny Rhea <[email protected]>
- Loading branch information
1 parent
7cfaaf0
commit ba3fde9
Showing
5 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 140 additions & 0 deletions
140
tasks/deploy/config/mainnet/morpho-blue-cbbtc-usdc-182day.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import { | ||
Address, | ||
encodeAbiParameters, | ||
keccak256, | ||
parseEther, | ||
toHex, | ||
zeroAddress, | ||
} from "viem"; | ||
import { | ||
CBBTC_ADDRESS_MAINNET, | ||
HyperdriveInstanceConfig, | ||
SIX_MONTHS, | ||
USDC_ADDRESS_MAINNET, | ||
getLinkerDetails, | ||
normalizeFee, | ||
parseDuration, | ||
toBytes32, | ||
} from "../../lib"; | ||
import { MAINNET_FACTORY_NAME } from "./factory"; | ||
import { MAINNET_MORPHO_BLUE_COORDINATOR_NAME } from "./morpho-blue-coordinator"; | ||
|
||
export const MAINNET_MORPHO_BLUE_CBBTC_USDC_182DAY_NAME = | ||
"ElementDAO 182 Day Morpho Blue cbBTC/USDC Hyperdrive"; | ||
|
||
// USDC only has 6 decimals. | ||
const CONTRIBUTION = 100_000_000n; | ||
|
||
const morphoBlueParameters = encodeAbiParameters( | ||
[ | ||
{ | ||
components: [ | ||
{ | ||
name: "morpho", | ||
type: "address", | ||
}, | ||
{ | ||
name: "collateralToken", | ||
type: "address", | ||
}, | ||
{ | ||
name: "oracle", | ||
type: "address", | ||
}, | ||
{ | ||
name: "irm", | ||
type: "address", | ||
}, | ||
{ | ||
name: "lltv", | ||
type: "uint256", | ||
}, | ||
], | ||
name: "MorphoBlueParams", | ||
type: "tuple", | ||
}, | ||
], | ||
[ | ||
{ | ||
morpho: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb" as `0x${string}`, | ||
collateralToken: CBBTC_ADDRESS_MAINNET, | ||
oracle: "0xA6D6950c9F177F1De7f7757FB33539e3Ec60182a" as `0x${string}`, | ||
irm: "0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC" as `0x${string}`, | ||
lltv: BigInt("860000000000000000"), | ||
}, | ||
], | ||
); | ||
|
||
export const MAINNET_MORPHO_BLUE_CBBTC_USDC_182DAY: HyperdriveInstanceConfig<"MorphoBlue"> = | ||
{ | ||
name: MAINNET_MORPHO_BLUE_CBBTC_USDC_182DAY_NAME, | ||
prefix: "MorphoBlue", | ||
coordinatorAddress: async (hre) => | ||
hre.hyperdriveDeploy.deployments.byName( | ||
MAINNET_MORPHO_BLUE_COORDINATOR_NAME, | ||
).address, | ||
deploymentId: keccak256( | ||
toHex(MAINNET_MORPHO_BLUE_CBBTC_USDC_182DAY_NAME), | ||
), | ||
salt: toBytes32("0x42080085"), | ||
extraData: morphoBlueParameters, | ||
contribution: CONTRIBUTION, | ||
// NOTE: The latest variable rate on the Morpho Blue market is 2.93% APY: | ||
// https://app.morpho.org/market?id=0x64d65c9a2d91c36d56fbc42d69e979335320169b3df63bf92789e2c8883fcc64&network=mainnet&morphoPrice=0.75 | ||
fixedAPR: parseEther("0.0293"), | ||
timestretchAPR: parseEther("0.05"), | ||
options: async (hre) => ({ | ||
extraData: "0x", | ||
asBase: true, | ||
destination: (await hre.getNamedAccounts())["deployer"] as Address, | ||
}), | ||
// Prepare to deploy the contract by setting approvals. | ||
prepare: async (hre, options) => { | ||
let pc = await hre.viem.getPublicClient(); | ||
let baseToken = await hre.viem.getContractAt( | ||
"contracts/src/interfaces/IERC20.sol:IERC20", | ||
USDC_ADDRESS_MAINNET, | ||
); | ||
let tx = await baseToken.write.approve([ | ||
hre.hyperdriveDeploy.deployments.byName( | ||
MAINNET_MORPHO_BLUE_COORDINATOR_NAME, | ||
).address, | ||
CONTRIBUTION, | ||
]); | ||
await pc.waitForTransactionReceipt({ hash: tx }); | ||
}, | ||
poolDeployConfig: async (hre) => { | ||
let factoryContract = await hre.viem.getContractAt( | ||
"HyperdriveFactory", | ||
hre.hyperdriveDeploy.deployments.byName(MAINNET_FACTORY_NAME) | ||
.address, | ||
); | ||
return { | ||
baseToken: USDC_ADDRESS_MAINNET, | ||
vaultSharesToken: zeroAddress, | ||
circuitBreakerDelta: parseEther("0.05"), | ||
minimumShareReserves: 1_000_000n, | ||
minimumTransactionAmount: 1_000_000n, | ||
positionDuration: parseDuration(SIX_MONTHS), | ||
checkpointDuration: parseDuration("1 day"), | ||
timeStretch: 0n, | ||
governance: await factoryContract.read.governance(), | ||
feeCollector: await factoryContract.read.feeCollector(), | ||
sweepCollector: await factoryContract.read.sweepCollector(), | ||
checkpointRewarder: | ||
await factoryContract.read.checkpointRewarder(), | ||
...(await getLinkerDetails( | ||
hre, | ||
hre.hyperdriveDeploy.deployments.byName( | ||
MAINNET_FACTORY_NAME, | ||
).address, | ||
)), | ||
fees: { | ||
curve: parseEther("0.01"), | ||
flat: normalizeFee(parseEther("0.0005"), SIX_MONTHS), | ||
governanceLP: parseEther("0.15"), | ||
governanceZombie: parseEther("0.03"), | ||
}, | ||
}; | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
test/instances/morpho-blue/MorphoBlue_cbETH_USDC_Mainnet_Hyperdrive.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity 0.8.22; | ||
|
||
import { stdStorage, StdStorage } from "forge-std/Test.sol"; | ||
import { IMorpho } from "morpho-blue/src/interfaces/IMorpho.sol"; | ||
import { IERC20 } from "../../../contracts/src/interfaces/IERC20.sol"; | ||
import { IFiatTokenProxy } from "../../../contracts/src/interfaces/IFiatTokenProxy.sol"; | ||
import { IHyperdrive } from "../../../contracts/src/interfaces/IHyperdrive.sol"; | ||
import { IMorphoBlueHyperdrive } from "../../../contracts/src/interfaces/IMorphoBlueHyperdrive.sol"; | ||
import { Lib } from "../../utils/Lib.sol"; | ||
import { MorphoBlueHyperdriveInstanceTest } from "./MorphoBlueHyperdriveInstanceTest.t.sol"; | ||
|
||
contract MorphoBlue_cbBTC_USDC_Mainnet_HyperdriveTest is | ||
MorphoBlueHyperdriveInstanceTest | ||
{ | ||
using Lib for *; | ||
using stdStorage for StdStorage; | ||
|
||
/// @dev The address of the loan token. This is just the USDC token. | ||
address internal constant LOAN_TOKEN = | ||
address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); | ||
|
||
/// @dev Whale accounts. | ||
address internal LOAN_TOKEN_WHALE = | ||
address(0x51eDF02152EBfb338e03E30d65C15fBf06cc9ECC); | ||
address[] internal baseTokenWhaleAccounts = [LOAN_TOKEN_WHALE]; | ||
|
||
/// @notice Instantiates the instance testing suite with the configuration. | ||
constructor() | ||
MorphoBlueHyperdriveInstanceTest( | ||
InstanceTestConfig({ | ||
name: "Hyperdrive", | ||
kind: "MorphoBlueHyperdrive", | ||
decimals: 6, | ||
baseTokenWhaleAccounts: baseTokenWhaleAccounts, | ||
vaultSharesTokenWhaleAccounts: new address[](0), | ||
baseToken: IERC20(LOAN_TOKEN), | ||
vaultSharesToken: IERC20(address(0)), | ||
// NOTE: The share tolerance is quite high for this integration | ||
// because the vault share price is ~1e12, which means that just | ||
// multiplying or dividing by the vault is an imprecise way of | ||
// converting between base and vault shares. We included more | ||
// assertions than normal to the round trip tests to verify that | ||
// the calculations satisfy our expectations of accuracy. | ||
shareTolerance: 1e3, | ||
minimumShareReserves: 1e6, | ||
minimumTransactionAmount: 1e6, | ||
positionDuration: POSITION_DURATION, | ||
fees: IHyperdrive.Fees({ | ||
curve: 0.001e18, | ||
flat: 0.0001e18, | ||
governanceLP: 0, | ||
governanceZombie: 0 | ||
}), | ||
enableBaseDeposits: true, | ||
enableShareDeposits: false, | ||
enableBaseWithdraws: true, | ||
enableShareWithdraws: false, | ||
baseWithdrawError: abi.encodeWithSelector( | ||
IHyperdrive.UnsupportedToken.selector | ||
), | ||
isRebasing: false, | ||
shouldAccrueInterest: true, | ||
// The base test tolerances. | ||
closeLongWithBaseTolerance: 2, | ||
roundTripLpInstantaneousWithBaseTolerance: 1e3, | ||
roundTripLpWithdrawalSharesWithBaseTolerance: 1e5, | ||
roundTripLongInstantaneousWithBaseUpperBoundTolerance: 100, | ||
// NOTE: Since the curve fee isn't zero, this check is ignored. | ||
roundTripLongInstantaneousWithBaseTolerance: 0, | ||
roundTripLongMaturityWithBaseUpperBoundTolerance: 100, | ||
roundTripLongMaturityWithBaseTolerance: 1e3, | ||
roundTripShortInstantaneousWithBaseUpperBoundTolerance: 100, | ||
// NOTE: Since the curve fee isn't zero, this check is ignored. | ||
roundTripShortInstantaneousWithBaseTolerance: 0, | ||
roundTripShortMaturityWithBaseTolerance: 1e3, | ||
// NOTE: Share deposits and withdrawals are disabled, so these are | ||
// 0. | ||
// | ||
// The share test tolerances. | ||
closeLongWithSharesTolerance: 0, | ||
closeShortWithSharesTolerance: 0, | ||
roundTripLpInstantaneousWithSharesTolerance: 0, | ||
roundTripLpWithdrawalSharesWithSharesTolerance: 0, | ||
roundTripLongInstantaneousWithSharesUpperBoundTolerance: 0, | ||
roundTripLongInstantaneousWithSharesTolerance: 0, | ||
roundTripLongMaturityWithSharesUpperBoundTolerance: 0, | ||
roundTripLongMaturityWithSharesTolerance: 0, | ||
roundTripShortInstantaneousWithSharesUpperBoundTolerance: 0, | ||
roundTripShortInstantaneousWithSharesTolerance: 0, | ||
roundTripShortMaturityWithSharesTolerance: 0, | ||
// The verification tolerances. | ||
verifyDepositTolerance: 2, | ||
verifyWithdrawalTolerance: 3 | ||
}), | ||
IMorphoBlueHyperdrive.MorphoBlueParams({ | ||
// The mainnet Morpho Blue pool | ||
morpho: IMorpho(0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb), | ||
// The address of the collateral token. This is cbBTC. | ||
collateralToken: address( | ||
0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf | ||
), | ||
// The address of the oracle. | ||
oracle: address(0xA6D6950c9F177F1De7f7757FB33539e3Ec60182a), | ||
// The address of the interest rate model. | ||
irm: address(0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC), | ||
// The liquidation loan to value ratio. | ||
lltv: 860000000000000000 | ||
}) | ||
) | ||
{} | ||
|
||
/// @notice Forge function that is invoked to setup the testing environment. | ||
function setUp() public override __mainnet_fork(21_092_084) { | ||
// Invoke the instance testing suite setup. | ||
super.setUp(); | ||
} | ||
|
||
/// Helpers /// | ||
|
||
/// @dev Mints base tokens to a specified account. | ||
/// @param _recipient The recipient of the minted tokens. | ||
/// @param _amount The amount of tokens to mint. | ||
function mintBaseTokens( | ||
address _recipient, | ||
uint256 _amount | ||
) internal override { | ||
bytes32 balanceLocation = keccak256(abi.encode(address(_recipient), 9)); | ||
vm.store(LOAN_TOKEN, balanceLocation, bytes32(_amount)); | ||
} | ||
} |