Skip to content

Commit

Permalink
Merge pull request #210 from overlay-market/arthurka/ov-to-ovl
Browse files Browse the repository at this point in the history
OV to OVL
  • Loading branch information
arthurka-o authored Jan 17, 2025
2 parents f721053 + 0710d42 commit 3ff1f21
Show file tree
Hide file tree
Showing 48 changed files with 511 additions and 510 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ V1 core relies on three modules:
- [Modules](#modules)
- [Markets Module](#markets-module)
- [Feeds Module](#feeds-module)
- [OV Module](#ov-module)
- [OVL Module](#ovl-module)
- [Deployment Process](#deployment-process)

### Markets Module
Expand All @@ -62,9 +62,9 @@ Traders interact directly with the market contract to take positions on a data s
- `liquidate()`
- `update()`

Traders transfer OV collateral to the market contract to back a position. This collateral is held in the market contract until the trader unwinds their position when exiting the trade. OV is the only collateral supported for V1.
Traders transfer OVL collateral to the market contract to back a position. This collateral is held in the market contract until the trader unwinds their position when exiting the trade. OVL is the only collateral supported for V1.

The market contract tracks the current open interest for all outstanding positions on a market as well as [information about each position](./contracts/libraries/Position.sol), that is needed in order to calculate the current value of the position in OV terms:
The market contract tracks the current open interest for all outstanding positions on a market as well as [information about each position](./contracts/libraries/Position.sol), that is needed in order to calculate the current value of the position in OVL terms:

```
library Position {
Expand Down Expand Up @@ -110,7 +110,7 @@ library Oracle {
uint256 priceOverMicroWindow; // p(now) averaged over micro
uint256 priceOverMacroWindow; // p(now) averaged over macro
uint256 priceOneMacroWindowAgo; // p(now - macro) avg over macro
uint256 reserveOverMicroWindow; // r(now) in ov averaged over micro
uint256 reserveOverMicroWindow; // r(now) in ovl averaged over micro
bool hasReserve; // whether oracle has manipulable reserve pool
}
}
Expand All @@ -121,11 +121,11 @@ from the [`Oracle.sol`](./contracts/libraries/Oracle.sol) library. `Oracle.Data`
For each oracle provider supported, there should be a specific implementation of a feed contract that inherits from `OverlayV1Feed.sol` (e.g. [`OverlayV1UniswapV3Feed.sol`](./contracts/feeds/uniswapv3/OverlayV1UniswapV3Feed.sol) for Uniswap V3 pools).


### OV Module
### OVL Module

The OV module consists of an ERC20 token with permissioned mint and burn functions. Upon initialization, markets must be given permission to mint and burn OV to compensate traders for their PnL on positions.
The OVL module consists of an ERC20 token with permissioned mint and burn functions. Upon initialization, markets must be given permission to mint and burn OVL to compensate traders for their PnL on positions.

[`OverlayV1Factory.sol`](./contracts/OverlayV1Factory.sol) grants these mint and burn permissions on a call to `deployMarket()`. Because of this, the factory contract must have admin privileges on the OV token prior to deploying markets.
[`OverlayV1Factory.sol`](./contracts/OverlayV1Factory.sol) grants these mint and burn permissions on a call to `deployMarket()`. Because of this, the factory contract must have admin privileges on the OVL token prior to deploying markets.

## Deployment Process

Expand All @@ -135,4 +135,4 @@ The process to add a new market is as follows:

2. Deploy an [`OverlayV1Market.sol`](./contracts/OverlayV1Market.sol) contract referencing the previously deployed feed from 1 as the `feed` constructor parameter. This is accomplished by governance calling `deployMarket()` on the market factory contract [`OverlayV1Factory.sol`](./contracts/OverlayV1Factory.sol). Traders interact directly with the newly deployed market contract to take positions out. The market contract stores the active positions and open interest for all outstanding trades on the data stream.

3. The market factory contract grants the newly deployed market contract mint and burn privileges on the sole instance of the [`OverlayV1Token.sol`](./contracts/OverlayV1Token.sol) token. Governance should grant the market factory contract admin privileges on the OV token prior to any markets being deployed, otherwise `deployMarket()` will revert.
3. The market factory contract grants the newly deployed market contract mint and burn privileges on the sole instance of the [`OverlayV1Token.sol`](./contracts/OverlayV1Token.sol) token. Governance should grant the market factory contract admin privileges on the OVL token prior to any markets being deployed, otherwise `deployMarket()` will revert.
12 changes: 6 additions & 6 deletions contracts/OverlayV1Deployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ import "./OverlayV1Market.sol";

contract OverlayV1Deployer is IOverlayV1Deployer {
address public immutable factory; // factory that has gov permissions
address public immutable ov; // ov token
address public immutable ovl; // ovl token

address public feed; // cached feed deploying market on

// factory modifier for governance sensitive functions
modifier onlyFactory() {
require(msg.sender == factory, "OVV1: !factory");
require(msg.sender == factory, "OVLV1: !factory");
_;
}

constructor(address _ov) {
constructor(address _ovl) {
factory = msg.sender;
ov = _ov;
ovl = _ovl;
}

function parameters() external view returns (address ov_, address feed_, address factory_) {
ov_ = ov;
function parameters() external view returns (address ovl_, address feed_, address factory_) {
ovl_ = ovl;
feed_ = feed;
factory_ = factory;
}
Expand Down
52 changes: 26 additions & 26 deletions contracts/OverlayV1Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ contract OverlayV1Factory is IOverlayV1Factory {
0.01e18, // MIN_LMBDA = 0.01
0, // MIN_DELTA = 0
1e18, // MIN_CAP_PAYOFF = 1x
0, // MIN_CAP_NOTIONAL = 0 OV
0, // MIN_CAP_NOTIONAL = 0 OVL
1e18, // MIN_CAP_LEVERAGE = 1x
86400, // MIN_CIRCUIT_BREAKER_WINDOW = 1 day
0, // MIN_CIRCUIT_BREAKER_MINT_TARGET = 0 OV
0, // MIN_CIRCUIT_BREAKER_MINT_TARGET = 0 OVL
0.01e18, // MIN_MAINTENANCE_MARGIN_FRACTION = 1%
0.01e18, // MIN_MAINTENANCE_MARGIN_BURN_RATE = 1%
0.001e18, // MIN_LIQUIDATION_FEE_RATE = 0.10% (10 bps)
1e14, // MIN_TRADING_FEE_RATE = 0.01% (1 bps)
0.000_1e18, // MIN_MINIMUM_COLLATERAL = 1e-4 OV
0.000_1e18, // MIN_MINIMUM_COLLATERAL = 1e-4 OVL
0.01e14, // MIN_PRICE_DRIFT_UPPER_LIMIT = 0.01 bps/s
100 // MIN_AVERAGE_BLOCK_TIME = 0.1s
];
Expand All @@ -39,15 +39,15 @@ contract OverlayV1Factory is IOverlayV1Factory {
10e18, // MAX_LMBDA = 10
200e14, // MAX_DELTA = 2% (200 bps)
100e18, // MAX_CAP_PAYOFF = 100x
88_888_888e18, // MAX_CAP_NOTIONAL = 88,888,888 OV (initial supply)
88_888_888e18, // MAX_CAP_NOTIONAL = 88,888,888 OVL (initial supply)
99e18, // MAX_CAP_LEVERAGE = 99x
31536000, // MAX_CIRCUIT_BREAKER_WINDOW = 365 days
88_888_888e18, // MAX_CIRCUIT_BREAKER_MINT_TARGET = 88,888,888 OV (initial supply)
88_888_888e18, // MAX_CIRCUIT_BREAKER_MINT_TARGET = 88,888,888 OVL (initial supply)
0.2e18, // MAX_MAINTENANCE_MARGIN_FRACTION = 20%
0.5e18, // MAX_MAINTENANCE_MARGIN_BURN_RATE = 50%
0.2e18, // MAX_LIQUIDATION_FEE_RATE = 20.00% (2000 bps)
100e14, // MAX_TRADING_FEE_RATE = 1% (100 bps)
100_000e18, // MAX_MINIMUM_COLLATERAL = 100,000 OV
100_000e18, // MAX_MINIMUM_COLLATERAL = 100,000 OVL
1e14, // MAX_PRICE_DRIFT_UPPER_LIMIT = 1 bps/s
3600000 // MAX_AVERAGE_BLOCK_TIME = 1h (arbitrary but large)
];
Expand All @@ -60,8 +60,8 @@ contract OverlayV1Factory is IOverlayV1Factory {
// event for emergency shutdown
event EmergencyShutdown(address indexed user, address indexed market);

// ov token
IOverlayV1Token public immutable ov;
// ovl token
IOverlayV1Token public immutable ovl;

// market deployer
IOverlayV1Deployer public immutable deployer;
Expand Down Expand Up @@ -94,42 +94,42 @@ contract OverlayV1Factory is IOverlayV1Factory {

// governor modifier for governance sensitive functions
modifier onlyGovernor() {
require(ov.hasRole(GOVERNOR_ROLE, msg.sender), "OVV1: !governor");
require(ovl.hasRole(GOVERNOR_ROLE, msg.sender), "OVLV1: !governor");
_;
}

// governor modifier for governance sensitive functions
modifier onlyGuardian() {
require(ov.hasRole(GUARDIAN_ROLE, msg.sender), "OVV1: !guardian");
require(ovl.hasRole(GUARDIAN_ROLE, msg.sender), "OVLV1: !guardian");
_;
}

// pauser modifier for pausable functions
modifier onlyPauser() {
require(ov.hasRole(PAUSER_ROLE, msg.sender), "OVV1: !pauser");
require(ovl.hasRole(PAUSER_ROLE, msg.sender), "OVLV1: !pauser");
_;
}

// risk manager modifier for risk parameters
modifier onlyRiskManager() {
require(ov.hasRole(RISK_MANAGER_ROLE, msg.sender), "OVV1: !riskManager");
require(ovl.hasRole(RISK_MANAGER_ROLE, msg.sender), "OVLV1: !riskManager");
_;
}

constructor(
address _ov,
address _ovl,
address _feeRecipient,
address _sequencerOracle,
uint256 _gracePeriod
) {
// set ov
ov = IOverlayV1Token(_ov);
// set ovl
ovl = IOverlayV1Token(_ovl);

// set the fee recipient
_setFeeRecipient(_feeRecipient);

// create a new deployer to use when deploying markets
deployer = new OverlayV1Deployer(_ov);
deployer = new OverlayV1Deployer(_ovl);

// set the sequencer oracle
sequencerOracle = AggregatorV3Interface(_sequencerOracle);
Expand All @@ -138,14 +138,14 @@ contract OverlayV1Factory is IOverlayV1Factory {

/// @dev adds a supported feed factory
function addFeedFactory(address feedFactory) external onlyGovernor {
require(!isFeedFactory[feedFactory], "OVV1: feed factory already supported");
require(!isFeedFactory[feedFactory], "OVLV1: feed factory already supported");
isFeedFactory[feedFactory] = true;
emit FeedFactoryAdded(msg.sender, feedFactory);
}

/// @dev removes a supported feed factory
function removeFeedFactory(address feedFactory) external onlyGovernor {
require(isFeedFactory[feedFactory], "OVV1: address not feed factory");
require(isFeedFactory[feedFactory], "OVLV1: address not feed factory");
isFeedFactory[feedFactory] = false;
emit FeedFactoryRemoved(msg.sender, feedFactory);
}
Expand All @@ -169,9 +169,9 @@ contract OverlayV1Factory is IOverlayV1Factory {
// initialize the new market
IOverlayV1Market(market_).initialize(params);

// grant market mint and burn priveleges on ov
ov.grantRole(MINTER_ROLE, market_);
ov.grantRole(BURNER_ROLE, market_);
// grant market mint and burn priveleges on ovl
ovl.grantRole(MINTER_ROLE, market_);
ovl.grantRole(BURNER_ROLE, market_);

// store market registry record for given feed
// and record address as a deployed market
Expand All @@ -182,9 +182,9 @@ contract OverlayV1Factory is IOverlayV1Factory {

/// @notice checks market doesn't exist on feed and feed is from a supported factory
function _checkFeed(address feedFactory, address feed) private view {
require(getMarket[feed] == address(0), "OVV1: market already exists");
require(isFeedFactory[feedFactory], "OVV1: feed factory not supported");
require(IOverlayV1FeedFactory(feedFactory).isFeed(feed), "OVV1: feed does not exist");
require(getMarket[feed] == address(0), "OVLV1: market already exists");
require(isFeedFactory[feedFactory], "OVLV1: feed factory not supported");
require(IOverlayV1FeedFactory(feedFactory).isFeed(feed), "OVLV1: feed does not exist");
}

/// @notice Checks all risk params are within acceptable bounds
Expand All @@ -199,7 +199,7 @@ contract OverlayV1Factory is IOverlayV1Factory {
function _checkRiskParam(Risk.Parameters name, uint256 value) private view {
uint256 minValue = PARAMS_MIN.get(name);
uint256 maxValue = PARAMS_MAX.get(name);
require(value >= minValue && value <= maxValue, "OVV1: param out of bounds");
require(value >= minValue && value <= maxValue, "OVLV1: param out of bounds");
}

/// @notice Setter for per-market risk parameters adjustable by governance
Expand All @@ -219,7 +219,7 @@ contract OverlayV1Factory is IOverlayV1Factory {
}

function _setFeeRecipient(address _feeRecipient) internal {
require(_feeRecipient != address(0), "OVV1: feeRecipient should not be zero address");
require(_feeRecipient != address(0), "OVLV1: feeRecipient should not be zero address");
feeRecipient = _feeRecipient;
emit FeeRecipientUpdated(msg.sender, _feeRecipient);
}
Expand Down
Loading

0 comments on commit 3ff1f21

Please sign in to comment.