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 143 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
143 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
54795bb
chore: linting
0xJem Dec 30, 2024
fe8e09e
CDAuctioneer: add docs, address logic errors
0xJem Dec 30, 2024
49d0ffd
CDAuctioneer: minor improvements
0xJem Dec 30, 2024
8e2e4bb
CDAuctioneer: rename day -> dayState
0xJem Dec 30, 2024
859b09b
CDAuctioneer: use scale instead of decimals
0xJem Dec 30, 2024
156b140
CDAuctioneer: split updating the current tick out of the getter function
0xJem Dec 30, 2024
2018d4a
CDAuctioneer: reset the day state
0xJem Dec 30, 2024
ab4dcf5
CDAuctioneer: fixes for bidding logic
0xJem Dec 30, 2024
6015163
CDAuctioneer: pull roles into constants, differentiate roles, add rol…
0xJem Dec 31, 2024
0267ede
CDAuctioneer: use basic types in constructor. Make `getUpdatedTick()`…
0xJem Dec 31, 2024
cdb31dd
CDAuctioneer: test stubs
0xJem Dec 31, 2024
9af47bf
CDAuctioneer: tests
0xJem Dec 31, 2024
1be96c3
chore: linting
0xJem Dec 31, 2024
a3e69c9
CDAuctioneer: compiler fixes
0xJem Jan 2, 2025
089f2be
CDAuctioneer: add TODOs for more tests
0xJem Jan 2, 2025
a5190ef
CDAuctioneer: extract function for tick price calculation
0xJem Jan 2, 2025
753251c
CDAuctioneer: tests for setter sanity-checks
0xJem Jan 2, 2025
31162f8
CDAuctioneer: restore previous logic with tick price in getUpdatedTick()
0xJem Jan 2, 2025
7826525
CDAuctioneer: tests for activate/deactivate/setAuctionParameters, fix…
0xJem Jan 2, 2025
2e375b5
CDAuctioneer: WIP getUpdatedTick() tests
0xJem Jan 2, 2025
30f5692
CDAuctioneer: document auction approach and TODOs, based on recent co…
0xJem Jan 3, 2025
ccf52ae
CDAuctioneer: split tick step into a separate variable, change scale …
0xJem Jan 3, 2025
41c88ac
CDAuctioneer: shift time to expiry into standalone variable
0xJem Jan 3, 2025
f2c8c0c
CDAuctioneer: add initialize() function that ensures all state variab…
0xJem Jan 3, 2025
3400c29
CDAuctioneer: test cases for initialize()
0xJem Jan 3, 2025
3296f9e
CDAuctioneer: rename getCurrentTick() to getPreviousTick() and getUpd…
0xJem Jan 3, 2025
6cde285
CDAuctioneer: WIP getCurrentTick() tests and fixes
0xJem Jan 3, 2025
f9e201d
CDAuctioneer: WIP getCurrentTick() tests
0xJem Jan 6, 2025
3bc3259
CDAuctioneer: finish getCurrentTick() tests
0xJem Jan 6, 2025
5c8ec9d
CDAuctioneer: WIP bid() tests
0xJem Jan 6, 2025
f0abf96
CDAuctioneer: return positionId from bid(), add token balance and pos…
0xJem Jan 7, 2025
45c0161
CDAuctioneer: bid() tests
0xJem Jan 7, 2025
98407fe
CDAuctioneer: ensure that bid() refills the tick upon depletion
0xJem Jan 7, 2025
b1480ec
CDAuctioneer: modify previewBid()/bid() to not be greedy if a deposit…
0xJem Jan 7, 2025
00745b1
CDAuctioneer: rename State to AuctionParameters. Test corrections.
0xJem Jan 7, 2025
76d458c
CDAuctioneer: handle edge cases when setting auction parameters
0xJem Jan 7, 2025
7b718c5
chore: fix TODOs
0xJem Jan 7, 2025
fa4b099
CDFacility: contract is disabled upon deployment
0xJem Jan 7, 2025
d736725
CDAuctioneer: incorrect conditional when checking auction parameters.…
0xJem Jan 7, 2025
5cd845b
Fix tests
0xJem Jan 7, 2025
5860096
chore: linting
0xJem Jan 8, 2025
aaaa0f2
CDAuctioneer: TODOs for reducing tick size
0xJem Jan 8, 2025
79e11fd
CDAuctioneer: shift lastUpdate property into tick data structure
0xJem Jan 8, 2025
eb5033d
CDAuctioneer: test fix
0xJem Jan 8, 2025
41893ee
CDAuctioneer: more robust tests and checks for initialized status
0xJem Jan 8, 2025
e570238
chore: linting
0xJem Jan 8, 2025
4ade3a7
CDAuctioneer: add property for the current tick size. Update tests to…
0xJem Jan 8, 2025
4071fc8
CDAuctioneer: WIP halving of tick size after the day target has been …
0xJem Jan 8, 2025
135ffed
CDAuctioneer: finish implementation and tests for adjusting the tick …
0xJem Jan 9, 2025
2663fb0
CDAuctioneer: test stubs for tracking of historical auction results
0xJem Jan 13, 2025
489a672
Merge branch 'develop' into CDsEmissions
0xJem Jan 14, 2025
42420f3
Fix compiler errors
0xJem Jan 14, 2025
80aca68
CDAuctioneer: implement tracking of auction results over a defined pe…
0xJem Jan 14, 2025
7486c69
Propagate auction result changes into EmissionManager. Remove redunda…
0xJem Jan 15, 2025
4289c62
EmissionManager: add missing events, remove redundant error
0xJem Jan 15, 2025
b558772
EmissionManager: avoid global import, remove redundant interface
0xJem Jan 15, 2025
0f89e20
Warn on global import
0xJem Jan 15, 2025
c49ffea
EmissionManager: add VERSION() function
0xJem Jan 15, 2025
7ced7f9
EmissionManager: swap check order
0xJem Jan 15, 2025
854cacd
Test fix
0xJem Jan 15, 2025
ce72f28
EmissionsManager: update tests
0xJem Jan 15, 2025
f5f4955
EmissionManager: add additional test cases for surplus, zero auction …
0xJem Jan 15, 2025
558346d
Add version function to policies
0xJem Jan 15, 2025
0ba0357
CDPOS: fix extraneous characters in tokenURI
0xJem Jan 16, 2025
d9e137f
CDPOS: tests for ERC721 metadata
0xJem Jan 16, 2025
4bba808
chore: linting
0xJem Jan 16, 2025
e0f3f6a
CDPOS: don't wrap position ID and expiry numerical attributes in quotes
0xJem Jan 16, 2025
725a6d4
CDPOS: don't wrap conversion price and remaining deposit in quotes
0xJem Jan 16, 2025
8f2e16f
Case-sensitivity
0xJem Jan 16, 2025
81c8cb4
Audit README
0xJem Jan 16, 2025
611914a
Audit README
0xJem Jan 16, 2025
629ea74
Add sequence diagrams
0xJem Jan 17, 2025
c5edfb1
CDFacility: rename reclaim() -> redeem() to be consistent with CDEPO
0xJem Jan 17, 2025
6ef3679
CDFacility: test stubs for reclaim()
0xJem Jan 17, 2025
6a4c8c0
CDFacility: reclaim() tests
0xJem Jan 17, 2025
923f6c7
CDFacility: implement reclaim/previewReclaim
0xJem Jan 17, 2025
135bf42
CDFacility: more consistent handling of numbers when calculating rede…
0xJem Jan 17, 2025
f2691d8
CDEPO: rename variable
0xJem Jan 17, 2025
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
2 changes: 1 addition & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"func-visibility": ["warn", {"ignoreConstructors": true}],
"no-console": "off",
"no-empty-blocks": "off",
"no-global-import": "off",
"no-global-import": "warn",
"no-inline-assembly": "off",
"not-rely-on-time": "off",
"quotes": ["warn", "double"],
Expand Down
4 changes: 4 additions & 0 deletions ROLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ This document describes the roles that are used in the Olympus protocol.
| bridge_admin | CrossChainBridge | Allows configuring the CrossChainBridge |
| callback_admin | BondCallback | Administers the policy |
| callback_whitelist | BondCallback | Whitelists/blacklists tellers for callback |
| cd_admin | CDAuctioneer | Allows updating the parameters |
| contract_registry_admin | ContractRegistryAdmin | Allows registering/deregistering contracts |
| cooler_overseer | Clearinghouse | Allows activating the Clearinghouse |
| custodian | TreasuryCustodian | Deposit/withdraw reserves and grant/revoke approvals |
| distributor_admin | Distributor | Set reward rate, bounty, and other parameters |
| emergency_restart | Emergency | Reactivates the TRSRY and/or MINTR modules |
| emergency_restart | EmissionManager | Reactivates the EmissionManager |
| emergency_shutdown | CDAuctioneer | Activate/deactivate the CDAuctioneer |
| emergency_shutdown | CDFacility | Activate/deactivate the CDFacility |
| emergency_shutdown | Clearinghouse | Allows shutting down the protocol in an emergency |
| emergency_shutdown | Emergency | Deactivates the TRSRY and/or MINTR modules |
| emergency_shutdown | EmissionManager | Deactivates the EmissionManager |
| emissions_admin | EmissionManager | Set configuration parameters |
| heart | CDAuctioneer | Calls the setAuctionParameters() function |
| heart | EmissionManager | Calls the execute() function |
| heart | Operator | Call the operate() function |
| heart | ReserveMigrator | Allows migrating reserves from one reserve token to another |
Expand Down
222 changes: 222 additions & 0 deletions audit/2025-01_convertible-deposits/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# Olympus Convertible Deposits Audit

