Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jankjr committed Mar 20, 2023
0 parents commit 5dcb9ee
Show file tree
Hide file tree
Showing 161 changed files with 48,023 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
env: {
browser: true,
es2021: true
},
extends: 'standard-with-typescript',
overrides: [
],
parserOptions: {
ecmaVersion: 'latest',
project: ["tsconfig.json"],
sourceType: 'module'
},
rules: {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"no-useless-catch": "off"
// "@typescript-eslint/no-non-null-assertion": "off"
}
}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.DS_Store
build/
node_modules/
lib.commonjs/
lib.esm/
55 changes: 55 additions & 0 deletions LICENCE
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Blue Oak Model License

Version 1.0.0

## Purpose

This license gives everyone as much permission to work with
this software as possible, while protecting contributors
from liability.

## Acceptance

In order to receive this license, you must agree to its
rules. The rules of this license are both obligations
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.

## Copyright

Each contributor licenses you to do everything with this
software that would otherwise infringe that contributor's
copyright in it.

## Notices

You must ensure that everyone who gets a copy of
any part of this software from you, with or without
changes, also gets the text of this license or a link to
<https://blueoakcouncil.org/license/1.0.0>.

## Excuse

If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice. If you do not do so, your license
ends immediately.

## Patent

Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.

## Reliability

No contributor can revoke this license.

## No Liability

***As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim.***
79 changes: 79 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Reserve token Zapper

This is a TypeScript library that enables finding the best way to swap between any token and into an RToken for the Reserve protocol.

## Installation

You can install the package using npm:

```bash
npm install reserve-token-zapper
```

## Usage

To use the library, import it in your TypeScript file:

```typescript
import { Universe, Searcher, configuration } from 'reserve-token-zapper';
```

Then, create the searcher universe `Universe`, and instantiate a `Searcher` ,

```typescript
const universe = await Universe.createWithConfig(provider, configuration.eth);
const searcher = new Searcher(universe);
```

Use the searcher to find a swap:
```typescript
const searcherResult = await searcher.findSingleInputToRTokenZap({
input: universe.nativeToken.fromDecimal("0.1"),
rToken: universe.rTokens.eUSD!,
signerAddress: Address.fromHexString(YOUR ADDRESS)
});

console.log(searcherResult.describe().join("\n"))
// input: 0.1 ETH
// exchange 0.1 WETH for 178.19591 USDT via OneInch(path=[UNISWAP_V3])
// exchange 44.549868 USDT for 40.101809 saUSDT via MintSATokensAction
// exchange 44.555392 USDT for 2003.81805384 cUSDT via MintCTokenAction
// exchange 40.101809 saUSDT, 2003.81805384 cUSDT, 89.09065 USDT for 178.17969238 eUSD via MintRTokenAction
// expected output: 178.17969238 eUSD
```

The `SearcherResult` will show you the path the path the searcher will use and an on the individual swaps it will execute. The `SearcherResult` can be converted into a transaction via the `.toTransaction()` method on the `SearcherResult`. This will encode all the individual `Action's` into something the `ZapperExecutor` can run. It will also simulate the transaction and estimate gas.

```typescript
const transaction = await searcherResult.toTransaction()

console.log(transaction.toString())
// ZapTransaction(input:0.1 ETH,outputs:[178.17969238 eUSD],txFee:0.015921885964378245 ETH)

// To execute the transaction simply sign the transaction.tx, and send it via a provider
const pendingTx = await provider.sendTransaction(await wallet.signTransaction(transaction.tx))
```

## Current features and limitations

Library can currently only resolve one `RToken` at a time, so `RToken`'s requiring RTokens will probably cause the code to bail out.

Library does currently not support Zapper from an `RToken` into another `RToken`, but it is definitely on the agenda.

Library is fully set up to do searching itself, but due to time constraints the current version only supports dex aggregators (1inch), to result any trading.


## Contributing

Contributions to this project are always welcome! Here are a few ways you can help:

Report bugs or issues by opening a new issue on the GitHub repository.
Implement new features by opening a pull request on the GitHub repository.
Improve the documentation by suggesting edits or additions.

Before submitting a pull request, please make sure your changes pass the existing tests and add new tests if necessary.


## License

This project is licensed under the Blue Oak Model License - see the LICENSE file for details.
11 changes: 11 additions & 0 deletions contracts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
.env
coverage
coverage.json
typechain
typechain-types

# Hardhat files
cache
artifacts

13 changes: 13 additions & 0 deletions contracts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Sample Hardhat Project

This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract.

Try running some of the following tasks:

```shell
npx hardhat help
npx hardhat test
REPORT_GAS=true npx hardhat test
npx hardhat node
npx hardhat run scripts/deploy.ts
```
112 changes: 112 additions & 0 deletions contracts/contracts/IBasketHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: BlueOak-1.0.0
pragma solidity 0.8.17;

import '@openzeppelin/contracts/token/ERC20/IERC20.sol';

struct BasketRange {
uint192 bottom; // {BU}
uint192 top; // {BU}
}

/// CollateralStatus must obey a linear ordering. That is:
/// - being DISABLED is worse than being IFFY, or SOUND
/// - being IFFY is worse than being SOUND.
enum CollateralStatus {
SOUND,
IFFY, // When a peg is not holding or a chainlink feed is stale
DISABLED // When the collateral has completely defaulted
}

enum RoundingMode {
FLOOR, // Round towards zero
ROUND, // Round to the nearest int
CEIL // Round away from zero
}

/**
* @title IBasketHandler
* @notice The BasketHandler aims to maintain a reference basket of constant target unit amounts.
* When a collateral token defaults, a new reference basket of equal target units is set.
* When _all_ collateral tokens default for a target unit, only then is the basket allowed to fall
* in terms of target unit amounts. The basket is considered defaulted in this case.
*/
interface IBasketHandler {
/// Set the prime basket
/// @param erc20s The collateral tokens for the new prime basket
/// @param targetAmts The target amounts (in) {target/BU} for the new prime basket
/// required range: 1e9 values; absolute range irrelevant.
/// @custom:governance
function setPrimeBasket(
IERC20[] memory erc20s,
uint192[] memory targetAmts
) external;

/// Set the backup configuration for a given target
/// @param targetName The name of the target as a bytes32
/// @param max The maximum number of collateral tokens to use from this target
/// Required range: 1-255
/// @param erc20s A list of ordered backup collateral tokens
/// @custom:governance
function setBackupConfig(
bytes32 targetName,
uint256 max,
IERC20[] calldata erc20s
) external;

/// Default the basket in order to schedule a basket refresh
/// @custom:protected
function disableBasket() external;

/// Governance-controlled setter to cause a basket switch explicitly
/// @custom:governance
/// @custom:interaction
function refreshBasket() external;

/// @return If the BackingManager has sufficient collateral to redeem the entire RToken supply
function fullyCollateralized() external view returns (bool);

/// @return status The worst CollateralStatus of all collateral in the basket
function status() external view returns (CollateralStatus status);

/// @param erc20 The ERC20 token contract for the asset
/// @return {tok/BU} The whole token quantity of token in the reference basket
/// Returns 0 if erc20 is not registered or not in the basket
/// Returns FIX_MAX (in lieu of +infinity) if Collateral.refPerTok() is 0.
/// Otherwise, returns (token's basket.refAmts / token's Collateral.refPerTok())
function quantity(IERC20 erc20) external view returns (uint192);


/// @param amount {BU}
/// @return erc20s The addresses of the ERC20 tokens in the reference basket
/// @return quantities {qTok} The quantity of each ERC20 token to issue `amount` baskets
function quote(
uint192 amount,
RoundingMode rounding
)
external
view
returns (address[] memory erc20s, uint256[] memory quantities);

/// @return top {BU} The number of partial basket units: e.g max(coll.map((c) => c.balAsBUs())
/// bottom {BU} The number of whole basket units held by the account
function basketsHeldBy(
address account
) external view returns (BasketRange memory);

/// Should not revert
/// @return low {UoA/BU} The lower end of the price estimate
/// @return high {UoA/BU} The upper end of the price estimate
function price() external view returns (uint192 low, uint192 high);

/// Should not revert
/// lotLow should be nonzero if a BU could be worth selling
/// @return lotLow {UoA/tok} The lower end of the lot price estimate
/// @return lotHigh {UoA/tok} The upper end of the lot price estimate
function lotPrice() external view returns (uint192 lotLow, uint192 lotHigh);

/// @return timestamp The timestamp at which the basket was last set
function timestamp() external view returns (uint48);

/// @return The current basket nonce, regardless of status
function nonce() external view returns (uint48);
}
40 changes: 40 additions & 0 deletions contracts/contracts/ICToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: BlueOak-1.0.0
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/// Portion of external interface for CTokens
// See: https://github.com/compound-finance/compound-protocol/blob/master/contracts/CToken.sol
interface ICToken is IERC20 {
function mint(uint256 mintAmount) external payable returns (uint256);
function redeem(uint256 cTokenAmount) external payable returns (uint256);

/// @dev From Compound Docs:
/// The current (up to date) exchange rate, scaled by 10^(18 - 8 + Underlying Token Decimals).
function exchangeRateCurrent() external returns (uint256);

/// @dev From Compound Docs: The stored exchange rate, with 18 - 8 + UnderlyingAsset.Decimals.
function exchangeRateStored() external view returns (uint256);

/// @return The address of the underlying token
function underlying() external view returns (address);

/// @return The address of the comptroller
function comptroller() external view returns (address);
}
interface CEther is IERC20 {
function mint() external payable returns (uint256);
function redeem(uint256 cTokenAmount) external payable returns (uint256);
}

interface IComptroller {
/// Claim comp for an account, to an account
function claimComp(address account) external;

/// @return The address for COMP token
function getCompAddress() external view returns (address);

/// @return Returns if minting is active or paused for the underlying asset
function mintGuardianPaused(address token) external view returns (bool);

function getAllMarkets() external view returns (address[] memory markets);
}
9 changes: 9 additions & 0 deletions contracts/contracts/IChainLinkFeedRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: BlueOak-1.0.0
pragma solidity 0.8.17;

interface IChainLinkFeedRegistry {
function latestAnswer(
address base,
address quote
) external returns (uint256);
}
21 changes: 21 additions & 0 deletions contracts/contracts/IMain.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: BlueOak-1.0.0
pragma solidity 0.8.17;

interface IComponentRegistry {
// === Component setters/getters ===
function rToken() external view returns (address);
function stRSR() external view returns (address);
function assetRegistry() external view returns (address);
function basketHandler() external view returns (address);
function backingManager() external view returns (address);
function distributor() external view returns (address);
function rsrTrader() external view returns (address);
function rTokenTrader() external view returns (address);
function furnace() external view returns (address);
function broker() external view returns (address);
}

interface IMain is IComponentRegistry {
function poke() external; // not used in p1
function rsr() external view returns (address);
}
Loading

0 comments on commit 5dcb9ee

Please sign in to comment.