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

working calculator aggregator for the protocol #7

Merged
merged 2 commits into from
Dec 17, 2024
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
55 changes: 51 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,65 @@
This repository contains the full suite of smart contracts that define the Reservoir protocol. User's are able to
purchase the native stablecoin _rUSD_ and exchange it for a fixed term or variable rate yield bearing tokens _trUSD_ and
_srUSD_. The liabilities of the protocol are backed by a mix of real world assets (RWA)s and onchain yield bearing assets in lending protocols and AMMs.
# Reservoir Protocol

Set of smart contracts that act as a bank issuing liabilities in the form of tokens: *rUSD*, *srUSD*, and *trUSD*, which will be backed by assets and restricted in their supply by the configured solvency ratios.

## Introduction

This repository contains the full suite of smart contracts that define the Reservoir protocol. User's are able to purchase the native stablecoin *rUSD* and exchange it for fixed term or variable rate yield bearing tokens *trUSD* and *srUSD*. The liabilities of the protocol are backed by a mix of Real World Assets (RWA) and onchain yield bearing assets in lending protocols and AMMs.

The assets where capital is allocated is fully configurable through governance, and
solvency in the protocol is controlled by ratios set through governance that constrain leverage in the system.

## Getting Started
## Flow of Funds

The sequence of actions between users and the fund administrator (governance):

User deposits *USDC* or redeems *rUSD*
Fund administrator (governance) moves capital between the peg stability module and any of the asset adapters add to the credit enforcer
Fund administrator (governance) leaves some capital in the peg stability module for any potential upcoming redemptions
The price of the asset adapters change automatically and reflect a new asset value to the protocol

## Operations

Governance is able to transfer USDC from the PSM to the different modules that generate yield for the protocol. USDC is moved into a variety of DeFi ecosystems and used for investment in Real World Assets (RWAs)

### Deposit

Users deposit their USDC into the peg stability module and receive *rUSD*, from there they are able to use their *rUSD* in whatever way they choose, getting liquid and term yield with *srUSD* and *trUSD* or simply using it across the DeFi ecosystem.

### Redemptions

For redemptions, a user is able to receive back USDC for their *rUSD* up to the amount available in the PSM which is restricted to some percentage of the total *rUSD* outstanding.

## Setup

```bash
$ curl -L https://foundry.paradigm.xyz | bash
```

```bash
$ forge install

$ forge test
```

## Development

Foundry tests cover all the possible cases that can occur while interacting with functions, or in general flow. To run Foundry tests, use the following cmd:

```bash
$ forge test
```

## Deployment

### Local

```
anvil
```

## Ethereum

Scripts used for deployment can be found under `bin/`.

## Audits
114 changes: 114 additions & 0 deletions src/CalcAggregator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

import {ITermIssuer} from "src/TermIssuer.sol";
import {ICreditEnforcer} from "src/CreditEnforcer.sol";

contract CalcAggregator {
struct TermToken {
uint256 id;
uint256 maturityTimestamp;
uint256 discountRate;
}


ITermIssuer public immutable termIssuer;
ICreditEnforcer public immutable creditEnforcer;

constructor(ICreditEnforcer creditEnforcer_) {
creditEnforcer = creditEnforcer_;
termIssuer = creditEnforcer_.termIssuer();

// Check non zero address ...
}

/// @notice Get the earliest term available
/// @return id of the earliest term
function getCurrentId() external view returns (uint256) {
return termIssuer.earliestID();
}

/// @notice Get the latest term available
/// @return id of the latest term
function getLastId() external view returns (uint256) {
return termIssuer.latestID();
}

/// @notice Get currently available terms
/// @return termTokens list of terms
function getCurrentOffers()
external
view
returns (TermToken[] memory termTokens)
{
uint256 latestID = termIssuer.latestID();
uint256 earliestID = termIssuer.earliestID();

uint256 length = latestID - earliestID + 1;

termTokens = new TermToken[](length);
for (uint256 i = 0; i < length; i++) {
TermToken memory token = _getTerm(earliestID + i);
termTokens[i] = token;
}
}

/// @notice Get the term details
/// @param id term identifier
function getTerm(uint256 id) external view returns (TermToken memory) {
return _getTerm(id);
}

function _getTerm(
uint256 id
) private view returns (TermToken memory termToken) {
termToken.id = id;
termToken.discountRate = termIssuer.getDiscountRate(id);
termToken.maturityTimestamp = termIssuer.maturityTimestamp(id);
}

function getTermAmount(
uint256 id,
uint256 amount
) external view returns (uint256) {
return _getTermAmount(id, amount);
}

function _getTermAmount(
uint256 id,
uint256 amount
) private view returns (uint256) {
(uint256 cost, ) = _getQuote(id, 1e36);

return (amount * 1e36) / cost;
}

/// @notice Get the cost and profit for the term's specific amount
/// @param id term identifier
/// @param amount amount of term
function getQuote(
uint256 id,
uint256 amount
) external view returns (uint256, uint256) {
if (id < termIssuer.earliestID() || id > termIssuer.latestID()) {
return (type(uint256).max, 0);
}
return _getQuote(id, amount);
}

function _getQuote(
uint256 id,
uint256 amount
) private view returns (uint256 cost, uint256 profit) {
uint256 mTimestamp;
uint256 discountRate;

mTimestamp = termIssuer.maturityTimestamp(id);
discountRate = termIssuer.getDiscountRate(id);

cost += termIssuer.applyDiscount(amount, mTimestamp, discountRate);

profit = amount - cost;
}
}
Loading