-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement a proposed contract structure
Implement a proposed contract structure Update Update Add more internal Add and rework more internal format Format Add more internal Add more internal Remove timestamp usage Move stuff around Remove unnecessary constants Address comments Remove some unused libs and test signed commit
- Loading branch information
1 parent
9fee7ab
commit 64a999c
Showing
30 changed files
with
1,474 additions
and
55 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
Submodule aave-v3-core
added at
f3e037
Submodule aave-v3-periphery
added at
932f36
Submodule morpho-utils
added at
dbf669
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 |
---|---|---|
@@ -1,5 +1,10 @@ | ||
ds-test/=lib/forge-std/lib/ds-test/src/ | ||
forge-std/=lib/forge-std/src/ | ||
openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts | ||
morpho-data-structures/=lib/morpho-data-structures/contracts/ | ||
@ds-test/=lib/forge-std/lib/ds-test/src/ | ||
@forge-std/=lib/forge-std/src/ | ||
|
||
@morpho-data-structures/=lib/morpho-data-structures/contracts/ | ||
@morpho-utils/=lib/morpho-utils/src/ | ||
|
||
@openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts | ||
@openzeppelin/=node_modules/@openzeppelin/ | ||
@aave/core-v3/=lib/aave-v3-core/ | ||
@aave/periphery-v3/=lib/aave-v3-periphery/ |
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,8 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.17; | ||
|
||
import {Types, Events, Errors, MarketLib} from "./libraries/Libraries.sol"; | ||
|
||
import {MatchingEngine} from "./MatchingEngine.sol"; | ||
|
||
contract EntryPositionsManager is MatchingEngine {} |
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,8 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.17; | ||
|
||
import {Types, Events, Errors, MarketLib} from "./libraries/Libraries.sol"; | ||
|
||
import {MatchingEngine} from "./MatchingEngine.sol"; | ||
|
||
contract ExitPositionsManager is MatchingEngine {} |
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,171 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.17; | ||
|
||
import {Types, Events, ThreeHeapOrdering, Math, WadRayMath} from "./libraries/Libraries.sol"; | ||
|
||
import {MorphoInternal} from "./MorphoInternal.sol"; | ||
|
||
abstract contract MatchingEngine is MorphoInternal { | ||
using Math for uint256; | ||
using ThreeHeapOrdering for ThreeHeapOrdering.HeapArray; | ||
using WadRayMath for uint256; | ||
|
||
function _matchSuppliers(address poolToken, uint256 amount, uint256 maxLoops) | ||
internal | ||
returns (uint256 matched, uint256 loopsDone) | ||
{ | ||
Types.Market storage market = _market[poolToken]; | ||
return _matchOrUnmatch( | ||
_marketBalances[poolToken].suppliersPool, | ||
_marketBalances[poolToken].suppliersP2P, | ||
Types.MatchVars({ | ||
poolToken: poolToken, | ||
poolIndex: market.poolSupplyIndex, | ||
p2pIndex: market.p2pSupplyIndex, | ||
amount: amount, | ||
maxLoops: maxLoops, | ||
borrow: false, | ||
matching: true | ||
}) | ||
); | ||
} | ||
|
||
function _matchBorrowers(address poolToken, uint256 amount, uint256 maxLoops) | ||
internal | ||
returns (uint256 matched, uint256 loopsDone) | ||
{ | ||
Types.Market storage market = _market[poolToken]; | ||
return _matchOrUnmatch( | ||
_marketBalances[poolToken].borrowersPool, | ||
_marketBalances[poolToken].borrowersP2P, | ||
Types.MatchVars({ | ||
poolToken: poolToken, | ||
poolIndex: market.poolBorrowIndex, | ||
p2pIndex: market.p2pBorrowIndex, | ||
amount: amount, | ||
maxLoops: maxLoops, | ||
borrow: true, | ||
matching: true | ||
}) | ||
); | ||
} | ||
|
||
function _unmatchSuppliers(address poolToken, uint256 amount, uint256 maxLoops) | ||
internal | ||
returns (uint256 unmatched) | ||
{ | ||
Types.Market storage market = _market[poolToken]; | ||
(unmatched,) = _matchOrUnmatch( | ||
_marketBalances[poolToken].suppliersPool, | ||
_marketBalances[poolToken].suppliersP2P, | ||
Types.MatchVars({ | ||
poolToken: poolToken, | ||
poolIndex: market.poolSupplyIndex, | ||
p2pIndex: market.p2pSupplyIndex, | ||
amount: amount, | ||
maxLoops: maxLoops, | ||
borrow: false, | ||
matching: false | ||
}) | ||
); | ||
} | ||
|
||
function _unmatchBorrowers(address poolToken, uint256 amount, uint256 maxLoops) | ||
internal | ||
returns (uint256 unmatched) | ||
{ | ||
Types.Market storage market = _market[poolToken]; | ||
(unmatched,) = _matchOrUnmatch( | ||
_marketBalances[poolToken].borrowersPool, | ||
_marketBalances[poolToken].borrowersP2P, | ||
Types.MatchVars({ | ||
poolToken: poolToken, | ||
poolIndex: market.poolBorrowIndex, | ||
p2pIndex: market.p2pBorrowIndex, | ||
amount: amount, | ||
maxLoops: maxLoops, | ||
borrow: true, | ||
matching: false | ||
}) | ||
); | ||
} | ||
|
||
function _matchOrUnmatch( | ||
ThreeHeapOrdering.HeapArray storage heapOnPool, | ||
ThreeHeapOrdering.HeapArray storage heapInP2P, | ||
Types.MatchVars memory vars | ||
) internal returns (uint256 matched, uint256 loopsDone) { | ||
if (vars.maxLoops == 0) return (0, 0); | ||
|
||
uint256 remainingToMatch = vars.amount; | ||
|
||
// prettier-ignore | ||
// This function will be used to decide whether to use the algorithm for matching or for unmatching. | ||
function(uint256, uint256, uint256, uint256, uint256) | ||
pure returns (uint256, uint256, uint256) f; | ||
ThreeHeapOrdering.HeapArray storage workingHeap; | ||
|
||
if (vars.matching) { | ||
workingHeap = heapOnPool; | ||
f = _matchStep; | ||
} else { | ||
workingHeap = heapInP2P; | ||
f = _unmatchStep; | ||
} | ||
|
||
for (; loopsDone < vars.maxLoops; ++loopsDone) { | ||
// Safe unchecked because `gasLeftAtTheBeginning` >= gas left now. | ||
address firstUser = workingHeap.getHead(); | ||
if (firstUser == address(0)) break; | ||
|
||
uint256 onPool; | ||
uint256 inP2P; | ||
|
||
(onPool, inP2P, remainingToMatch) = f( | ||
heapOnPool.getValueOf(firstUser), | ||
heapInP2P.getValueOf(firstUser), | ||
vars.poolIndex, | ||
vars.p2pIndex, | ||
remainingToMatch | ||
); | ||
|
||
if (!vars.borrow) { | ||
_updateSupplierInDS(vars.poolToken, firstUser, onPool, inP2P); | ||
} else { | ||
_updateBorrowerInDS(vars.poolToken, firstUser, onPool, inP2P); | ||
} | ||
|
||
emit Events.PositionUpdated(vars.borrow, firstUser, vars.poolToken, onPool, inP2P); | ||
} | ||
|
||
// Safe unchecked because `gasLeftAtTheBeginning` >= gas left now. | ||
// And _amount >= remainingToMatch. | ||
unchecked { | ||
matched = vars.amount - remainingToMatch; | ||
} | ||
} | ||
|
||
function _matchStep(uint256 poolBalance, uint256 p2pBalance, uint256 poolIndex, uint256 p2pIndex, uint256 remaining) | ||
internal | ||
pure | ||
returns (uint256 newPoolBalance, uint256 newP2PBalance, uint256 newRemaining) | ||
{ | ||
uint256 toProcess = Math.min(poolBalance.rayMul(poolIndex), remaining); | ||
newRemaining = remaining - toProcess; | ||
newPoolBalance = poolBalance - toProcess.rayDiv(poolIndex); | ||
newP2PBalance = p2pBalance + toProcess.rayDiv(p2pIndex); | ||
} | ||
|
||
function _unmatchStep( | ||
uint256 poolBalance, | ||
uint256 p2pBalance, | ||
uint256 poolIndex, | ||
uint256 p2pIndex, | ||
uint256 remaining | ||
) internal pure returns (uint256 newPoolBalance, uint256 newP2PBalance, uint256 newRemaining) { | ||
uint256 toProcess = Math.min(p2pBalance.rayMul(p2pIndex), remaining); | ||
newRemaining = remaining - toProcess; | ||
newPoolBalance = poolBalance + toProcess.rayDiv(poolIndex); | ||
newP2PBalance = p2pBalance - toProcess.rayDiv(p2pIndex); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.17; | ||
|
||
import {Types, Events, Errors, MarketLib} from "./libraries/Libraries.sol"; | ||
|
||
import {MorphoInternal} from "./MorphoInternal.sol"; | ||
|
||
abstract contract MorphoGettersAndSetters is MorphoInternal { | ||
using MarketLib for Types.MarketBalances; | ||
using MarketLib for Types.Market; | ||
|
||
/// STORAGE /// | ||
|
||
function market(address poolToken) external view returns (Types.Market memory) { | ||
return _market[poolToken]; | ||
} | ||
|
||
function scaledPoolSupplyBalance(address poolToken, address user) external view returns (uint256) { | ||
return _marketBalances[poolToken].scaledPoolSupplyBalance(user); | ||
} | ||
|
||
function scaledP2PSupplyBalance(address poolToken, address user) external view returns (uint256) { | ||
return _marketBalances[poolToken].scaledP2PSupplyBalance(user); | ||
} | ||
|
||
function scaledPoolBorrowBalance(address poolToken, address user) external view returns (uint256) { | ||
return _marketBalances[poolToken].scaledPoolBorrowBalance(user); | ||
} | ||
|
||
function scaledP2PBorrowBalance(address poolToken, address user) external view returns (uint256) { | ||
return _marketBalances[poolToken].scaledP2PBorrowBalance(user); | ||
} | ||
|
||
function scaledCollateralBalance(address poolToken, address user) external view returns (uint256) { | ||
return _marketBalances[poolToken].scaledCollateralBalance(user); | ||
} | ||
|
||
function userMarkets(address user) external view returns (Types.UserMarkets memory) { | ||
return _userMarkets[user]; | ||
} | ||
|
||
function maxSortedUsers() external view returns (uint256) { | ||
return _maxSortedUsers; | ||
} | ||
|
||
function isClaimRewardsPaused() external view returns (bool) { | ||
return _isClaimRewardsPaused; | ||
} | ||
|
||
/// UTILITY /// | ||
|
||
function decodeId(uint256 id) external pure returns (address poolToken, Types.PositionType positionType) { | ||
return _decodeId(id); | ||
} | ||
|
||
/// ERC1155 /// | ||
|
||
function balanceOf(address user, uint256 id) external view returns (uint256) { | ||
(address poolToken, Types.PositionType positionType) = _decodeId(id); | ||
Types.MarketBalances storage marketBalances = _marketBalances[poolToken]; | ||
|
||
if (positionType == Types.PositionType.COLLATERAL) { | ||
return marketBalances.scaledCollateralBalance(user); | ||
} else if (positionType == Types.PositionType.SUPPLY) { | ||
return marketBalances.scaledP2PSupplyBalance(user) + marketBalances.scaledPoolSupplyBalance(user); // TODO: take into account indexes. | ||
} else if (positionType == Types.PositionType.BORROW) { | ||
return marketBalances.scaledP2PBorrowBalance(user) + marketBalances.scaledPoolBorrowBalance(user); // TODO: take into account indexes. | ||
} else { | ||
return 0; | ||
} | ||
} | ||
} |
Oops, something went wrong.