Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions src/factory/MarketFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "src/Market.sol";

contract MarketFactory {
IDolaBorrowingRights public constant DBR = IDolaBorrowingRights(0xAD038Eb671c44b853887A7E32528FaB35dC5D710);
uint256 public constant INITIAL_COLLATERAL_FACTOR_BPS = 5000;
uint256 public constant INITIAL_REPLENISHMENT_INCENTIVE_BPS = 5000;
uint256 public constant INITIAL_LIQUIDATION_INCENTIVE_BPS = 100;
IOracle public oracle;
address public gov;
address public fed;
address public pauseGuardian;
address public pendingGov;

mapping(address => bool) public isFromFactory;

event NewMarket(address indexed collateral, address indexed market);
event NewOracle(address indexed oldOracle, address indexed newOracle);
event NewFed(address indexed oldFed, address indexed newFed);
event NewPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian);
event NewPendingGov(address indexed oldPendingGov, address indexed newPendingGov);
event NewGov(address indexed oldGov, address indexed newGov);

constructor(address _gov, address _oracle, address _fed, address _pauseGuardian) {
gov = _gov;
oracle = IOracle(_oracle);
fed = _fed;
pauseGuardian = _pauseGuardian;

}

modifier onlyGov() {
require(msg.sender == gov, "Only gov");
_;
}

/**
* @notice Deploy a new market contract with preset values.
* @dev This market then has to be approved and initialized by on-chain vote after deployment.
* @param collateral collateral for the market
* @param escrowImpl implementation of the escrow contract
* @param callbackOnDeposit whether to callback on deposit
*/
function deployMarket(address collateral, address escrowImpl, bool callbackOnDeposit)
external
returns (address market)
{
market = address(
new Market(
gov,
fed,
pauseGuardian,
escrowImpl,
DBR,
IERC20(collateral),
oracle,
INITIAL_COLLATERAL_FACTOR_BPS,
INITIAL_REPLENISHMENT_INCENTIVE_BPS,
INITIAL_LIQUIDATION_INCENTIVE_BPS,
callbackOnDeposit
)
);
isFromFactory[market] = true;
emit NewMarket(collateral, market);
}

// Admin functions

/**
* @notice Set a new pending gov. The new pending gov then has to call `acceptGov`.
* @dev Can only be called by the gov.
* @param _pendingGov address of the new pending gov
*/
function setPendingGov(address _pendingGov) external onlyGov {
emit NewPendingGov(pendingGov, _pendingGov);
pendingGov = _pendingGov;

}

/**
* @notice Accept the new pending gov.
* @dev Can only be called by the pending gov.
*/
function acceptGov() external {
require(msg.sender == pendingGov, "Only pending gov");
emit NewGov(gov, pendingGov);
gov = pendingGov;
pendingGov = address(0);
}

/**
* @notice Set a new oracle.
* @dev Can only be called by the gov.
* @param _oracle address of the new oracle
*/
function setOracle(address _oracle) external onlyGov {
emit NewOracle(address(oracle), _oracle);
oracle = IOracle(_oracle);
}

/**
* @notice Set a new fed.
* @dev Can only be called by the gov.
* @param _fed address of the new fed
*/
function setFed(address _fed) external onlyGov {
emit NewFed(fed, _fed);
fed = _fed;
}

/**
* @notice Set a new pause guardian.
* @dev Can only be called by the gov.
* @param _pauseGuardian address of the new pause guardian
*/
function setPauseGuardian(address _pauseGuardian) external onlyGov {
emit NewPauseGuardian(pauseGuardian, _pauseGuardian);
pauseGuardian = _pauseGuardian;
}
}
125 changes: 125 additions & 0 deletions src/factory/PTUSDeFeedSwitchFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {FeedSwitch} from "src/util/FeedSwitch.sol";
import {USDeNavBeforeMaturityFeed} from "src/feeds/USDeNavBeforeMaturityFeed.sol";
import {NavBeforeMaturityFeed} from "src/feeds/NavBeforeMaturityFeed.sol";
import {PendleNAVFeed} from "src/feeds/PendleNAVFeed.sol";

contract PTUSDeFeedSwitchFactory {
address public constant USDeWrapperFeed = 0xB3C1D801A02d88adC96A294123c2Daa382345058;
address public constant sUSDeWrapper = 0xD723a0910e261de49A90779d38A94aFaAA028F15;
address public constant sUSDe = 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497;
address public gov;
uint256 public timelockPeriod;
address public guardian;
address public pendingGov;

mapping(address => bool) public isFromFactory;

event NewFeedSwitch(
address indexed pendlePT, address indexed feedSwitch, address indexed navFeed, address beforeMaturityFeed, address afterMaturityFeed
);
event NewPendingGov(address indexed oldPendingGov, address indexed newPendingGov);
event NewGov(address indexed oldGov, address indexed newGov);
event NewTimelockPeriod(uint256 oldTimelockPeriod, uint256 newTimelockPeriod);
event NewGuardian(address indexed oldGuardian, address indexed newGuardian);

constructor(address _gov, address _guardian, uint256 _timelockPeriod) {
gov = _gov;
guardian = _guardian;
timelockPeriod = _timelockPeriod;
}

modifier onlyGov() {
require(msg.sender == gov, "Only gov");
_;
}

/**
* @notice Deploy a new PT USDe feed.
* @dev The deployed feed has to be set in the oracle for the specific market via on-chain vote.
* @param pendlePT address of the Pendle PT
* @param baseDiscount base discount for the feed
*/
function deployUSDeFeed(address pendlePT, uint256 baseDiscount) external returns (address feedSwitch) {
PendleNAVFeed navFeed = new PendleNAVFeed(pendlePT, baseDiscount);

NavBeforeMaturityFeed beforeMaturityFeed = new NavBeforeMaturityFeed(USDeWrapperFeed, address(navFeed));

feedSwitch = address(
new FeedSwitch(
address(navFeed), address(beforeMaturityFeed), USDeWrapperFeed, timelockPeriod, pendlePT, guardian
)
);
isFromFactory[feedSwitch] = true;

emit NewFeedSwitch(pendlePT, feedSwitch, address(navFeed), address(beforeMaturityFeed), USDeWrapperFeed);
}

/**
* @notice Deploy a new PT sUSDe feed.
* @dev The deployed feed has to be set in the oracle for the specific market via on-chain vote.
* @param pendlePT address of the Pendle PT
* @param baseDiscount base discount for the feed
*/
function deploySUSDeFeed(address pendlePT, uint256 baseDiscount) external returns (address feedSwitch) {
PendleNAVFeed navFeed = new PendleNAVFeed(pendlePT, baseDiscount);

USDeNavBeforeMaturityFeed beforeMaturityFeed =
new USDeNavBeforeMaturityFeed(sUSDeWrapper, sUSDe, address(navFeed)); // USDeBeforeMaturityFeed: USDe/USD Feed using sUSDe Chainlink feed and sUSDe/USDe rate and NAV

feedSwitch = address(
new FeedSwitch(
address(navFeed), address(beforeMaturityFeed), USDeWrapperFeed, timelockPeriod, pendlePT, guardian
)
);

isFromFactory[feedSwitch] = true;

emit NewFeedSwitch(pendlePT, feedSwitch, address(navFeed), address(beforeMaturityFeed), USDeWrapperFeed);
}

// Admin functions

/**
* @notice Set a new pending gov. The new pending gov then has to call `acceptGov`.
* @dev Can only be called by the gov.
* @param _pendingGov address of the new pending gov
*/
function setPendingGov(address _pendingGov) external onlyGov {
emit NewPendingGov(pendingGov, _pendingGov);
pendingGov = _pendingGov;
}

/**
* @notice Accept the new pending gov.
* @dev Can only be called by the pending gov.
*/
function acceptGov() external {
require(msg.sender == pendingGov, "Only pending gov");
emit NewGov(gov, pendingGov);
gov = pendingGov;
pendingGov = address(0);
}

/**
* @notice Set a new timelock period for all deployed feeds.
* @dev Can only be called by the gov.
* @param _timelockPeriod new timelock period
*/
function setTimelockPeriod(uint256 _timelockPeriod) external onlyGov {
emit NewTimelockPeriod(timelockPeriod, _timelockPeriod);
timelockPeriod = _timelockPeriod;
}

/**
* @notice Set a new guardian.
* @dev Can only be called by the gov.
* @param _guardian address of the new guardian
*/
function setGuardian(address _guardian) external onlyGov {
emit NewGuardian(guardian, _guardian);
guardian = _guardian;
}
}
Loading
Loading