Skip to content

Commit

Permalink
Update examples to show usage of YT oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
UncleGrandpa925 committed Jun 4, 2024
1 parent 467a063 commit 5026671
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 59 deletions.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"forge-std": "github:foundry-rs/forge-std#v1.7.5",
"prettier": "^3.0.0",
"solhint": "^3.6.2",
"@pendle/core-v2": "^4.2.6"
"@pendle/core-v2": "^4.7.0"
},
"keywords": [
"blockchain",
Expand Down
96 changes: 38 additions & 58 deletions test/OracleSample.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,96 +6,76 @@ import { console2 as console } from "forge-std/src/console2.sol";
import { StdCheats } from "forge-std/src/StdCheats.sol";
import "@pendle/core-v2/contracts/interfaces/IPAllActionV3.sol";
import "@pendle/core-v2/contracts/interfaces/IPMarket.sol";
import "@pendle/core-v2/contracts/oracles/PendlePtLpOracle.sol";
import "@pendle/core-v2/contracts/oracles/PendlePYLpOracle.sol";
import "../src/StructGen.sol";
import { AggregatorV2V3Interface as IChainlinkAggregator } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol";

contract OracleSample is PRBTest, StdCheats, StructGen {
using PendlePtOracleLib for IPMarket;
using PendlePYOracleLib for IPMarket;
using PendleLpOracleLib for IPMarket;

IPMarket public constant market = IPMarket(0xE11f9786B06438456b044B3E21712228ADcAA0D1);
PendlePtLpOracle public constant oracle = PendlePtLpOracle(0x1Fd95db7B7C0067De8D45C0cb35D59796adfD187);
IChainlinkAggregator public constant feed = IChainlinkAggregator(0xA736eAe8805dDeFFba40cAB8c99bCB309dEaBd9B); // weETH
// to ETH, Redstone
uint8 public feedDecimals;

uint32 public constant twapDuration = 900;

IStandardizedYield public SY;
IPPrincipalToken public PT;
IPYieldToken public YT;

IPMarket public constant market = IPMarket(0x952083cde7aaa11AB8449057F7de23A970AA8472);
PendlePYLpOracle public constant oracle = PendlePYLpOracle(0x9a9Fa8338dd5E5B2188006f1Cd2Ef26d921650C2);

IChainlinkAggregator public constant weETH_ETH_feed =
IChainlinkAggregator(0xE141425bc1594b8039De6390db1cDaf4397EA22b);
IChainlinkAggregator public constant ETH_USD_feed = IChainlinkAggregator(0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612);
IChainlinkAggregator public constant USDC_USD_Feed = IChainlinkAggregator(0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3);

uint32 public constant twapDuration = 900;

function setUp() public virtual {
vm.createSelectFork({ urlOrAlias: "arbitrum", blockNumber: 192_001_277 });
vm.createSelectFork({ urlOrAlias: "arbitrum", blockNumber: 218241893 });
(SY, PT, YT) = IPMarket(market).readTokens();
_test_oracle_ready(address(market), twapDuration);
feedDecimals = uint8(feed.decimals());
}

function test_get_prices_use_library() external view {
uint256 ptRateInEEth = IPMarket(market).getPtToAssetRate(twapDuration);
console.log("1 PT = %s eEth (base 1e18)", ptRateInEEth);
function test_get_price_LRT_in_underlying() external view {
uint256 ptRateInWeEth = oracle.getPtToSyRate(address(market), twapDuration);
uint256 ytRateInWeEth = oracle.getYtToSyRate(address(market), twapDuration);
uint256 lpRateInWeEth = oracle.getLpToSyRate(address(market), twapDuration);

uint256 ptRateInWeEth = IPMarket(market).getPtToSyRate(twapDuration);
console.log("1 PT = %s weEth (base 1e18)", ptRateInWeEth);
console.log("1 PT = %s Wrapped eEth (base 1e18)", ptRateInWeEth);
console.log("1 YT = %s Wrapped eEth (base 1e18)", ytRateInWeEth);
console.log("1 LP = %s Wrapped eEth (base 1e18)", lpRateInWeEth);
}

uint256 lpRateInEEth = IPMarket(market).getLpToAssetRate(twapDuration);
console.log("1 LP = %s eEth (base 1e18)", lpRateInEEth);
function test_get_price_LRT_with_external_oracle() external view {
uint256 ptRateInWeEth = oracle.getPtToSyRate(address(market), twapDuration); // 1 SY-weETH = 1 weETH

uint256 lpRateInWeEth = IPMarket(market).getLpToSyRate(twapDuration);
console.log("1 LP = %s weEth (base 1e18)", lpRateInWeEth);
}
uint256 ptRateInEth = (ptRateInWeEth * uint256(weETH_ETH_feed.latestAnswer())) / (10 ** weETH_ETH_feed.decimals());
console.log("1 PT = %s ETH (base 1e18)", ptRateInEth); // 1 PT = 0.980103943942239852 ETH

function test_get_price_SY_multiply_by_external_price() external view {
uint256 ptRateInWeEth = IPMarket(market).getPtToSyRate(twapDuration); // 1 SY-weETH = 1 weETH
uint256 ptRateInEth = (ptRateInWeEth * uint256(feed.latestAnswer())) / (10 ** feedDecimals);
console.log("1 PT = %s ETH (base 1e18)", ptRateInEth);
uint256 ptRateInUsd = (ptRateInEth * uint256(ETH_USD_feed.latestAnswer())) / (10 ** ETH_USD_feed.decimals());
console.log("1 PT = %s USD (base 1e18)", ptRateInUsd); // 1 PT = 3714.1302603652102 USD
}

function test_get_price_asset_multiply_by_external_price() external view {
function test_get_price_aUSDC_with_external_price() external view {
address aUSDCMarket = 0xBa4A858d664Ddb052158168DB04AFA3cFF5CFCC8;
IChainlinkAggregator aUSDCFeed = IChainlinkAggregator(0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3); // aUSDC to
// USD, Chainlink

uint256 ptRateInUSDC = IPMarket(aUSDCMarket).getPtToAssetRate(twapDuration); // Have to get in asset because
// SY-aUSDC ~= aUSDC and doesn't have a price
// Have to get price in asset because SY-aUSDC != aUSDC and doesn't have a price
uint256 ptRateInUSDC = oracle.getPtToAssetRate(aUSDCMarket, twapDuration);

uint256 ptRateInUsd = (ptRateInUSDC * uint256(aUSDCFeed.latestAnswer())) / (10 ** 8);
uint256 ptRateInUsd = (ptRateInUSDC * uint256(USDC_USD_Feed.latestAnswer())) / (10 ** USDC_USD_Feed.decimals());
console.log("1 PT = %s USD (base 1e18)", ptRateInUsd);
}

function test_get_LP_price_use_library() external view {
uint256 lpRateInEEth = IPMarket(market).getLpToAssetRate(twapDuration);
console.log("1 LP = %s eEth (base 1e18)", lpRateInEEth);

uint256 lpRateInWeEth = IPMarket(market).getLpToSyRate(twapDuration);
console.log("1 LP = %s weEth (base 1e18)", lpRateInWeEth);

uint256 lpRateInEth = (lpRateInWeEth * uint256(feed.latestAnswer())) / (10 ** feedDecimals);
console.log("1 LP = %s ETH (base 1e18)", lpRateInEth);
}

/// @dev more gas consuming than using library, same results
function test_get_prices_use_oracle_contract() external view {
uint256 ptRateInEEth = oracle.getPtToAssetRate(address(market), twapDuration);
console.log("1 PT = %s eEth (base 1e18)", ptRateInEEth);

uint256 ptRateInWeEth = oracle.getPtToSyRate(address(market), twapDuration);
console.log("1 PT = %s weEth (base 1e18)", ptRateInWeEth);

uint256 lpRateInEEth = oracle.getLpToAssetRate(address(market), twapDuration);
console.log("1 LP = %s eEth (base 1e18)", lpRateInEEth);

uint256 lpRateInWeEth = oracle.getLpToSyRate(address(market), twapDuration);
console.log("1 LP = %s weEth (base 1e18)", lpRateInWeEth);
// ! Replace oracle.getPtToAssetRate to IPMarket(market).getPtToAssetRate to save 3000 gas
function test_get_price_save_gas() external view {
uint256 ptRateInWeEth = market.getPtToSyRate(twapDuration);
}

/// @dev Call only once for each (market, duration). Once successful, it's permanently valid (also for any shorter
/// duration).
function _test_oracle_ready(address marketToCheck, uint32 duration) public view {
(bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied) = oracle
.getOracleState(marketToCheck, duration);
(bool increaseCardinalityRequired, , bool oldestObservationSatisfied) = oracle.getOracleState(
marketToCheck,
duration
);

if (increaseCardinalityRequired) {
// It's required to call IPMarket(market).increaseObservationsCardinalityNext(cardinalityRequired) and wait
Expand Down

0 comments on commit 5026671

Please sign in to comment.