Skip to content

Commit

Permalink
Merge pull request #271 from morpho-org/revert-240-refactor/interfaces
Browse files Browse the repository at this point in the history
Revert "Refactor interfaces"
  • Loading branch information
MerlinEgalite authored Oct 25, 2023
2 parents fec39c2 + 4324a2a commit 2f9a8e7
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 118 deletions.
32 changes: 18 additions & 14 deletions src/MetaMorpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ pragma solidity 0.8.21;

import {IMorphoMarketParams} from "./interfaces/IMorphoMarketParams.sol";
import {
MarketConfig,
PendingUint192,
PendingAddress,
MarketAllocation,
IMetaMorphoStaticTyping
IMetaMorpho, MarketConfig, PendingUint192, PendingAddress, MarketAllocation
} from "./interfaces/IMetaMorpho.sol";
import {Id, MarketParams, Market, IMorpho} from "@morpho-blue/interfaces/IMorpho.sol";

Expand All @@ -32,7 +28,7 @@ import {IERC20, IERC4626, ERC20, ERC4626, Math, SafeERC20} from "@openzeppelin/t
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice ERC4626 compliant vault allowing users to deposit assets to Morpho.
contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorphoStaticTyping {
contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorpho {
using Math for uint256;
using UtilsLib for uint256;
using SafeCast for uint256;
Expand Down Expand Up @@ -471,40 +467,44 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph
/* ERC4626 (PUBLIC) */

/// @inheritdoc IERC20Metadata
function decimals() public view override(ERC20, ERC4626) returns (uint8) {
function decimals() public view override(IERC20Metadata, ERC20, ERC4626) returns (uint8) {
return ERC4626.decimals();
}

/// @inheritdoc IERC4626
function maxWithdraw(address owner) public view override returns (uint256 assets) {
function maxWithdraw(address owner) public view override(IERC4626, ERC4626) returns (uint256 assets) {
(assets,,) = _maxWithdraw(owner);
}

/// @inheritdoc IERC4626
function maxRedeem(address owner) public view override returns (uint256) {
function maxRedeem(address owner) public view override(IERC4626, ERC4626) returns (uint256) {
(uint256 assets, uint256 newTotalSupply, uint256 newTotalAssets) = _maxWithdraw(owner);

return _convertToSharesWithTotals(assets, newTotalSupply, newTotalAssets, Math.Rounding.Floor);
}

/// @inheritdoc IERC4626
function deposit(uint256 assets, address receiver) public override returns (uint256 shares) {
function deposit(uint256 assets, address receiver) public override(IERC4626, ERC4626) returns (uint256 shares) {
uint256 newTotalAssets = _accrueFee();

shares = _convertToSharesWithTotals(assets, totalSupply(), newTotalAssets, Math.Rounding.Floor);
_deposit(_msgSender(), receiver, assets, shares);
}

/// @inheritdoc IERC4626
function mint(uint256 shares, address receiver) public override returns (uint256 assets) {
function mint(uint256 shares, address receiver) public override(IERC4626, ERC4626) returns (uint256 assets) {
uint256 newTotalAssets = _accrueFee();

assets = _convertToAssetsWithTotals(shares, totalSupply(), newTotalAssets, Math.Rounding.Ceil);
_deposit(_msgSender(), receiver, assets, shares);
}

/// @inheritdoc IERC4626
function withdraw(uint256 assets, address receiver, address owner) public override returns (uint256 shares) {
function withdraw(uint256 assets, address receiver, address owner)
public
override(IERC4626, ERC4626)
returns (uint256 shares)
{
uint256 newTotalAssets = _accrueFee();

// Do not call expensive `maxWithdraw` and optimistically withdraw assets.
Expand All @@ -514,7 +514,11 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph
}

/// @inheritdoc IERC4626
function redeem(uint256 shares, address receiver, address owner) public override returns (uint256 assets) {
function redeem(uint256 shares, address receiver, address owner)
public
override(IERC4626, ERC4626)
returns (uint256 assets)
{
uint256 newTotalAssets = _accrueFee();

// Do not call expensive `maxRedeem` and optimistically redeem shares.
Expand All @@ -524,7 +528,7 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph
}

/// @inheritdoc IERC4626
function totalAssets() public view override returns (uint256 assets) {
function totalAssets() public view override(IERC4626, ERC4626) returns (uint256 assets) {
for (uint256 i; i < withdrawQueue.length; ++i) {
assets += _supplyBalance(_marketParams(withdrawQueue[i]));
}
Expand Down
41 changes: 9 additions & 32 deletions src/interfaces/IMetaMorpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity >=0.5.0;

import {IMorpho, Id, MarketParams} from "@morpho-blue/interfaces/IMorpho.sol";
import {IERC4626} from "@openzeppelin/interfaces/IERC4626.sol";
import {IERC20Permit} from "@openzeppelin/token/ERC20/extensions/IERC20Permit.sol";

struct MarketConfig {
/// @notice The maximum amount of assets that can be allocated to the market.
Expand Down Expand Up @@ -36,21 +35,7 @@ struct MarketAllocation {
uint256 shares;
}

interface IMulticall {
function multicall(bytes[] calldata) external returns (bytes[] memory);
}

interface IOwnable {
function owner() external 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 {
interface IMetaMorpho is IERC4626 {
function MORPHO() external view returns (IMorpho);

function curator() external view returns (address);
Expand All @@ -65,24 +50,29 @@ interface IMetaMorphoBase {
function supplyQueueSize() external view returns (uint256);
function withdrawQueue(uint256) external view returns (Id);
function withdrawQueueSize() external view returns (uint256);
function config(Id) external view returns (uint192 cap, uint64 withdrawRank);

function idle() external view returns (uint256);
function lastTotalAssets() external view returns (uint256);

function submitTimelock(uint256 newTimelock) external;
function acceptTimelock() external;
function revokeTimelock() external;
function pendingTimelock() external view returns (uint192 value, uint64 submittedAt);

function submitCap(MarketParams memory marketParams, uint256 supplyCap) external;
function acceptCap(Id id) external;
function revokeCap(Id id) external;
function pendingCap(Id) external view returns (uint192 value, uint64 submittedAt);

function submitFee(uint256 newFee) external;
function acceptFee() external;
function pendingFee() external view returns (uint192 value, uint64 submittedAt);

function submitGuardian(address newGuardian) external;
function acceptGuardian() external;
function revokeGuardian() external;
function pendingGuardian() external view returns (address guardian, uint96 submittedAt);

function transferRewards(address) external;

Expand All @@ -96,21 +86,8 @@ interface IMetaMorphoBase {
function reallocate(MarketAllocation[] calldata withdrawn, MarketAllocation[] calldata supplied) 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 {
function config(Id) external view returns (uint192 cap, uint64 withdrawRank);
function pendingGuardian() external view returns (address guardian, uint96 submittedAt);
function pendingCap(Id) external view returns (uint192 value, uint64 submittedAt);
function pendingTimelock() external view returns (uint192 value, uint64 submittedAt);
function pendingFee() external view returns (uint192 value, uint64 submittedAt);
}

/// @dev Use this interface for MetaMorpho vaults to have access to all the functions with the appropriate signatures.
interface IMetaMorpho is IMetaMorphoBase, IERC4626, IERC20Permit, IOwnable, IMulticall {
function config(Id) external view returns (MarketConfig memory);
function pendingGuardian() external view returns (PendingAddress memory);
function pendingCap(Id) external view returns (PendingUint192 memory);
interface IPending {
function pendingTimelock() external view returns (PendingUint192 memory);
function pendingFee() external view returns (PendingUint192 memory);
function pendingCap(Id) external view returns (PendingUint192 memory);
function pendingGuardian() external view returns (PendingAddress memory);
}
30 changes: 15 additions & 15 deletions test/forge/GuardianTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@ contract GuardianTest is IntegrationTest {
vm.warp(block.timestamp + elapsed);

vm.expectEmit();
emit EventsLib.RevokeTimelock(GUARDIAN, vault.pendingTimelock());
emit EventsLib.RevokeTimelock(GUARDIAN, IPending(address(vault)).pendingTimelock());
vm.prank(GUARDIAN);
vault.revokeTimelock();

uint256 newTimelock = vault.timelock();
PendingUint192 memory pendingTimelock = vault.pendingTimelock();
(uint256 pendingTimelock, uint64 submittedAt) = vault.pendingTimelock();

assertEq(newTimelock, TIMELOCK, "newTimelock");
assertEq(pendingTimelock.value, 0, "pendingTimelock.value");
assertEq(pendingTimelock.submittedAt, 0, "pendingTimelock.submittedAt");
assertEq(pendingTimelock, 0, "pendingTimelock");
assertEq(submittedAt, 0, "submittedAt");
}

function testRevokeCapIncreased(uint256 seed, uint256 cap, uint256 elapsed) public {
Expand All @@ -63,17 +63,17 @@ contract GuardianTest is IntegrationTest {
Id id = marketParams.id();

vm.expectEmit();
emit EventsLib.RevokeCap(GUARDIAN, id, vault.pendingCap(id));
emit EventsLib.RevokeCap(GUARDIAN, id, IPending(address(vault)).pendingCap(id));
vm.prank(GUARDIAN);
vault.revokeCap(id);

MarketConfig memory marketConfig = vault.config(id);
PendingUint192 memory pendingCap = vault.pendingCap(id);
(uint192 newCap, uint64 withdrawRank) = vault.config(id);
(uint256 pendingCap, uint64 submittedAt) = vault.pendingCap(id);

assertEq(marketConfig.cap, 0, "marketConfig.cap");
assertEq(marketConfig.withdrawRank, 0, "marketConfig.withdrawRank");
assertEq(pendingCap.value, 0, "pendingCap.value");
assertEq(pendingCap.submittedAt, 0, "pendingCap.submittedAt");
assertEq(newCap, 0, "newCap");
assertEq(withdrawRank, 0, "withdrawRank");
assertEq(pendingCap, 0, "pendingCap");
assertEq(submittedAt, 0, "submittedAt");
}

function testRevokeGuardian(uint256 elapsed) public {
Expand All @@ -87,15 +87,15 @@ contract GuardianTest is IntegrationTest {
vm.warp(block.timestamp + elapsed);

vm.expectEmit();
emit EventsLib.RevokeGuardian(GUARDIAN, vault.pendingGuardian());
emit EventsLib.RevokeGuardian(GUARDIAN, IPending(address(vault)).pendingGuardian());
vm.prank(GUARDIAN);
vault.revokeGuardian();

address newGuardian = vault.guardian();
PendingAddress memory pendingGuardian = vault.pendingGuardian();
(address pendingGuardian, uint96 submittedAt) = vault.pendingGuardian();

assertEq(newGuardian, GUARDIAN, "newGuardian");
assertEq(pendingGuardian.value, address(0), "pendingGuardian.value");
assertEq(pendingGuardian.submittedAt, 0, "pendingGuardian.submittedAt");
assertEq(pendingGuardian, address(0), "pendingGuardian");
assertEq(submittedAt, 0, "submittedAt");
}
}
Loading

0 comments on commit 2f9a8e7

Please sign in to comment.