## Purpose

The purpose of this audit is to review the Convertible Deposits (CD) contracts.

These contracts will be installed in the Olympus V3 "Bophades" system, based on the [Default Framework](https://palm-cause-2bd.notion.site/Default-A-Design-Pattern-for-Better-Protocol-Development-7f8ace6d263c4303b108dc5f8c3055b1).

## Design

The CD contracts provide a mechanism for the protocol to operate an auction that is infinite duration and infinite capacity. Bidders are required to deposit the configured reserve token into the auctioneer (`CDAuctioneer`), and in return they receive a convertible deposit token (`CDEPO`) that can be converted into the configured bid token (OHM) or redeemed for the deposited reserve token.

### Auction Design

The auction is designed to be infinite duration and infinite capacity. The auction is made up of "ticks", where each tick is a price and capacity (number of OHM that can be purchased).

The auction has a number of parameters that affect its behaviour:

- Minimum Price: the minimum price of reserve token per OHM
- Tick Size: the size/capacity of each tick, in terms of OHM
- Tick Step: the percentage increase per tick
- Target: the target amount of OHM sold per day

The `EmissionManager` is responsible for periodically tuning these auction parameters according to the protocol's emission schedule.

There are a few additional behaviours:

- As tick capacity is depleted, the auctioneer will increase the price of the subsequent tick.
- With each multiple of the day target being reached, the auctioneer will progressively halve the size of each tick.
- The active tick price will decay over time, in the absence of any bids.

### Convertible Deposit Design

A successful bidder will receive a convertible deposit that can be converted into OHM or redeemed for the deposited reserve token. The deposit is composed of:

- A quantity of `CDEPO` tokens, which is a fungible ERC20 token across all deposits and terms.
- A `CDPOS` ERC721 token, which represents the non-fungible position of the bidder. This includes terms such as the expiry date, conversion price and size of the convertible deposit.

Using the `CDFacility` policy, convertible deposit holders are able to:

- Convert their deposit into OHM before expiry, at the conversion price of the deposit terms.
- Redeem the deposited reserve tokens after expiry.
- Reclaim the deposited reserve tokens before expiry, with a discount.

## Scope

### In-Scope Contracts

- [src/](../../src)
- [libraries/](../../src/libraries)
- [DecimalString.sol](../../src/libraries/DecimalString.sol)
- [Timestamp.sol](../../src/libraries/Timestamp.sol)
- [Uint2Str.sol](../../src/libraries/Uint2Str.sol)
- [modules/](../../src/modules)
- [CDEPO/](../../src/modules/CDEPO)
- [CDEPO.v1.sol](../../src/modules/CDEPO/CDEPO.v1.sol)
- [OlympusConvertibleDepository.sol](../../src/modules/CDEPO/OlympusConvertibleDepository.sol)
- [CDPOS/](../../src/modules/CDPOS)
- [CDPOS.v1.sol](../../src/modules/CDPOS/CDPOS.v1.sol)
- [OlympusConvertibleDepositPositions.sol](../../src/modules/CDPOS/OlympusConvertibleDepositPositions.sol)
- [policies/](../../src/policies)
- [interfaces/](../../src/policies/interfaces)
- [IConvertibleDepositAuctioneer.sol](../../src/policies/interfaces/IConvertibleDepositAuctioneer.sol)
- [IConvertibleDepositFacility.sol](../../src/policies/interfaces/IConvertibleDepositFacility.sol)
- [IEmissionManager.sol](../../src/policies/interfaces/IEmissionManager.sol)
- [CDAuctioneer.sol](../../src/policies/CDAuctioneer.sol)
- [CDFacility.sol](../../src/policies/CDFacility.sol)
- [EmissionManager.sol](../../src/policies/EmissionManager.sol)

The following pull requests can be referred to for the in-scope contracts:

- [Convertible Deposits](https://github.com/OlympusDAO/olympus-v3/pull/29)

See the [solidity-metrics.html](./solidity-metrics.html) report for a summary of the code metrics for these contracts.

### Previous Audits

You can review previous audits here:

- Spearbit (07/2022)
- [Report](https://storage.googleapis.com/olympusdao-landing-page-reports/audits/2022-08%20Code4rena.pdf)
- Code4rena Olympus V3 Audit (08/2022)
- [Repo](https://github.com/code-423n4/2022-08-olympus)
- [Findings](https://github.com/code-423n4/2022-08-olympus-findings)
- Kebabsec Olympus V3 Remediation and Follow-up Audits (10/2022 - 11/2022)
- [Remediation Audit Phase 1 Report](https://hackmd.io/tJdujc0gSICv06p_9GgeFQ)
- [Remediation Audit Phase 2 Report](https://hackmd.io/@12og4u7y8i/rk5PeIiEs)
- [Follow-on Audit Report](https://hackmd.io/@12og4u7y8i/Sk56otcBs)
- Cross-Chain Bridge by OtterSec (04/2023)🙏🏼
- [Report](https://storage.googleapis.com/olympusdao-landing-page-reports/audits/Olympus-CrossChain-Audit.pdf)
- PRICEv2 by HickupHH3 (06/2023)
- [Report](https://storage.googleapis.com/olympusdao-landing-page-reports/audits/2023_7_OlympusDAO-final.pdf)
- [Pre-Audit Commit](https://github.com/OlympusDAO/bophades/tree/17fe660525b2f0d706ca318b53111fbf103949ba)
- [Post-Remediations Commit](https://github.com/OlympusDAO/bophades/tree/9c10dc188210632b6ce46c7a836484e8e063151f)
- Cooler Loans by Sherlock (09/2023)
- [Report](https://docs.olympusdao.finance/assets/files/Cooler_Update_Audit_Report-f3f983a8ee8632637790bcc136275aa0.pdf)
- RBS 1.3 & 1.4 by HickupHH3 (11/2023)
- [Report](https://storage.googleapis.com/olympusdao-landing-page-reports/audits/OlympusDAO%20Nov%202023.pdf)
- [Pre-Audit Commit](https://github.com/OlympusDAO/bophades/tree/7a0902cf3ced19d41aafa83e96cf235fb3f15921)
- [Post-Remediations Commit](https://github.com/OlympusDAO/bophades/tree/e61d954cc620254effb014f2d2733e59d828b5b1)
- Emission Manager by yAudit (11/2024)
- [Report](https://storage.googleapis.com/olympusdao-landing-page-reports/audits/2024_11_EmissionManager_ReserveMigrator.pdf)
- [Pre-Audit Commit](https://github.com/OlympusDAO/bophades/tree/e367e7977ea58a2fd365296d9c9f620c7cd0512d)
- [Post-Remediations Commit](https://github.com/OlympusDAO/bophades/tree/3ace544f24adfd3d218ae625b9d1449321f9e184)
- LoanConsolidator by HickupHH3 (11/2024)
- [Report](https://storage.googleapis.com/olympusdao-landing-page-reports/audits/2024_10_LoanConsolidator_Audit.pdf)
- [Pre-Audit Commit](https://github.com/OlympusDAO/bophades/tree/95479d5d4a9bb941c60c7a8347709d9fc895b819)
- [Post-Remediations Commit](https://github.com/OlympusDAO/bophades/tree/d2d5b63dee16a259400628df4cf6ce2d3df02558)

## Architecture

### Overview

The diagrams below illustrate the architecture of the components.

#### Activation and Deactivation

Callers with the appropriate permissions can activate and deactivate the functionality of the CDAuctioneer and CDFacility contracts.

```mermaid
flowchart TD
cd_admin((cd_admin)) -- initialize --> CDAuctioneer
emergency_restart((emergency_restart)) -- restart --> EmissionManager
emergency_shutdown((emergency_shutdown)) -- activate/deactivate --> CDAuctioneer
emergency_shutdown((emergency_shutdown)) -- activate/deactivate --> CDFacility
emergency_shutdown((emergency_shutdown)) -- deactivate --> EmissionManager
emissions_admin((emissions_admin)) -- initialize --> EmissionManager

subgraph Policies
CDAuctioneer
CDFacility
EmissionManager
end
```

#### Auction Tuning

As part of the regular heartbeat, the EmissionManager contract will calculate the desired emission rate and set the auction parameters on CDAuctioneer accordingly.

```mermaid
sequenceDiagram
participant caller
participant Heart
participant EmissionManager
participant CDAuctioneer

caller->>Heart: beat
Heart->>EmissionManager: execute
EmissionManager->>CDAuctioneer: setAuctionParameters
```

#### Deposit Creation

A bidder can call `bid()` on the CDAuctioneer to create a deposit. This will result in the caller receiving the CDEPO tokens and a CDPOS position.

```mermaid
sequenceDiagram
participant caller
participant CDAuctioneer
participant CDFacility
participant CDPOS
participant CDEPO
participant MINTR
participant ReserveToken as Reserve (ERC20)
participant VaultToken as Vault (ERC4626)

caller->>CDAuctioneer: bid(depositAmount)
CDAuctioneer->>CDAuctioneer: determine conversion price
CDAuctioneer->>CDFacility: create(caller, depositAmount, conversionPrice, expiry, wrapNft)
CDFacility->>CDEPO: mintFor(caller, depositAmount)
CDEPO->>ReserveToken: transferFrom(caller, depositAmount)
caller-->>CDEPO: reserve tokens
CDEPO->>VaultToken: deposit(depositAmount, caller)
VaultToken-->>CDEPO: vault tokens
CDEPO-->>caller: CDEPO tokens
CDFacility->>CDPOS: create(caller, CDEPO, depositAmount, conversionPrice, expiry, wrapNft)
CDPOS-->>caller: CDPOS ERC721 token
CDFacility->>MINTR: increaseMintApproval(CDFacility, convertedAmount)
```

#### Deposit Conversion

Prior to the expiry of the convertible deposit, a deposit owner can convert their deposit into OHM at the conversion price of the deposit terms.

```mermaid
sequenceDiagram
participant caller
participant CDFacility
participant CDPOS
participant CDEPO
participant TRSRY
participant MINTR
participant ReserveToken
participant VaultToken
participant OHM

caller->>CDFacility: convert(positionIds, amounts)
loop For each position
CDFacility->>CDPOS: update(positionId, remainingAmount)
end
CDFacility->>CDEPO: redeemFor(caller, amount)
CDEPO->>ReserveToken: transfer(CDFacility, amount)
CDFacility->>VaultToken: deposit(amount, TRSRY)
VaultToken-->>TRSRY: vault tokens
CDFacility->>MINTR: mintOhm(caller, convertedAmount)
MINTR->>OHM: mint(caller, convertedAmount)
OHM-->>caller: OHM tokens
```

#### Deposit Reclaim

After

### CDEPO (Module)

### CDPOS (Module)

### CDFacility (Policy)

### CDAuctioneer (Policy)

### EmissionManager (Policy)
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ remappings_generate = false

[dependencies]
surl = { version = "1.0.0", git = "https://github.com/memester-xyz/surl.git", rev = "034c912ae9b5e707a5afd21f145b452ad8e800df" }
base64 = { version = "1.1.0", git = "https://github.com/Brechtpd/base64.git", rev = "4d85607b18d981acff392d2e99ba654305552a97" }
1 change: 1 addition & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ openzeppelin/=lib/forge-proposal-simulator/lib/openzeppelin-contracts/contracts/
solidity-code-metrics/=node_modules/solidity-code-metrics/
solidity-examples/=lib/solidity-examples/contracts/
surl-1.0.0/=dependencies/surl-1.0.0/src/
base64-1.1.0/=dependencies/base64-1.1.0/
6 changes: 6 additions & 0 deletions soldeer.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[[dependencies]]
name = "base64"
version = "1.1.0"
git = "https://github.com/Brechtpd/base64.git"
rev = "4d85607b18d981acff392d2e99ba654305552a97"

[[dependencies]]
name = "surl"
version = "1.0.0"
Expand Down
92 changes: 92 additions & 0 deletions src/libraries/DecimalString.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8;

import {uint2str} from "./Uint2Str.sol";
import {console2} from "forge-std/console2.sol";

library DecimalString {
/// @notice Converts a uint256 value to a string with a specified number of decimal places.
/// The value is adjusted by the scale factor and then formatted to the specified number of decimal places.
/// The decimal places are not zero-padded, so the result is not always the same length.
/// @dev This is inspired by code in [FixedStrikeOptionTeller](https://github.com/Bond-Protocol/option-contracts/blob/b8ce2ca2bae3bd06f0e7665c3aa8d827e4d8ca2c/src/fixed-strike/FixedStrikeOptionTeller.sol#L722).
///
/// @param value_ The uint256 value to convert to a string.
/// @param valueDecimals_ The scale factor of the value.
/// @param decimalPlaces_ The number of decimal places to format the value to.
/// @return result A string representation of the value with the specified number of decimal places.
function toDecimalString(
uint256 value_,
uint8 valueDecimals_,
uint8 decimalPlaces_
) internal pure returns (string memory) {
// Handle zero case
if (value_ == 0) return "0";

// Convert the entire number to string first
string memory str = uint2str(value_);
bytes memory bStr = bytes(str);

// If no decimal places requested, just handle the scaling and return
if (decimalPlaces_ == 0) {
if (bStr.length <= valueDecimals_) return "0";
return uint2str(value_ / (10 ** valueDecimals_));
}

// If value is a whole number, return as-is
if (valueDecimals_ == 0) return str;

// Calculate decimal places to show (limited by request and available decimals)
uint256 maxDecimalPlaces = valueDecimals_ > decimalPlaces_
? decimalPlaces_
: valueDecimals_;

// Handle numbers smaller than 1
if (bStr.length <= valueDecimals_) {
bytes memory smallResult = new bytes(2 + maxDecimalPlaces);
smallResult[0] = "0";
smallResult[1] = ".";

uint256 leadingZeros = valueDecimals_ - bStr.length;
uint256 zerosToAdd = leadingZeros > maxDecimalPlaces ? maxDecimalPlaces : leadingZeros;

// Add leading zeros after decimal
for (uint256 i = 0; i < zerosToAdd; i++) {
smallResult[i + 2] = "0";
}

// Add available digits
for (uint256 i = 0; i < maxDecimalPlaces - zerosToAdd && i < bStr.length; i++) {
smallResult[i + 2 + zerosToAdd] = bStr[i];
}

return string(smallResult);
}

// Find decimal position and last significant digit
uint256 decimalPosition = bStr.length - valueDecimals_;
uint256 lastNonZeroPos = decimalPosition;
for (uint256 i = 0; i < maxDecimalPlaces && i + decimalPosition < bStr.length; i++) {
if (bStr[decimalPosition + i] != "0") {
lastNonZeroPos = decimalPosition + i + 1;
}
}

// Create and populate result
bytes memory finalResult = new bytes(
lastNonZeroPos - decimalPosition > 0 ? lastNonZeroPos + 1 : lastNonZeroPos
);

for (uint256 i = 0; i < decimalPosition; i++) {
finalResult[i] = bStr[i];
}

if (lastNonZeroPos > decimalPosition) {
finalResult[decimalPosition] = ".";
for (uint256 i = 0; i < lastNonZeroPos - decimalPosition; i++) {
finalResult[decimalPosition + 1 + i] = bStr[decimalPosition + i];
}
}

return string(finalResult);
}
}
Loading
Loading