-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7340a3b
commit 351f548
Showing
7 changed files
with
226 additions
and
15 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity ^0.8.12; | ||
|
||
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; | ||
|
||
import "../../BaseFeedPTPendle.sol"; | ||
|
||
/// @title MorphoFeedPTUSDe | ||
/// @author Angle Labs, Inc. | ||
/// @notice Gives the price of PT-USDe in ETH in base 18 | ||
contract MorphoFeedPTUSDe is BaseFeedPTPendle { | ||
string public constant description = "PT-USDe/USDe Oracle"; | ||
|
||
constructor( | ||
IAccessControlManager accessControlManager, | ||
Check notice Code scanning / Slither Local variable shadowing Low |
||
uint256 _maxImpliedRate, | ||
uint32 _twapDuration | ||
) BaseFeedPTPendle(accessControlManager, _maxImpliedRate, _twapDuration) {} | ||
|
||
/*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
OVERRIDES | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ | ||
|
||
function asset() public pure override returns (address) { | ||
return 0x4c9EDD5852cd905f086C759E8383e09bff1E68B3; | ||
} | ||
|
||
function sy() public pure override returns (address) { | ||
return 0x42862F48eAdE25661558AFE0A630b132038553D0; | ||
} | ||
|
||
function maturity() public pure override returns (uint256) { | ||
return 1721865600; | ||
} | ||
|
||
function market() public pure override returns (address) { | ||
return 0x19588F29f9402Bb508007FeADd415c875Ee3f19F; | ||
} | ||
} |
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,4 +1,5 @@ | ||
[profile.default] | ||
evm_version = "shanghai" | ||
src = 'contracts' | ||
out = 'out' | ||
test = 'test' | ||
|
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,34 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.17; | ||
|
||
import "forge-std/Script.sol"; | ||
import { console } from "forge-std/console.sol"; | ||
import { MorphoFeedPTUSDe } from "borrow-contracts/oracle/morpho/mainnet/MorphoFeedPTUSDe.sol"; | ||
import "utils/src/CommonUtils.sol"; | ||
import { IAccessControlManager } from "borrow-contracts/interfaces/IAccessControlManager.sol"; | ||
|
||
contract PTweETHOracleDeploy is Script, CommonUtils { | ||
function run() external { | ||
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY"); | ||
address deployer = vm.addr(deployerPrivateKey); | ||
vm.startBroadcast(deployerPrivateKey); | ||
|
||
// TODO | ||
uint256 chainId = CHAIN_ETHEREUM; | ||
address coreBorrow = 0x5bc6BEf80DA563EBf6Df6D6913513fa9A7ec89BE; | ||
uint32 _TWAP_DURATION = 30 minutes; | ||
uint256 _MAX_IMPLIED_RATE = 0.5 ether; | ||
// end TODO | ||
|
||
MorphoFeedPTUSDe oracle = new MorphoFeedPTUSDe( | ||
IAccessControlManager(address(coreBorrow)), | ||
_MAX_IMPLIED_RATE, | ||
_TWAP_DURATION | ||
); | ||
(, int256 answer, , , ) = oracle.latestRoundData(); | ||
console.log("oracle value ", uint256(answer)); | ||
console.log("Successfully deployed PT-weETH: ", address(oracle)); | ||
|
||
vm.stopBroadcast(); | ||
} | ||
} |
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
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,91 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.12; | ||
|
||
import "./MorphoFeedPTPendle.t.sol"; | ||
import { MorphoFeedPTUSDe } from "borrow-contracts/oracle/morpho/mainnet/MorphoFeedPTUSDe.sol"; | ||
import { IAccessControlManager } from "borrow-contracts/interfaces/IAccessControlManager.sol"; | ||
|
||
contract MorphoFeedPTUSDeTest is MorphoFeedPTPendleTest { | ||
using stdStorage for StdStorage; | ||
|
||
function setUp() public override { | ||
super.setUp(); | ||
|
||
_TWAP_DURATION = 30 minutes; | ||
_STALE_PERIOD = 24 hours; | ||
_MAX_IMPLIED_RATE = 0.5 ether; | ||
|
||
_oracle = BaseFeedPTPendle( | ||
address(new MorphoFeedPTUSDe(IAccessControlManager(address(coreBorrow)), _MAX_IMPLIED_RATE, _TWAP_DURATION)) | ||
); | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
CORE LOGIC | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ | ||
|
||
function test_Description_Success() public { | ||
assertEq(_oracle.description(), "PT-USDe/USDe Oracle"); | ||
} | ||
|
||
function test_Simple_Success() public { | ||
(, int256 answer, , , ) = _oracle.latestRoundData(); | ||
uint256 value = uint256(answer); | ||
|
||
assertApproxEqAbs(value, 0.90 ether, 0.01 ether); | ||
} | ||
|
||
function test_EconomicalLowerBound_tooSmall() public { | ||
vm.prank(_governor); | ||
_oracle.setMaxImpliedRate(uint256(1e1)); | ||
uint256 pendleAMMPrice = PendlePtOracleLib.getPtToAssetRate(IPMarket(_oracle.market()), _TWAP_DURATION); | ||
|
||
(, int256 answer, , , ) = _oracle.latestRoundData(); | ||
uint256 value = uint256(answer); | ||
|
||
assertEq(value, pendleAMMPrice); | ||
} | ||
|
||
function test_AfterMaturity_Success() public { | ||
// Adavnce to the PT maturity | ||
vm.warp(_oracle.maturity()); | ||
|
||
uint256 pendleAMMPrice = PendlePtOracleLib.getPtToAssetRate(IPMarket(_oracle.market()), _TWAP_DURATION); | ||
(, int256 answer, , , ) = _oracle.latestRoundData(); | ||
uint256 value = uint256(answer); | ||
|
||
assertEq(value, pendleAMMPrice); | ||
assertEq(value, 1 ether); | ||
} | ||
|
||
function test_HackRemove_Success(uint256 slash) public { | ||
slash = bound(slash, 1, BASE_18); | ||
// Remove part of the SY backing collateral to simulate a hack | ||
IERC20 weETH = IERC20(address(_oracle.asset())); | ||
uint256 prevBalance = weETH.balanceOf(_oracle.sy()); | ||
uint256 postBalance = (prevBalance * slash) / BASE_18; | ||
deal(address(weETH), _oracle.sy(), postBalance); | ||
|
||
uint256 lowerBound = _economicLowerBound(_MAX_IMPLIED_RATE, _oracle.maturity()); | ||
(, int256 answer, , , ) = _oracle.latestRoundData(); | ||
uint256 value = uint256(answer); | ||
|
||
assertLe(value, (lowerBound * slash) / BASE_18); | ||
if (slash > 0) assertGe(value, (lowerBound * (slash - 1)) / BASE_18); | ||
} | ||
|
||
function test_HackExpand_Success(uint256 expand) public { | ||
expand = bound(expand, BASE_18, BASE_18 * 1e7); | ||
// Remove part of the SY backing collateral to simulate a hack | ||
IERC20 weETH = IERC20(address(_oracle.asset())); | ||
uint256 prevBalance = weETH.balanceOf(_oracle.sy()); | ||
uint256 postBalance = (prevBalance * expand) / BASE_18; | ||
deal(address(weETH), _oracle.sy(), postBalance); | ||
|
||
uint256 lowerBound = _economicLowerBound(_MAX_IMPLIED_RATE, _oracle.maturity()); | ||
(, int256 answer, , , ) = _oracle.latestRoundData(); | ||
uint256 value = uint256(answer); | ||
|
||
assertEq(value, lowerBound); | ||
} | ||
} |