-
Notifications
You must be signed in to change notification settings - Fork 33
Morpho Views #492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
x0s0l
wants to merge
5
commits into
main
Choose a base branch
from
x0s0l/morpho-markets
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Morpho Views #492
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
22ae5a6
Morpho Views
x0s0l eaba579
Merge remote-tracking branch 'origin' into x0s0l/morpho-markets
x0s0l 9e7390c
Merge remote-tracking branch 'origin' into x0s0l/morpho-markets
x0s0l e649480
Add getStakingInfo to BaseMoonwellViews
x0s0l 58492cd
Merge branch 'main' into x0s0l/morpho-markets
anajuliabit File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,63 @@ | ||
| // SPDX-License-Identifier: GPL-3.0-or-later | ||
| pragma solidity 0.8.19; | ||
| pragma experimental ABIEncoderV2; | ||
|
|
||
| import {console} from "@forge-std/console.sol"; | ||
| import {Script} from "@forge-std/Script.sol"; | ||
| import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
|
|
||
| import "@forge-std/Test.sol"; | ||
|
|
||
| import {AllChainAddresses as Addresses} from "@proposals/Addresses.sol"; | ||
| import {MorphoViews} from "@protocol/views/MorphoViews.sol"; | ||
| import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; | ||
| import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; | ||
|
|
||
| import {console} from "@forge-std/console.sol"; | ||
| /* | ||
| to run: | ||
| forge script script/DeployMorphoViews.s.sol:DeployMorphoViews -vvvv --rpc-url {rpc} --broadcast --etherscan-api-key {key} | ||
| forge script script/DeployMorphoViews.s.sol:DeployMorphoViews -vvvv --rpc-url https://sepolia.base.org --broadcast | ||
|
|
||
| */ | ||
|
|
||
| contract DeployMorphoViews is Script, Test { | ||
| uint256 public PRIVATE_KEY; | ||
|
|
||
| Addresses public addresses; | ||
|
|
||
| function setUp() public { | ||
| addresses = new Addresses(); | ||
|
|
||
| // Default behavior: use Anvil 0 private key | ||
| PRIVATE_KEY = vm.envOr( | ||
| "MOONWELL_DEPLOY_PK", | ||
| 77814517325470205911140941194401928579557062014761831930645393041380819009408 | ||
| ); | ||
| } | ||
|
|
||
| function run() public { | ||
| vm.startBroadcast(PRIVATE_KEY); | ||
|
|
||
| address unitroller = addresses.getAddress("UNITROLLER"); | ||
| address morpho = 0xce95AfbB8EA029495c66020883F87aaE8864AF92; | ||
|
|
||
| MorphoViews viewsContract = new MorphoViews(); | ||
|
|
||
| bytes memory initdata = abi.encodeWithSignature( | ||
| "initialize(address,address)", | ||
| unitroller, | ||
| morpho | ||
| ); | ||
|
|
||
| ProxyAdmin proxyAdmin = new ProxyAdmin(); | ||
|
|
||
| new TransparentUpgradeableProxy( | ||
| address(viewsContract), | ||
| address(proxyAdmin), | ||
| initdata | ||
| ); | ||
|
|
||
| vm.stopBroadcast(); | ||
| } | ||
| } | ||
This file contains hidden or 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 hidden or 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,252 @@ | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
| pragma solidity >=0.5.0; | ||
|
|
||
| import {IMorpho, Id, MarketParams} from "./MorphoBlueInterface.sol"; | ||
| import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; | ||
| import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; | ||
|
|
||
| struct MarketConfig { | ||
| /// @notice The maximum amount of assets that can be allocated to the market. | ||
| uint184 cap; | ||
| /// @notice Whether the market is in the withdraw queue. | ||
| bool enabled; | ||
| /// @notice The timestamp at which the market can be instantly removed from the withdraw queue. | ||
| uint64 removableAt; | ||
| } | ||
|
|
||
| struct PendingUint192 { | ||
| /// @notice The pending value to set. | ||
| uint192 value; | ||
| /// @notice The timestamp at which the pending value becomes valid. | ||
| uint64 validAt; | ||
| } | ||
|
|
||
| struct PendingAddress { | ||
| /// @notice The pending value to set. | ||
| address value; | ||
| /// @notice The timestamp at which the pending value becomes valid. | ||
| uint64 validAt; | ||
| } | ||
|
|
||
| struct MarketAllocation { | ||
| /// @notice The market to allocate. | ||
| MarketParams marketParams; | ||
| /// @notice The amount of assets to allocate. | ||
| uint256 assets; | ||
| } | ||
|
|
||
| interface IMulticall { | ||
| function multicall(bytes[] calldata) external returns (bytes[] memory); | ||
| } | ||
|
|
||
| interface IOwnable { | ||
| function owner() external view returns (address); | ||
| function transferOwnership(address) external; | ||
| function renounceOwnership() external; | ||
| function acceptOwnership() external; | ||
| function pendingOwner() external view returns (address); | ||
| } | ||
|
|
||
| /// @dev This interface is used for factorizing IMetaMorphoStaticTyping and IMetaMorpho. | ||
| /// @dev Consider using the IMetaMorpho interface instead of this one. | ||
| interface IMetaMorphoBase { | ||
| /// @notice The address of the Morpho contract. | ||
| function MORPHO() external view returns (IMorpho); | ||
| function DECIMALS_OFFSET() external view returns (uint8); | ||
|
|
||
| /// @notice The address of the curator. | ||
| function curator() external view returns (address); | ||
|
|
||
| /// @notice Stores whether an address is an allocator or not. | ||
| function isAllocator(address target) external view returns (bool); | ||
|
|
||
| /// @notice The current guardian. Can be set even without the timelock set. | ||
| function guardian() external view returns (address); | ||
|
|
||
| /// @notice The current fee. | ||
| function fee() external view returns (uint96); | ||
|
|
||
| /// @notice The fee recipient. | ||
| function feeRecipient() external view returns (address); | ||
|
|
||
| /// @notice The skim recipient. | ||
| function skimRecipient() external view returns (address); | ||
|
|
||
| /// @notice The current timelock. | ||
| function timelock() external view returns (uint256); | ||
|
|
||
| /// @dev Stores the order of markets on which liquidity is supplied upon deposit. | ||
| /// @dev Can contain any market. A market is skipped as soon as its supply cap is reached. | ||
| function supplyQueue(uint256) external view returns (Id); | ||
|
|
||
| /// @notice Returns the length of the supply queue. | ||
| function supplyQueueLength() external view returns (uint256); | ||
|
|
||
| /// @dev Stores the order of markets from which liquidity is withdrawn upon withdrawal. | ||
| /// @dev Always contain all non-zero cap markets as well as all markets on which the vault supplies liquidity, | ||
| /// without duplicate. | ||
| function withdrawQueue(uint256) external view returns (Id); | ||
|
|
||
| /// @notice Returns the length of the withdraw queue. | ||
| function withdrawQueueLength() external view returns (uint256); | ||
|
|
||
| /// @notice Stores the total assets managed by this vault when the fee was last accrued. | ||
| /// @dev May be greater than `totalAssets()` due to removal of markets with non-zero supply or socialized bad debt. | ||
| /// This difference will decrease the fee accrued until one of the functions updating `lastTotalAssets` is | ||
| /// triggered (deposit/mint/withdraw/redeem/setFee/setFeeRecipient). | ||
| function lastTotalAssets() external view returns (uint256); | ||
|
|
||
| /// @notice Submits a `newTimelock`. | ||
| /// @dev Warning: Reverts if a timelock is already pending. Revoke the pending timelock to overwrite it. | ||
| /// @dev In case the new timelock is higher than the current one, the timelock is set immediately. | ||
| function submitTimelock(uint256 newTimelock) external; | ||
|
|
||
| /// @notice Accepts the pending timelock. | ||
| function acceptTimelock() external; | ||
|
|
||
| /// @notice Revokes the pending timelock. | ||
| /// @dev Does not revert if there is no pending timelock. | ||
| function revokePendingTimelock() external; | ||
|
|
||
| /// @notice Submits a `newSupplyCap` for the market defined by `marketParams`. | ||
| /// @dev Warning: Reverts if a cap is already pending. Revoke the pending cap to overwrite it. | ||
| /// @dev Warning: Reverts if a market removal is pending. | ||
| /// @dev In case the new cap is lower than the current one, the cap is set immediately. | ||
| function submitCap( | ||
| MarketParams memory marketParams, | ||
| uint256 newSupplyCap | ||
| ) external; | ||
|
|
||
| /// @notice Accepts the pending cap of the market defined by `marketParams`. | ||
| function acceptCap(MarketParams memory marketParams) external; | ||
|
|
||
| /// @notice Revokes the pending cap of the market defined by `id`. | ||
| /// @dev Does not revert if there is no pending cap. | ||
| function revokePendingCap(Id id) external; | ||
|
|
||
| /// @notice Submits a forced market removal from the vault, eventually losing all funds supplied to the market. | ||
| /// @notice Funds can be recovered by enabling this market again and withdrawing from it (using `reallocate`), | ||
| /// but funds will be distributed pro-rata to the shares at the time of withdrawal, not at the time of removal. | ||
| /// @notice This forced removal is expected to be used as an emergency process in case a market constantly reverts. | ||
| /// To softly remove a sane market, the curator role is expected to bundle a reallocation that empties the market | ||
| /// first (using `reallocate`), followed by the removal of the market (using `updateWithdrawQueue`). | ||
| /// @dev Warning: Removing a market with non-zero supply will instantly impact the vault's price per share. | ||
| /// @dev Warning: Reverts for non-zero cap or if there is a pending cap. Successfully submitting a zero cap will | ||
| /// prevent such reverts. | ||
| function submitMarketRemoval(MarketParams memory marketParams) external; | ||
|
|
||
| /// @notice Revokes the pending removal of the market defined by `id`. | ||
| /// @dev Does not revert if there is no pending market removal. | ||
| function revokePendingMarketRemoval(Id id) external; | ||
|
|
||
| /// @notice Submits a `newGuardian`. | ||
| /// @notice Warning: a malicious guardian could disrupt the vault's operation, and would have the power to revoke | ||
| /// any pending guardian. | ||
| /// @dev In case there is no guardian, the gardian is set immediately. | ||
| /// @dev Warning: Submitting a gardian will overwrite the current pending gardian. | ||
| function submitGuardian(address newGuardian) external; | ||
|
|
||
| /// @notice Accepts the pending guardian. | ||
| function acceptGuardian() external; | ||
|
|
||
| /// @notice Revokes the pending guardian. | ||
| function revokePendingGuardian() external; | ||
|
|
||
| /// @notice Skims the vault `token` balance to `skimRecipient`. | ||
| function skim(address) external; | ||
|
|
||
| /// @notice Sets `newAllocator` as an allocator or not (`newIsAllocator`). | ||
| function setIsAllocator(address newAllocator, bool newIsAllocator) external; | ||
|
|
||
| /// @notice Sets `curator` to `newCurator`. | ||
| function setCurator(address newCurator) external; | ||
|
|
||
| /// @notice Sets the `fee` to `newFee`. | ||
| function setFee(uint256 newFee) external; | ||
|
|
||
| /// @notice Sets `feeRecipient` to `newFeeRecipient`. | ||
| function setFeeRecipient(address newFeeRecipient) external; | ||
|
|
||
| /// @notice Sets `skimRecipient` to `newSkimRecipient`. | ||
| function setSkimRecipient(address newSkimRecipient) external; | ||
|
|
||
| /// @notice Sets `supplyQueue` to `newSupplyQueue`. | ||
| /// @param newSupplyQueue is an array of enabled markets, and can contain duplicate markets, but it would only | ||
| /// increase the cost of depositing to the vault. | ||
| function setSupplyQueue(Id[] calldata newSupplyQueue) external; | ||
|
|
||
| /// @notice Updates the withdraw queue. Some markets can be removed, but no market can be added. | ||
| /// @notice Removing a market requires the vault to have 0 supply on it, or to have previously submitted a removal | ||
| /// for this market (with the function `submitMarketRemoval`). | ||
| /// @notice Warning: Anyone can supply on behalf of the vault so the call to `updateWithdrawQueue` that expects a | ||
| /// market to be empty can be griefed by a front-run. To circumvent this, the allocator can simply bundle a | ||
| /// reallocation that withdraws max from this market with a call to `updateWithdrawQueue`. | ||
| /// @dev Warning: Removing a market with supply will decrease the fee accrued until one of the functions updating | ||
| /// `lastTotalAssets` is triggered (deposit/mint/withdraw/redeem/setFee/setFeeRecipient). | ||
| /// @dev Warning: `updateWithdrawQueue` is not idempotent. Submitting twice the same tx will change the queue twice. | ||
| /// @param indexes The indexes of each market in the previous withdraw queue, in the new withdraw queue's order. | ||
| function updateWithdrawQueue(uint256[] calldata indexes) external; | ||
|
|
||
| /// @notice Reallocates the vault's liquidity so as to reach a given allocation of assets on each given market. | ||
| /// @notice The allocator can withdraw from any market, even if it's not in the withdraw queue, as long as the loan | ||
| /// token of the market is the same as the vault's asset. | ||
| /// @dev The behavior of the reallocation can be altered by state changes, including: | ||
| /// - Deposits on the vault that supplies to markets that are expected to be supplied to during reallocation. | ||
| /// - Withdrawals from the vault that withdraws from markets that are expected to be withdrawn from during | ||
| /// reallocation. | ||
| /// - Donations to the vault on markets that are expected to be supplied to during reallocation. | ||
| /// - Withdrawals from markets that are expected to be withdrawn from during reallocation. | ||
| /// @dev Sender is expected to pass `assets = type(uint256).max` with the last MarketAllocation of `allocations` to | ||
| /// supply all the remaining withdrawn liquidity, which would ensure that `totalWithdrawn` = `totalSupplied`. | ||
| function reallocate(MarketAllocation[] calldata allocations) external; | ||
| } | ||
|
|
||
| /// @dev This interface is inherited by MetaMorpho so that function signatures are checked by the compiler. | ||
| /// @dev Consider using the IMetaMorpho interface instead of this one. | ||
| interface IMetaMorphoStaticTyping is IMetaMorphoBase { | ||
| /// @notice Returns the current configuration of each market. | ||
| function config( | ||
| Id | ||
| ) external view returns (uint184 cap, bool enabled, uint64 removableAt); | ||
|
|
||
| /// @notice Returns the pending guardian. | ||
| function pendingGuardian() | ||
| external | ||
| view | ||
| returns (address guardian, uint64 validAt); | ||
|
|
||
| /// @notice Returns the pending cap for each market. | ||
| function pendingCap( | ||
| Id | ||
| ) external view returns (uint192 value, uint64 validAt); | ||
|
|
||
| /// @notice Returns the pending timelock. | ||
| function pendingTimelock() | ||
| external | ||
| view | ||
| returns (uint192 value, uint64 validAt); | ||
| } | ||
|
|
||
| /// @title IMetaMorpho | ||
| /// @author Morpho Labs | ||
| /// @custom:contact [email protected] | ||
| /// @dev Use this interface for MetaMorpho to have access to all the functions with the appropriate function signatures. | ||
| interface IMetaMorpho is | ||
| IMetaMorphoBase, | ||
| IERC4626, | ||
| IERC20Permit, | ||
| IOwnable, | ||
| IMulticall | ||
| { | ||
| /// @notice Returns the current configuration of each market. | ||
| function config(Id) external view returns (MarketConfig memory); | ||
|
|
||
| /// @notice Returns the pending guardian. | ||
| function pendingGuardian() external view returns (PendingAddress memory); | ||
|
|
||
| /// @notice Returns the pending cap for each market. | ||
| function pendingCap(Id) external view returns (PendingUint192 memory); | ||
|
|
||
| /// @notice Returns the pending timelock. | ||
| function pendingTimelock() external view returns (PendingUint192 memory); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@x0s0l should we be putting a deploy PK in a public repository? I know it's probably just used for internal testing but it seems like bad practice.