Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convertible Deposits #29

Draft
wants to merge 65 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
053cb32
Create CDsEmissions.sol
chefomi Nov 29, 2024
56b8f3b
Update CDsEmissions.sol
chefomi Nov 29, 2024
49ecd6d
Auctioneer + Facility
chefomi Dec 4, 2024
356af03
updates
chefomi Dec 6, 2024
4d55f12
integrate with emissions manager
chefomi Dec 7, 2024
61a7377
Fix compilation errors
0xJem Dec 9, 2024
9068ba0
chore: linting
0xJem Dec 9, 2024
e41276b
Add custom error to contracts. Add missing CDFacility parameter to CD…
0xJem Dec 9, 2024
74ebfa4
Extract CDAuctioneer into interface
0xJem Dec 9, 2024
fb68663
Fix compilation errors for EmissionManager test
0xJem Dec 9, 2024
2f2a0de
Add cdUSDS parameter to CDFacility. Extract cdUSDS into interface.
0xJem Dec 9, 2024
4797b13
Fix naming consistency with debt/deposit. Add missing parameter to de…
0xJem Dec 13, 2024
a6dacc8
Create interface for convertible deposit facility
0xJem Dec 13, 2024
6291399
Fix compile errors
0xJem Dec 13, 2024
55397f8
Fix licenses
0xJem Dec 13, 2024
7953b93
Interface for a proposed CDEPO module
0xJem Dec 13, 2024
43ca59c
Update description
0xJem Dec 13, 2024
c3a7ee8
Add module for convertible deposit terms
0xJem Dec 16, 2024
349c671
Add CTERM events
0xJem Dec 16, 2024
6b20f80
WIP implementation of CDEPO
0xJem Dec 16, 2024
5536d54
First pass a CDEPO
0xJem Dec 16, 2024
9fb539c
First pass at implementation of CTERM
0xJem Dec 16, 2024
e3dcecc
Add a permissioned function to CDEPO to redeem CD tokens for assets. …
0xJem Dec 16, 2024
42a6d68
Rename CTERM to CDPOS
0xJem Dec 16, 2024
be52b09
Shift CDAuctioneer to use new CDFacility interface
0xJem Dec 16, 2024
2c28d33
Check CD token before converting/reclaiming using a CD position
0xJem Dec 17, 2024
f1dbb75
First pass at SVG for CD positions
0xJem Dec 17, 2024
6b9888f
Extract previewBid functionality
0xJem Dec 17, 2024
fddaa3b
Docs
0xJem Dec 17, 2024
e3ad735
Add isExpired getter to CDPOS
0xJem Dec 18, 2024
77e2787
Adjust CDPOS SVG
0xJem Dec 18, 2024
abf0b3c
Wrote helper function to convert a fixed-point integer into a decimal…
0xJem Dec 18, 2024
7ba544a
Add conversion price and remaining deposit to the SVG and traits
0xJem Dec 18, 2024
724b2b5
Add setter
0xJem Dec 18, 2024
51648f0
Docs
0xJem Dec 18, 2024
1719af0
Add previewConvert to CDPOS
0xJem Dec 18, 2024
4be3322
Add stubs for CDPOS tests
0xJem Dec 18, 2024
497ed1c
Add owner back to position struct
0xJem Dec 18, 2024
f293e5e
Implement tests for CDPOS.create()
0xJem Dec 18, 2024
6571d51
CDPOS tests for create/update/split
0xJem Dec 19, 2024
6c4fcac
CDPOS tests for wrap/unwrap
0xJem Dec 19, 2024
95ad4be
Clarify decimal scale in docs, tests for previewConvert
0xJem Dec 19, 2024
0520eba
Tests for setDisplayDecimals and transferFrom
0xJem Dec 19, 2024
d8d89bf
Handling of transferFrom in CDPOS
0xJem Dec 19, 2024
27a3695
Fix handling of mint checks
0xJem Dec 19, 2024
875cdd9
Remove redundant tests
0xJem Dec 19, 2024
dbd3f6e
CDEPO: rename burn() to reclaim() and adjust logic around spending to…
0xJem Dec 19, 2024
fcd4e3d
CDEPO: test stubs
0xJem Dec 19, 2024
908a641
CDEPO: tests for mint/mintTo/previewMint, rename burn rate to reclaim…
0xJem Dec 19, 2024
fb9bf7e
CDEPO: setReclaimRate tests
0xJem Dec 19, 2024
56cabb2
CDEPO: mint test fixes
0xJem Dec 19, 2024
85e73e9
CDEPO: more tests
0xJem Dec 19, 2024
e73bf8e
CDEPO: more tests, use safeTransfer/safeApprove, clarify allowance
0xJem Dec 20, 2024
d9b3679
CDEPO: tests and impl fixes for rounding, redeem tests
0xJem Dec 20, 2024
4bbde8a
CDEPO: sweepYield tests
0xJem Dec 20, 2024
e98f502
CDFacility: test stubs
0xJem Dec 20, 2024
c4f56c2
CDEPO: add mint/reclaim/redeem -For functions, add spending allowance…
0xJem Dec 20, 2024
2aca51a
CDFacility: test updates
0xJem Dec 20, 2024
0cf6892
Add preview functions to CD facility
0xJem Dec 23, 2024
21580db
CD Facility: role must be lowercase. Add previewConvert and previewRe…
0xJem Dec 23, 2024
3fb895c
CDFacility: convert tests
0xJem Dec 23, 2024
1820d39
CDFacility: more comprehensive tests
0xJem Dec 23, 2024
34307b4
CDFacility: better handling of ownership check
0xJem Dec 23, 2024
e9146a3
CDFacility: WIP previewReclaim tests
0xJem Dec 23, 2024
20571b2
CDFacility: tests for convert, reclaim
0xJem Dec 26, 2024
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
181 changes: 181 additions & 0 deletions src/policies/CDAuctioneer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.15;

