• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

delvtech / hyperdrive / 9991233897

18 Jul 2024 11:31AM UTC coverage: 91.602% (-0.5%) from 92.08%
9991233897

push

github

web-flow
Added a Morpho Blue integration (#1094)

* Implemented a basic version of the `addLiquidity` circuit breaker

* Fixed `test_lp_withdrawal_long_and_short_maturity`

* Fixed the remaining tests

* add priceDiscoveryCheck to LPMath and also check it in initialize

* use initial price

* add tests and fix placement of check

* remove lib from LPMath

* remove comment

* remove console import

* remove console import

* fix price discovery tests

* fixed tests

* commit test to investigate

* add test_solvency_at_0_apr

* add test_solvency_cross_checkpoint_long_short

* address review feedback

* Update test/integrations/hyperdrive/PriceDiscovery.t.sol

* Added some testing examples

* Minor updates

* Updated `verifyPriceDiscovery` to `calculateSolvencyAfterMaxLong`

* Cleaned up the tests

* Increased the efficiency of the solvency check

* Fixed the code size issue

* Addressed Saw Mon's comment

* Improved one of the price discovery tests

* Updated the price discovery tests

* Fixed the remaining tests

* Addressed review feedback from @mcclurejt

* Fixed the deployment scripts

* Generated the code for the Aave integration

* forge install: aave-v3-core

v1.19.1

* Fixed codegen and compiler errors

* Implemented `_convertToBase` and `_convertToShares` for AaveHyperdrive

* Implemented the deposit functions for the AaveHyperdrive instance

* Implemented the withdrawal logic for ATokens

* Addressed most of the remaining FIXMEs

* Reduced the code-size of the Aave integration

* Copied over the instance test

* Added a fourth target to fix the codesize issues

* Started work on the AaveHyperdrive tests

* Fixed some of the tests

* Fixed more tests

* Fixed the remaining Aave instance tests

* Fixed the other instance tests

* Addressed remaining FIXMEs and fixed the code generator

* Fixed the publish scripts

* Lowered the minimum share reserves

* Addressed review feedback from @jrhea

* Added conversion functions to the public interfaces for insta... (continued)

58 of 76 new or added lines in 11 files covered. (76.32%)

3 existing lines in 3 files now uncovered.

2138 of 2334 relevant lines covered (91.6%)

369381.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.82
/contracts/src/instances/morpho-blue/MorphoBlueBase.sol
1
// SPDX-License-Identifier: Apache-2.0
2
pragma solidity 0.8.20;
3

4
import { IMorpho, MarketParams } from "morpho-blue/src/interfaces/IMorpho.sol";
5
import { MarketParamsLib } from "morpho-blue/src/libraries/MarketParamsLib.sol";
6
import { SharesMathLib } from "morpho-blue/src/libraries/SharesMathLib.sol";
7
import { MorphoBalancesLib } from "morpho-blue/src/libraries/periphery/MorphoBalancesLib.sol";
8
import { ERC20 } from "openzeppelin/token/ERC20/ERC20.sol";
9
import { SafeERC20 } from "openzeppelin/token/ERC20/utils/SafeERC20.sol";
10
import { IHyperdrive } from "../../interfaces/IHyperdrive.sol";
11
import { IMorphoBlueHyperdrive } from "../../interfaces/IMorphoBlueHyperdrive.sol";
12
import { HyperdriveBase } from "../../internal/HyperdriveBase.sol";
13
import { MorphoBlueConversions } from "./MorphoBlueConversions.sol";
14

15
/// @author DELV
16
/// @title MorphoBlueBase
17
/// @notice The base contract for the MorphoBlue Hyperdrive implementation.
18
/// @dev This Hyperdrive implementation is designed to work with standard
19
///      MorphoBlue vaults. Non-standard implementations may not work correctly
20
///      and should be carefully checked.
21
/// @custom:disclaimer The language used in this code is for coding convenience
22
///                    only, and is not intended to, and does not, have any
23
///                    particular legal or regulatory significance.
24
abstract contract MorphoBlueBase is HyperdriveBase {
25
    using SafeERC20 for ERC20;
26
    using MarketParamsLib for MarketParams;
27
    using MorphoBalancesLib for IMorpho;
28
    using SharesMathLib for uint256;
29

30
    /// @dev The Morpho Blue contract.
31
    IMorpho internal immutable _vault;
32

33
    /// @dev The collateral token for this Morpho Blue market.
34
    address internal immutable _collateralToken;
35

36
    /// @dev The oracle for this Morpho Blue market.
37
    address internal immutable _oracle;
38

39
    /// @dev The IRM for this Morpho Blue market.
40
    address internal immutable _irm;
41

42
    /// @dev The LLTV for this Morpho Blue market.
43
    uint256 internal immutable _lltv;
44

45
    /// @notice Instantiates the MorphoBlueHyperdrive base contract.
46
    /// @param _params The Morpho Blue params.
47
    constructor(IMorphoBlueHyperdrive.MorphoBlueParams memory _params) {
48
        // Initialize the Morpho vault immutable.
49
        _vault = _params.morpho;
150✔
50

51
        // Initialize the market parameters immutables. We don't need an
52
        // immutable for the loan token because we set the base token to the
53
        // loan token.
54
        _collateralToken = _params.collateralToken;
150✔
55
        _oracle = _params.oracle;
150✔
56
        _irm = _params.irm;
150✔
57
        _lltv = _params.lltv;
150✔
58

59
        // Approve the Morpho vault with 1 wei. This ensures that all of the
60
        // subsequent approvals will be writing to a dirty storage slot.
61
        ERC20(address(_baseToken)).forceApprove(address(_vault), 1);
150✔
62
    }
63

64
    /// Yield Source ///
65

66
    /// @dev Accepts a deposit from the user in base.
67
    /// @param _baseAmount The base amount to deposit.
68
    /// @param _extraData Additional data to pass to the Morpho vault. This
69
    ///        should be zero if it is unused.
70
    /// @return sharesMinted The shares that were minted in the deposit.
71
    /// @return value The amount of ETH to refund. Since this yield source isn't
72
    ///         payable, this is always zero.
73
    function _depositWithBase(
74
        uint256 _baseAmount,
75
        bytes calldata _extraData
76
    ) internal override returns (uint256 sharesMinted, uint256 value) {
77
        // Take custody of the deposit in base.
78
        ERC20(address(_baseToken)).safeTransferFrom(
532✔
79
            msg.sender,
80
            address(this),
81
            _baseAmount
82
        );
83

84
        // Deposit the base into the yield source.
85
        //
86
        // NOTE: We increase the required approval amount by 1 wei so that
87
        // the vault ends with an approval of 1 wei. This makes future
88
        // approvals cheaper by keeping the storage slot warm.
89
        ERC20(address(_baseToken)).forceApprove(
532✔
90
            address(_vault),
91
            _baseAmount + 1
92
        );
93
        (, sharesMinted) = _vault.supply(
532✔
94
            MarketParams({
95
                loanToken: address(_baseToken),
96
                collateralToken: _collateralToken,
97
                oracle: _oracle,
98
                irm: _irm,
99
                lltv: _lltv
100
            }),
101
            _baseAmount,
102
            0,
103
            address(this),
104
            _extraData
105
        );
106

107
        // NOTE: Since this yield source isn't payable, the value must be zero.
108
        value = 0;
532✔
NEW
109
        return (sharesMinted, value);
×
110
    }
111

112
    /// @dev Deposits with shares are not supported for this integration.
113
    function _depositWithShares(
114
        uint256, // unused _shareAmount
115
        bytes calldata // unused _extraData
116
    ) internal pure override {
NEW
117
        revert IHyperdrive.UnsupportedToken();
×
118
    }
119

120
    /// @dev Process a withdrawal in base and send the proceeds to the
121
    ///      destination.
122
    /// @param _shareAmount The amount of vault shares to withdraw.
123
    /// @param _destination The destination of the withdrawal.
124
    /// @return amountWithdrawn The amount of base withdrawn.
125
    function _withdrawWithBase(
126
        uint256 _shareAmount,
127
        address _destination,
128
        bytes calldata // unused
129
    ) internal override returns (uint256 amountWithdrawn) {
130
        (amountWithdrawn, ) = _vault.withdraw(
206✔
131
            MarketParams({
132
                loanToken: address(_baseToken),
133
                collateralToken: _collateralToken,
134
                oracle: _oracle,
135
                irm: _irm,
136
                lltv: _lltv
137
            }),
138
            0,
139
            _shareAmount,
140
            address(this),
141
            _destination
142
        );
143

NEW
144
        return amountWithdrawn;
×
145
    }
146

147
    /// @dev Withdrawals with shares are not supported for this integration.
148
    function _withdrawWithShares(
149
        uint256, // unused _shareAmount
150
        address, // unused _destination
151
        bytes calldata // unused
152
    ) internal pure override {
NEW
153
        revert IHyperdrive.UnsupportedToken();
×
154
    }
155

156
    /// @dev Convert an amount of vault shares to an amount of base.
157
    /// @param _shareAmount The vault shares amount.
158
    /// @return The base amount.
159
    function _convertToBase(
160
        uint256 _shareAmount
161
    ) internal view override returns (uint256) {
162
        return
1,751✔
163
            MorphoBlueConversions.convertToBase(
1,751✔
164
                _vault,
165
                _baseToken,
166
                _collateralToken,
167
                _oracle,
168
                _irm,
169
                _lltv,
170
                _shareAmount
171
            );
172
    }
173

174
    /// @dev Convert an amount of base to an amount of vault shares.
175
    /// @param _baseAmount The base amount.
176
    /// @return The vault shares amount.
177
    function _convertToShares(
178
        uint256 _baseAmount
179
    ) internal view override returns (uint256) {
180
        return
1,017✔
181
            MorphoBlueConversions.convertToShares(
1,017✔
182
                _vault,
183
                _baseToken,
184
                _collateralToken,
185
                _oracle,
186
                _irm,
187
                _lltv,
188
                _baseAmount
189
            );
190
    }
191

192
    /// @dev Gets the total amount of shares held by the pool in the yield
193
    ///      source.
194
    /// @return shareAmount The total amount of shares.
195
    function _totalShares()
196
        internal
197
        view
198
        override
199
        returns (uint256 shareAmount)
200
    {
201
        return
2✔
202
            _vault
203
                .position(
204
                    MarketParams({
205
                        loanToken: address(_baseToken),
206
                        collateralToken: _collateralToken,
207
                        oracle: _oracle,
208
                        irm: _irm,
209
                        lltv: _lltv
210
                    }).id(),
211
                    address(this)
212
                )
213
                .supplyShares;
214
    }
215

216
    /// @dev We override the message value check since this integration is
217
    ///      not payable.
218
    function _checkMessageValue() internal view override {
219
        if (msg.value != 0) {
536✔
220
            revert IHyperdrive.NotPayable();
4✔
221
        }
222
    }
223
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc