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

delvtech / hyperdrive / 12941312920

24 Jan 2025 12:10AM UTC coverage: 89.489% (+0.3%) from 89.229%
12941312920

push

github

web-flow
Ensure that Morpho is the caller of `onMorphoFlashLoan` (#1227)

* Ensure that Morpho is the caller of `onMorphoFlashLoan`

* Updated coverage job

* Addressed a front-running vulnerability in the matching engine (#1228)

* Allow traders to specify the counterparty and fee recipient of their trades

* Added a non-reentrancy modifier to `cancelOrders` (#1229)

8 of 8 new or added lines in 1 file covered. (100.0%)

17 existing lines in 4 files now uncovered.

3014 of 3368 relevant lines covered (89.49%)

328347.25 hits per line

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

98.0
/contracts/src/external/HyperdriveTarget0.sol
1
// SPDX-License-Identifier: Apache-2.0
2
pragma solidity 0.8.24;
3

4
import { IERC20 } from "../interfaces/IERC20.sol";
5
import { IHyperdrive } from "../interfaces/IHyperdrive.sol";
6
import { IHyperdriveAdminController } from "../interfaces/IHyperdriveAdminController.sol";
7
import { IHyperdriveRead } from "../interfaces/IHyperdriveRead.sol";
8
import { HyperdriveAdmin } from "../internal/HyperdriveAdmin.sol";
9
import { HyperdriveCheckpoint } from "../internal/HyperdriveCheckpoint.sol";
10
import { HyperdriveLong } from "../internal/HyperdriveLong.sol";
11
import { HyperdriveLP } from "../internal/HyperdriveLP.sol";
12
import { HyperdriveMultiToken } from "../internal/HyperdriveMultiToken.sol";
13
import { HyperdrivePair } from "../internal/HyperdrivePair.sol";
14
import { HyperdriveShort } from "../internal/HyperdriveShort.sol";
15
import { HyperdriveStorage } from "../internal/HyperdriveStorage.sol";
16
import { AssetId } from "../libraries/AssetId.sol";
17
import { VERSION } from "../libraries/Constants.sol";
18
import { FixedPointMath } from "../libraries/FixedPointMath.sol";
19
import { LPMath } from "../libraries/LPMath.sol";
20

21
/// @author DELV
22
/// @title HyperdriveTarget0
23
/// @notice Hyperdrive's target 0 logic contract.
24
/// @custom:disclaimer The language used in this code is for coding convenience
25
///                    only, and is not intended to, and does not, have any
26
///                    particular legal or regulatory significance.
27
abstract contract HyperdriveTarget0 is
28
    IHyperdriveRead,
29
    HyperdriveAdmin,
30
    HyperdriveMultiToken,
31
    HyperdriveLP,
32
    HyperdriveLong,
33
    HyperdriveShort,
34
    HyperdrivePair,
35
    HyperdriveCheckpoint
36
{
37
    using FixedPointMath for uint256;
38

39
    /// @notice Instantiates target0.
40
    /// @param _config The configuration of the Hyperdrive pool.
41
    /// @param __adminController The admin controller that will specify the
42
    ///        admin parameters for this contract.
43
    constructor(
44
        IHyperdrive.PoolConfig memory _config,
45
        IHyperdriveAdminController __adminController
46
    ) HyperdriveStorage(_config, __adminController) {}
47

48
    /// Admin ///
49

50
    // TODO: This function doesn't do anything anymore and is only here for
51
    // backwards compatability. This can be removed when the factory is upgraded.
52
    //
53
    /// @notice A stub for the old setPauser functions that doesn't do anything
54
    ///         anymore.
55
    /// @dev Don't call this. It doesn't do anything.
56
    function setGovernance(address) external {}
57

58
    // TODO: This function doesn't do anything anymore and is only here for
59
    // backwards compatability. This can be removed when the factory is upgraded.
60
    //
61
    /// @notice A stub for the old setPauser functions that doesn't do anything
62
    ///         anymore.
63
    /// @dev Don't call this. It doesn't do anything.
64
    function setPauser(address, bool) external {}
65

66
    /// @notice This function collects the governance fees accrued by the pool.
67
    /// @param _options The options that configure how the fees are settled.
68
    /// @return proceeds The governance fees collected. The units of this
69
    ///         quantity are either base or vault shares, depending on the value
70
    ///         of `_options.asBase`.
71
    function collectGovernanceFee(
72
        IHyperdrive.Options calldata _options
73
    ) external returns (uint256 proceeds) {
74
        return _collectGovernanceFee(_options);
5✔
75
    }
76

77
    /// @notice Allows an authorized address to pause this contract.
78
    /// @param _status True to pause all deposits and false to unpause them.
79
    function pause(bool _status) external {
80
        _pause(_status);
11✔
81
    }
82

83
    /// @notice Transfers the contract's balance of a target token to the sweep
84
    ///         collector address.
85
    /// @dev WARN: It is unlikely but possible that there is a selector overlap
86
    ///      with 'transfer'. Any integrating contracts should be checked
87
    ///      for that, as it may result in an unexpected call from this address.
88
    /// @param _target The target token to sweep.
89
    function sweep(IERC20 _target) external {
90
        _sweep(_target);
77✔
91
    }
92

93
    /// MultiToken ///
94

95
    /// @notice Transfers an amount of assets from the source to the destination.
96
    /// @param tokenID The token identifier.
97
    /// @param from The address whose balance will be reduced.
98
    /// @param to The address whose balance will be increased.
99
    /// @param amount The amount of token to move.
100
    function transferFrom(
101
        uint256 tokenID,
102
        address from,
103
        address to,
104
        uint256 amount
105
    ) external {
106
        // Forward to our internal version
107
        _transferFrom(tokenID, from, to, amount, msg.sender);
7✔
108
    }
109

110
    /// @notice Permissioned transfer for the bridge to access, only callable by
111
    ///         the ERC20 linking bridge.
112
    /// @param tokenID The token identifier.
113
    /// @param from The address whose balance will be reduced.
114
    /// @param to The address whose balance will be increased.
115
    /// @param amount The amount of token to move.
116
    /// @param caller The msg.sender from the bridge.
117
    function transferFromBridge(
118
        uint256 tokenID,
119
        address from,
120
        address to,
121
        uint256 amount,
122
        address caller
123
    ) external onlyLinker(tokenID) {
124
        // Route to our internal transfer
125
        _transferFrom(tokenID, from, to, amount, caller);
101✔
126
    }
127

128
    /// @notice Allows the compatibility linking contract to forward calls to
129
    ///         set asset approvals.
130
    /// @param tokenID The asset to approve the use of.
131
    /// @param operator The address who will be able to use the tokens.
132
    /// @param amount The max tokens the approved person can use, setting to
133
    ///        uint256.max will cause the value to never decrement [saving gas
134
    ///        on transfer].
135
    /// @param caller The eth address which called the linking contract.
136
    function setApprovalBridge(
137
        uint256 tokenID,
138
        address operator,
139
        uint256 amount,
140
        address caller
141
    ) external onlyLinker(tokenID) {
142
        _setApproval(tokenID, operator, amount, caller);
4✔
143
    }
144

145
    /// @notice Allows a user to approve an operator to use all of their assets.
146
    /// @param operator The eth address which can access the caller's assets.
147
    /// @param approved True to approve, false to remove approval.
148
    function setApprovalForAll(address operator, bool approved) external {
149
        // set the appropriate state
150
        _isApprovedForAll[msg.sender][operator] = approved;
60✔
151
        // Emit an event to track approval
152
        emit ApprovalForAll(msg.sender, operator, approved);
60✔
153
    }
154

155
    /// @notice Allows a user to set an approval for an individual asset with
156
    ///         specific amount.
157
    /// @param tokenID The asset to approve the use of.
158
    /// @param operator The address who will be able to use the tokens.
159
    /// @param amount The max tokens the approved person can use, setting to
160
    ///        uint256.max will cause the value to never decrement (saving gas
161
    ///        on transfer).
162
    function setApproval(
163
        uint256 tokenID,
164
        address operator,
165
        uint256 amount
166
    ) external {
167
        _setApproval(tokenID, operator, amount, msg.sender);
81✔
168
    }
169

170
    /// @notice Transfers several assets from one account to another.
171
    /// @param from The source account.
172
    /// @param to The destination account.
173
    /// @param ids The array of token ids of the asset to transfer.
174
    /// @param values The amount of each token to transfer.
175
    function batchTransferFrom(
176
        address from,
177
        address to,
178
        uint256[] calldata ids,
179
        uint256[] calldata values
180
    ) external {
181
        _batchTransferFrom(from, to, ids, values);
6✔
182
    }
183

184
    /// @notice Allows a caller who is not the owner of an account to execute
185
    ///         the functionality of 'approve' for all assets with the owner's
186
    ///         signature.
187
    /// @param domainSeparator The EIP712 domain separator of the contract.
188
    /// @param permitTypeHash The EIP712 domain separator of the contract.
189
    /// @param owner The owner of the account which is having the new approval set.
190
    /// @param spender The address which will be allowed to spend owner's tokens.
191
    /// @param _approved A boolean of the approval status to set to.
192
    /// @param deadline The timestamp which the signature must be submitted by
193
    ///        to be valid.
194
    /// @param v Extra ECDSA data which allows public key recovery from
195
    ///        signature assumed to be 27 or 28.
196
    /// @param r The r component of the ECDSA signature.
197
    /// @param s The s component of the ECDSA signature.
198
    /// @dev The signature for this function follows EIP 712 standard and should
199
    ///      be generated with the eth_signTypedData JSON RPC call instead of
200
    ///      the eth_sign JSON RPC call. If using out of date parity signing
201
    ///      libraries the v component may need to be adjusted. Also it is very
202
    ///      rare but possible for v to be other values, those values are not
203
    ///      supported.
204
    function permitForAll(
205
        bytes32 domainSeparator,
206
        bytes32 permitTypeHash,
207
        address owner,
208
        address spender,
209
        bool _approved,
210
        uint256 deadline,
211
        uint8 v,
212
        bytes32 r,
213
        bytes32 s
214
    ) external {
215
        _permitForAll(
8✔
216
            domainSeparator,
217
            permitTypeHash,
218
            owner,
219
            spender,
220
            _approved,
221
            deadline,
222
            v,
223
            r,
224
            s
225
        );
226
    }
227

228
    /// Getters ///
229

230
    /// @notice Gets the instance's name.
231
    /// @return The instance's name.
232
    function name() external view returns (string memory) {
233
        _revert(abi.encode(_name));
171✔
234
    }
235

236
    /// @notice Gets the instance's kind.
237
    /// @return The instance's kind.
238
    function kind() external pure virtual returns (string memory);
239

240
    /// @notice Gets the instance's version.
241
    /// @return The instance's version.
242
    function version() external pure returns (string memory) {
243
        _revert(abi.encode(VERSION));
111✔
244
    }
245

246
    /// @notice Gets the address that contains the admin configuration for this
247
    ///         instance.
248
    /// @return The admin controller address.
249
    function adminController() external view returns (address) {
UNCOV
250
        _revert(abi.encode(_adminController));
×
251
    }
252

253
    /// @notice Gets the pauser status of an address.
254
    /// @param _account The account to check.
255
    /// @return The pauser status.
256
    function isPauser(address _account) external view returns (bool) {
257
        _revert(abi.encode(_isPauser(_account)));
5✔
258
    }
259

260
    /// @notice Gets the base token.
261
    /// @return The base token address.
262
    function baseToken() external view returns (address) {
263
        _revert(abi.encode(_baseToken));
16,588✔
264
    }
265

266
    /// @notice Gets the vault shares token.
267
    /// @return The vault shares token address.
268
    function vaultSharesToken() external view returns (address) {
269
        _revert(abi.encode(_vaultSharesToken));
5,662✔
270
    }
271

272
    /// @notice Gets a specified checkpoint.
273
    /// @param _checkpointTime The checkpoint time.
274
    /// @return The checkpoint.
275
    function getCheckpoint(
276
        uint256 _checkpointTime
277
    ) external view returns (IHyperdrive.Checkpoint memory) {
278
        _revert(abi.encode(_checkpoints[_checkpointTime]));
21,422✔
279
    }
280

281
    /// @notice Gets the checkpoint exposure at a specified time.
282
    /// @param _checkpointTime The checkpoint time.
283
    /// @return The checkpoint exposure.
284
    function getCheckpointExposure(
285
        uint256 _checkpointTime
286
    ) external view returns (int256) {
287
        _revert(
69,482✔
288
            abi.encode(_nonNettedLongs(_checkpointTime + _positionDuration))
289
        );
290
    }
291

292
    /// @notice Gets the pool's configuration parameters.
293
    /// @dev These parameters are immutable, so this should only need to be
294
    ///      called once.
295
    /// @return The PoolConfig struct.
296
    function getPoolConfig()
297
        external
298
        view
299
        returns (IHyperdrive.PoolConfig memory)
300
    {
301
        _revert(
2,089,816✔
302
            abi.encode(
303
                IHyperdrive.PoolConfig({
304
                    baseToken: _baseToken,
305
                    vaultSharesToken: _vaultSharesToken,
306
                    linkerFactory: _linkerFactory,
307
                    linkerCodeHash: _linkerCodeHash,
308
                    initialVaultSharePrice: _initialVaultSharePrice,
309
                    minimumShareReserves: _minimumShareReserves,
310
                    minimumTransactionAmount: _minimumTransactionAmount,
311
                    circuitBreakerDelta: _circuitBreakerDelta,
312
                    positionDuration: _positionDuration,
313
                    checkpointDuration: _checkpointDuration,
314
                    timeStretch: _timeStretch,
315
                    governance: _adminController.hyperdriveGovernance(),
316
                    feeCollector: _adminController.feeCollector(),
317
                    sweepCollector: _adminController.sweepCollector(),
318
                    checkpointRewarder: _adminController.checkpointRewarder(),
319
                    fees: IHyperdrive.Fees(
320
                        _curveFee,
321
                        _flatFee,
322
                        _governanceLPFee,
323
                        _governanceZombieFee
324
                    )
325
                })
326
            )
327
        );
328
    }
329

330
    /// @notice Gets info about the pool's reserves and other state that is
331
    ///         important to evaluate potential trades.
332
    /// @return The pool info.
333
    function getPoolInfo() external view returns (IHyperdrive.PoolInfo memory) {
334
        uint256 vaultSharePrice = _pricePerVaultShare();
242,531✔
335
        uint256 lpTotalSupply = _totalSupply[AssetId._LP_ASSET_ID] +
242,531✔
336
            _totalSupply[AssetId._WITHDRAWAL_SHARE_ASSET_ID] -
337
            _withdrawPool.readyToWithdraw;
338
        uint256 presentValue;
242,531✔
339
        if (vaultSharePrice > 0) {
242,531✔
340
            (presentValue, ) = LPMath.calculatePresentValueSafe(
241,931✔
341
                _getPresentValueParams(vaultSharePrice)
342
            );
343
            presentValue = presentValue.mulDown(vaultSharePrice);
241,931✔
344
        }
345
        IHyperdrive.PoolInfo memory poolInfo = IHyperdrive.PoolInfo({
242,531✔
346
            shareReserves: _marketState.shareReserves,
347
            shareAdjustment: _marketState.shareAdjustment,
348
            zombieBaseProceeds: _marketState.zombieBaseProceeds,
349
            zombieShareReserves: _marketState.zombieShareReserves,
350
            bondReserves: _marketState.bondReserves,
351
            vaultSharePrice: vaultSharePrice,
352
            longsOutstanding: _marketState.longsOutstanding,
353
            longAverageMaturityTime: _marketState.longAverageMaturityTime,
354
            shortsOutstanding: _marketState.shortsOutstanding,
355
            shortAverageMaturityTime: _marketState.shortAverageMaturityTime,
356
            lpTotalSupply: lpTotalSupply,
357
            lpSharePrice: lpTotalSupply == 0
358
                ? 0
359
                : presentValue.divDown(lpTotalSupply),
360
            withdrawalSharesReadyToWithdraw: _withdrawPool.readyToWithdraw,
361
            withdrawalSharesProceeds: _withdrawPool.proceeds,
362
            longExposure: _marketState.longExposure
363
        });
364
        _revert(abi.encode(poolInfo));
242,531✔
365
    }
366

367
    /// @notice Gets information about the withdrawal pool.
368
    /// @return Hyperdrive's withdrawal pool information.
369
    function getWithdrawPool()
370
        external
371
        view
372
        returns (IHyperdrive.WithdrawPool memory)
373
    {
374
        _revert(
2✔
375
            abi.encode(
376
                IHyperdrive.WithdrawPool({
377
                    readyToWithdraw: _withdrawPool.readyToWithdraw,
378
                    proceeds: _withdrawPool.proceeds
379
                })
380
            )
381
        );
382
    }
383

384
    /// @notice Gets info about the fees presently accrued by the pool.
385
    /// @return Governance fees denominated in shares yet to be collected.
386
    function getUncollectedGovernanceFees() external view returns (uint256) {
387
        _revert(abi.encode(_governanceFeesAccrued));
3,425✔
388
    }
389

390
    /// @notice Gets the market state.
391
    /// @return The market state.
392
    function getMarketState()
393
        external
394
        view
395
        returns (IHyperdrive.MarketState memory)
396
    {
397
        _revert(abi.encode(_marketState));
13✔
398
    }
399

400
    /// @notice Allows plugin data libs to provide getters or other complex
401
    ///         logic instead of the main.
402
    /// @param _slots The storage slots the caller wants the data from.
403
    /// @return A raw array of loaded data.
404
    function load(
405
        uint256[] calldata _slots
406
    ) external view returns (bytes32[] memory) {
407
        bytes32[] memory loaded = new bytes32[](_slots.length);
1✔
408

409
        // Iterate on requested loads and then do them.
410
        for (uint256 i = 0; i < _slots.length; i++) {
1✔
411
            uint256 slot = _slots[i];
2✔
412
            bytes32 data;
2✔
413
            assembly ("memory-safe") {
414
                data := sload(slot)
2✔
415
            }
416
            loaded[i] = data;
2✔
417
        }
418

419
        _revert(abi.encode(loaded));
1✔
420
    }
421

422
    /// @notice Convert an amount of vault shares to an amount of base.
423
    /// @dev This is a convenience method that allows developers to convert from
424
    ///      vault shares to base without knowing the specifics of the
425
    ///      integration.
426
    /// @param _shareAmount The vault shares amount.
427
    /// @return baseAmount The base amount.
428
    function convertToBase(
429
        uint256 _shareAmount
430
    ) external view returns (uint256) {
431
        _revert(abi.encode(_convertToBase(_shareAmount)));
32,300✔
432
    }
433

434
    /// @notice Convert an amount of base to an amount of vault shares.
435
    /// @dev This is a convenience method that allows developers to convert from
436
    ///      base to vault shares without knowing the specifics of the
437
    ///      integration.
438
    /// @param _baseAmount The base amount.
439
    /// @return shareAmount The vault shares amount.
440
    function convertToShares(
441
        uint256 _baseAmount
442
    ) external view returns (uint256) {
443
        _revert(abi.encode(_convertToShares(_baseAmount)));
50,466✔
444
    }
445

446
    /// @notice Gets the total amount of vault shares held by Hyperdrive.
447
    /// @dev This is a convenience method that allows developers to get the
448
    ///      total amount of vault shares without knowing the specifics of the
449
    ///      integration.
450
    /// @return The total amount of vault shares held by Hyperdrive.
451
    function totalShares() external view returns (uint256) {
452
        _revert(abi.encode(_totalShares()));
3,034✔
453
    }
454

455
    /// @notice Gets an account's balance of a sub-token.
456
    /// @param tokenId The sub-token id.
457
    /// @param account The account.
458
    /// @return The balance.
459
    function balanceOf(
460
        uint256 tokenId,
461
        address account
462
    ) external view returns (uint256) {
463
        _revert(abi.encode(_balanceOf[tokenId][account]));
25,939✔
464
    }
465

466
    /// @notice Gets the total supply of a sub-token.
467
    /// @param tokenId The sub-token id.
468
    /// @return The total supply.
469
    function totalSupply(uint256 tokenId) external view returns (uint256) {
470
        _revert(abi.encode(_totalSupply[tokenId]));
46,460✔
471
    }
472

473
    /// @notice Gets the approval status of an operator for an account.
474
    /// @param account The account.
475
    /// @param operator The operator.
476
    /// @return The approval status.
477
    function isApprovedForAll(
478
        address account,
479
        address operator
480
    ) external view returns (bool) {
481
        _revert(abi.encode(_isApprovedForAll[account][operator]));
10✔
482
    }
483

484
    /// @notice Gets the approval status of an operator for an account.
485
    /// @param tokenId The sub-token id.
486
    /// @param account The account.
487
    /// @param spender The spender.
488
    /// @return The approval status.
489
    function perTokenApprovals(
490
        uint256 tokenId,
491
        address account,
492
        address spender
493
    ) external view returns (uint256) {
494
        _revert(abi.encode(_perTokenApprovals[tokenId][account][spender]));
72✔
495
    }
496

497
    /// @notice Gets the decimals of the MultiToken. This is the same as the
498
    ///         decimals used by the base token.
499
    /// @return The decimals of the MultiToken.
500
    function decimals() external view virtual returns (uint8) {
501
        _revert(abi.encode(_baseToken.decimals()));
44✔
502
    }
503

504
    /// @notice Gets the name of a sub-token.
505
    /// @param tokenId The sub-token id.
506
    /// @return The name.
507
    function name(uint256 tokenId) external pure returns (string memory) {
508
        _revert(abi.encode(AssetId.assetIdToName(tokenId)));
2✔
509
    }
510

511
    /// @notice Gets the symbol of a sub-token.
512
    /// @param tokenId The sub-token id.
513
    /// @return The symbol.
514
    function symbol(uint256 tokenId) external pure returns (string memory) {
515
        _revert(abi.encode(AssetId.assetIdToSymbol(tokenId)));
2✔
516
    }
517

518
    /// @notice Gets the permitForAll signature nonce for an account.
519
    /// @param account The account.
520
    /// @return The signature nonce.
521
    function nonces(address account) external view returns (uint256) {
522
        _revert(abi.encode(_nonces[account]));
9✔
523
    }
524

525
    /// Helpers ///
526

527
    /// @dev Reverts with the provided bytes. This is useful in getters used
528
    ///      with the force-revert delegatecall pattern.
529
    /// @param _bytes The bytes to revert with.
530
    function _revert(bytes memory _bytes) internal pure {
531
        revert IHyperdrive.ReturnData(_bytes);
2,609,579✔
532
    }
533
}
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

© 2026 Coveralls, Inc