import "src/Kernel.sol";

import {ReentrancyGuard} from "solmate/utils/ReentrancyGuard.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";

import {RolesConsumer, ROLESv1} from "modules/ROLES/OlympusRoles.sol";

import {FullMath} from "libraries/FullMath.sol";

import {CDFacility} from "./CDFacility.sol";

interface CDRC20 {
function mint(address to, uint256 amount) external;
function burn(address from, uint256 amount) external;
function convertFor(uint256 amount) external view returns (uint256);
function expiry() external view returns (uint256);
}

contract CDAuctioneer is Policy, RolesConsumer {
using FullMath for uint256;

// ========== DATA STRUCTURES ========== //

struct State {
uint256 target; // number of ohm per day
uint256 tickSize; // number of ohm in a tick
uint256 minPrice; // minimum tick price
uint256 tickStep; // percentage increase (decrease) per tick
uint256 timeToExpiry; // time between creation and expiry of deposit
uint256 lastUpdate; // timestamp of last update to current tick
}

struct Day {
uint256 deposits; // total deposited for day
uint256 convertable; // total convertable for day
}

struct Tick {
uint256 price;
uint256 capacity;
}

// ========== EVENTS ========== //

// ========== STATE VARIABLES ========== //

Tick public currentTick;
State public state;

uint256 public decimals;

CDFacility public cdFacility;

mapping(uint256 => mapping(uint256 => address)) public cdTokens; // mapping(expiry => price => token)

Day public today;

// ========== SETUP ========== //

constructor(Kernel kernel_) Policy(kernel_) {}

function configureDependencies() external override returns (Keycode[] memory dependencies) {
dependencies = new Keycode[](1);
dependencies[2] = toKeycode("ROLES");

ROLES = ROLESv1(getModuleAddress(dependencies[0]));
}

function requestPermissions()
external
view
override
returns (Permissions[] memory permissions)
{}

// ========== AUCTION ========== //

/// @notice use a deposit to bid for CDs
/// @param deposit amount of reserve tokens
/// @return convertable amount of convertable tokens
function bid(uint256 deposit) external returns (uint256 convertable) {
// update state
currentTick = getCurrentTick();
state.lastUpdate = block.timestamp;

// iterate until user has no more reserves to bid
while (deposit > 0) {
// handle spent/capacity for tick
uint256 amount = currentTick.capacity < convertFor(deposit, currentTick.price)
? state.tickSize
: deposit;
if (amount != state.tickSize) currentTick.capacity -= amount;
else currentTick.price *= state.tickStep / decimals;

// decrement bid and increment tick price
deposit -= amount;
convertable += convertFor(amount, currentTick.price);
}

today.deposits += deposit;
today.convertable += convertable;

// mint amount of CD token
cdFacility.addNewCD(msg.sender, deposit, convertable, block.timestamp + state.timeToExpiry);
}

// ========== VIEW FUNCTIONS ========== //

/// @notice get current tick info
/// @dev time passing changes tick info
/// @return tick info in Tick struct
function getCurrentTick() public view returns (Tick memory tick) {
// find amount of time passed and new capacity to add
uint256 timePassed = block.timestamp - state.lastUpdate;
uint256 newCapacity = (state.target * timePassed) / 1 days;

tick = currentTick;

// decrement price while ticks are full
while (tick.capacity + newCapacity > state.tickSize) {
newCapacity -= state.tickSize;
tick.price *= decimals / state.tickStep;

// tick price does not go below the minimum
// tick capacity is full if the min price is exceeded
if (tick.price < state.minPrice) {
tick.price = state.minPrice;
newCapacity = state.tickSize;
break;
}
}

// decrement capacity by remainder
tick.capacity = newCapacity;
}

/// @notice get amount of cdOHM for a deposit at a tick price
/// @return amount convertable
function convertFor(uint256 deposit, uint256 price) public view returns (uint256) {
return (deposit * decimals) / price;
}

// ========== ADMIN FUNCTIONS ========== //

/// @notice update auction parameters
/// @dev only callable by the auction admin
/// @param newTarget new target sale per day
/// @param newSize new size per tick
/// @param newMinPrice new minimum tick price
function beat(
uint256 newTarget,
uint256 newSize,
uint256 newMinPrice
) external onlyRole("CD_Auction_Admin") returns (uint256 remainder) {
remainder = (state.target > today.convertable) ? state.target - today.convertable : 0;

state = State(
newTarget,
newSize,
newMinPrice,
state.tickStep,
state.timeToExpiry,
state.lastUpdate
);
}

/// @notice update time between creation and expiry of deposit
/// @param newTime number of seconds
function setTimeToExpiry(uint256 newTime) external onlyRole("CD_Admin") {
state.timeToExpiry = newTime;
}

/// @notice update change between ticks
/// @param newStep percentage in decimal terms
function setTickStep(uint256 newStep) external onlyRole("CD_Admin") {
state.tickStep = newStep;
}
}
Loading
Loading