Skip to content

Commit

Permalink
added tests for relatyer child deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
MrDeadCe11 committed Jul 6, 2024
1 parent bf94cf0 commit 55b254c
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 9 deletions.
3 changes: 2 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ number_underscore = 'thousands'
wrap_comments = false

[profile.default]
evm_version = "cancun"
auto_detect_solc = true
src = "src"
out = "out"
libs = ["lib"]

[rpc_endpoints]
mainnet = "${ARB_MAINNET_RPC}"
sepolia = "${ARB_SEPOLIA_RPC}"
sepolia = "${ARB_SEPOLIA_RPC}"
5 changes: 5 additions & 0 deletions script/Registry.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,8 @@ address constant ARB = 0x912CE59144191C1204E64559FE8253a0e49E6548;
address constant ETH_ARB_POOL = 0xe51635ae8136aBAc44906A8f230C2D235E9c195F;

address constant MAINNET_DEPLOYER = 0xF78dA2A37049627636546E0cFAaB2aD664950917;

//Pendle
address constant MAINNET_PENDLE_ORACLE = 0x9a9Fa8338dd5E5B2188006f1Cd2Ef26d921650C2;
address constant MAINNET_PENDLE_RETH_MARKET = 0x14FbC760eFaF36781cB0eb3Cb255aD976117B9Bd;
address constant MAINNET_PENDLE_STETH_MARKET = 0x08a152834de126d2ef83D612ff36e4523FD0017F;
1 change: 1 addition & 0 deletions src/contracts/factories/pendle/PendleRelayerFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {PendlePtToSyRelayerChild} from '@contracts/factories/pendle/PendlePtToSy
import {PendleYtToSyRelayerChild} from '@contracts/factories/pendle/PendleYtToSyRelayerChild.sol';
import {PendleLpToSyRelayerChild} from '@contracts/factories/pendle/PendleLpToSyRelayerChild.sol';
import {Authorizable} from '@contracts/utils/Authorizable.sol';
import 'forge-std/console2.sol';

Check failure on line 9 in src/contracts/factories/pendle/PendleRelayerFactory.sol

View workflow job for this annotation

GitHub Actions / Run Linters (18.x)

Unexpected import of console file

Check warning on line 9 in src/contracts/factories/pendle/PendleRelayerFactory.sol

View workflow job for this annotation

GitHub Actions / Run Linters (18.x)

global import of path forge-std/console2.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 9 in src/contracts/factories/pendle/PendleRelayerFactory.sol

View workflow job for this annotation

GitHub Actions / Run Linters (18.x)

Import 'forge-std/console2.sol' in contract PendleRelayerFactory should be declared as import {contract_to_import} from 'forge-std/console2.sol';

contract PendleRelayerFactory is Authorizable {
uint256 public relayerId;
Expand Down
4 changes: 2 additions & 2 deletions src/contracts/oracles/pendle/PendleLpToSyRelayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ contract PendleLpToSyRelayer {

constructor(address _market, address _oracle, uint32 _twapDuration) {
require(_market != address(0) && _oracle != address(0), 'Invalid address');
require(twapDuration != 0, 'Invalid TWAP duration');
require(_twapDuration != 0, 'Invalid TWAP duration');

market = IPMarket(_market);
oracle = IPOracle(_oracle);
twapDuration = _twapDuration;

(SY, PT, YT) = market.readTokens();
symbol = string(abi.encodePacked(market.symbol()));
symbol = string(abi.encodePacked('LP => ', SY.symbol()));
// test if oracle is ready
(bool increaseCardinalityRequired,, bool oldestObservationSatisfied) = oracle.getOracleState(_market, _twapDuration);
// It's required to call IPMarket(market).increaseObservationsCardinalityNext(cardinalityRequired) and wait
Expand Down
8 changes: 5 additions & 3 deletions src/contracts/oracles/pendle/PendlePtToSyRelayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ pragma solidity 0.7.6;

import '@interfaces/oracles/pendle/IPOracle.sol';
import '@interfaces/oracles/pendle/IPMarket.sol';

import 'forge-std/console2.sol';

Check failure on line 6 in src/contracts/oracles/pendle/PendlePtToSyRelayer.sol

View workflow job for this annotation

GitHub Actions / Run Linters (18.x)

Unexpected import of console file
/**
* @title PendleRelayer
* @notice This contracts transforms a Pendle TWAP price feed into a standard IBaseOracle feed
*
*/

contract PendlePtToSyRelayer {
IStandardizedYield public SY;
IPPrincipalToken public PT;
Expand All @@ -22,14 +23,15 @@ contract PendlePtToSyRelayer {

constructor(address _market, address _oracle, uint32 _twapDuration) {
require(_market != address(0) && _oracle != address(0), 'Invalid address');
require(twapDuration != 0, 'Invalid TWAP duration');
require(_twapDuration != uint32(0), 'Invalid TWAP duration');

market = IPMarket(_market);
oracle = IPOracle(_oracle);
twapDuration = _twapDuration;

(SY, PT, YT) = market.readTokens();
symbol = string(abi.encodePacked(market.symbol()));
symbol = string(abi.encodePacked(PT.symbol(), ' => ', SY.symbol()));

// test if oracle is ready
(bool increaseCardinalityRequired,, bool oldestObservationSatisfied) = oracle.getOracleState(_market, _twapDuration);
// It's required to call IPMarket(market).increaseObservationsCardinalityNext(cardinalityRequired) and wait
Expand Down
4 changes: 2 additions & 2 deletions src/contracts/oracles/pendle/PendleYtToSyRelayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ contract PendleYtToSyRelayer {

constructor(address _market, address _oracle, uint32 _twapDuration) {
require(_market != address(0) && _oracle != address(0), 'Invalid address');
require(twapDuration != 0, 'Invalid TWAP duration');
require(_twapDuration != 0, 'Invalid TWAP duration');

market = IPMarket(_market);
oracle = IPOracle(_oracle);
twapDuration = _twapDuration;

(SY, PT, YT) = market.readTokens();
symbol = string(abi.encodePacked(market.symbol()));
symbol = string(abi.encodePacked(YT.symbol(), ' => ', SY.symbol()));
// test if oracle is ready
(bool increaseCardinalityRequired,, bool oldestObservationSatisfied) = oracle.getOracleState(_market, _twapDuration);
// It's required to call IPMarket(market).increaseObservationsCardinalityNext(cardinalityRequired) and wait
Expand Down
4 changes: 3 additions & 1 deletion src/interfaces/factories/IPendleRelayerFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
pragma solidity ^0.7.6;

import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol';
import {IAuthorizable} from '@interfaces/utils/IAuthorizable.sol';

interface IPendleRelayerFactory {
interface IPendleRelayerFactory is IAuthorizable {
// --- Events ---
event NewPendlePtRelayer(address indexed _market, address _oracle, uint32 _twapDuration);
event NewPendleYtRelayer(address indexed _market, address _oracle, uint32 _twapDuration);
event NewPendleLpRelayer(address indexed _market, address _oracle, uint32 _twapDuration);

// --- Methods ---
function relayerId() external view returns (uint256);

function deployPendlePtRelayer(
address _market,
Expand Down
18 changes: 18 additions & 0 deletions src/interfaces/oracles/pendle/IPendleRelayer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.6;

import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol';
import {IPMarket} from '@interfaces/oracles/pendle/IPMarket.sol';
import {IPOracle} from '@interfaces/oracles/pendle/IPOracle.sol';
import {IStandardizedYield} from '@interfaces/oracles/pendle/IStandardizedYield.sol';
import {IPPrincipalToken} from '@interfaces/oracles/pendle/IPPrincipalToken.sol';
import {IPYieldToken} from '@interfaces/oracles/pendle/IPYieldToken.sol';

interface IPendleRelayer is IBaseOracle {
function twapDuration() external view returns (uint32);
function market() external view returns (IPMarket);
function oracle() external view returns (IPOracle);
function SY() external view returns (IStandardizedYield);
function PT() external view returns (IPPrincipalToken);
function YT() external view returns (IPYieldToken);
}
73 changes: 73 additions & 0 deletions test/unit/RelayerFactories.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ import {CamelotRelayerFactory} from '@contracts/factories/CamelotRelayerFactory.
import {CamelotRelayerChild} from '@contracts/factories/CamelotRelayerChild.sol';
import {ChainlinkRelayerFactory} from '@contracts/factories/ChainlinkRelayerFactory.sol';
import {ChainlinkRelayerChild} from '@contracts/factories/ChainlinkRelayerChild.sol';
import {PendleRelayerFactory} from '@contracts/factories/pendle/PendleRelayerFactory.sol';
import {IBaseOracle} from '@interfaces/oracles/IBaseOracle.sol';
import {DenominatedOracleFactory} from '@contracts/factories/DenominatedOracleFactory.sol';
import {DenominatedOracleChild} from '@contracts/factories/DenominatedOracleChild.sol';
import {MAINNET_PENDLE_ORACLE, MAINNET_PENDLE_RETH_MARKET} from '@script/Registry.s.sol';
import {IAuthorizable} from '@interfaces/utils/IAuthorizable.sol';
import {IPendleRelayerFactory} from '@interfaces/factories/IPendleRelayerFactory.sol';
import {IPendleRelayer} from '@interfaces/oracles/pendle/IPendleRelayer.sol';

abstract contract Base is DSTestPlus {
address deployer = label('deployer');
Expand Down Expand Up @@ -381,3 +385,72 @@ contract Unit_DenominatedPriceOracleFactory_DeployDenominatedOracle is Base {
);
}
}

contract Unit_PendleRelayerFactory_DeployPendleOracles is Base {
IPendleRelayerFactory public pendleFactory;

function setUp() public virtual override {
super.setUp();
vm.createSelectFork(vm.envString('ARB_MAINNET_RPC'));
pendleFactory = IPendleRelayerFactory(address(new PendleRelayerFactory()));
}

function test_Deploy_PendleFactory() public {
assertEq(pendleFactory.relayerId(), 0);
assertEq(pendleFactory.authorizedAccounts()[0], address(this));
}

function test_Deploy_PT_Oracle() public {
IBaseOracle ptOracle =
pendleFactory.deployPendlePtRelayer(MAINNET_PENDLE_RETH_MARKET, MAINNET_PENDLE_ORACLE, uint32(900));
assertTrue(keccak256(abi.encode(ptOracle.symbol())) != keccak256(abi.encode('')));
assertEq(uint256(IPendleRelayer(address(ptOracle)).twapDuration()), 900);
assertEq(address(IPendleRelayer(address(ptOracle)).market()), MAINNET_PENDLE_RETH_MARKET);
assertEq(address(IPendleRelayer(address(ptOracle)).oracle()), MAINNET_PENDLE_ORACLE);
assertEq(address(IPendleRelayer(address(ptOracle)).PT()), 0x685155D3BD593508Fe32Be39729810A591ED9c87);
assertEq(address(IPendleRelayer(address(ptOracle)).YT()), 0xe822AE44EB2466B4E263b1cbC94b4833dDEf9700);
assertEq(address(IPendleRelayer(address(ptOracle)).SY()), 0xc0Cf4b266bE5B3229C49590B59E67A09c15b22f4);
}

function test_Deploy_YT_Oracle() public {
IBaseOracle ytOracle =
pendleFactory.deployPendleYtRelayer(MAINNET_PENDLE_RETH_MARKET, MAINNET_PENDLE_ORACLE, uint32(900));
assertTrue(keccak256(abi.encode(ytOracle.symbol())) != keccak256(abi.encode('')));
assertEq(uint256(IPendleRelayer(address(ytOracle)).twapDuration()), 900);
assertEq(address(IPendleRelayer(address(ytOracle)).market()), MAINNET_PENDLE_RETH_MARKET);
assertEq(address(IPendleRelayer(address(ytOracle)).oracle()), MAINNET_PENDLE_ORACLE);
assertEq(address(IPendleRelayer(address(ytOracle)).PT()), 0x685155D3BD593508Fe32Be39729810A591ED9c87);
assertEq(address(IPendleRelayer(address(ytOracle)).YT()), 0xe822AE44EB2466B4E263b1cbC94b4833dDEf9700);
assertEq(address(IPendleRelayer(address(ytOracle)).SY()), 0xc0Cf4b266bE5B3229C49590B59E67A09c15b22f4);
}

function test_Deploy_LP_Oracle() public {
IBaseOracle lpOracle =
pendleFactory.deployPendleLpRelayer(MAINNET_PENDLE_RETH_MARKET, MAINNET_PENDLE_ORACLE, uint32(900));
assertTrue(keccak256(abi.encode(lpOracle.symbol())) != keccak256(abi.encode('')));
assertEq(uint256(IPendleRelayer(address(lpOracle)).twapDuration()), 900);
assertEq(address(IPendleRelayer(address(lpOracle)).market()), MAINNET_PENDLE_RETH_MARKET);
assertEq(address(IPendleRelayer(address(lpOracle)).oracle()), MAINNET_PENDLE_ORACLE);
assertEq(address(IPendleRelayer(address(lpOracle)).PT()), 0x685155D3BD593508Fe32Be39729810A591ED9c87);
assertEq(address(IPendleRelayer(address(lpOracle)).YT()), 0xe822AE44EB2466B4E263b1cbC94b4833dDEf9700);
assertEq(address(IPendleRelayer(address(lpOracle)).SY()), 0xc0Cf4b266bE5B3229C49590B59E67A09c15b22f4);
}

function test_Deploy_Oracle_Revert_Invalid_Twap() public {
vm.expectRevert('Invalid TWAP duration');
pendleFactory.deployPendlePtRelayer(MAINNET_PENDLE_RETH_MARKET, MAINNET_PENDLE_ORACLE, uint32(0));
vm.expectRevert('Invalid TWAP duration');
pendleFactory.deployPendleYtRelayer(MAINNET_PENDLE_RETH_MARKET, MAINNET_PENDLE_ORACLE, uint32(0));
vm.expectRevert('Invalid TWAP duration');
pendleFactory.deployPendleLpRelayer(MAINNET_PENDLE_RETH_MARKET, MAINNET_PENDLE_ORACLE, uint32(0));
}

function test_Deploy_Oracle_Revert_Invalid_Address() public {
vm.expectRevert('Invalid address');
pendleFactory.deployPendlePtRelayer(address(0), MAINNET_PENDLE_ORACLE, uint32(900));
vm.expectRevert('Invalid address');
pendleFactory.deployPendleYtRelayer(address(0), MAINNET_PENDLE_ORACLE, uint32(900));
vm.expectRevert('Invalid address');
pendleFactory.deployPendleLpRelayer(address(0), MAINNET_PENDLE_ORACLE, uint32(900));
}
}

0 comments on commit 55b254c

Please sign in to comment.