Skip to content

Commit

Permalink
Feat/vault rewarder staking vaults (#86)
Browse files Browse the repository at this point in the history
* fix: adding post mint and redeem hooks

* test: changes to base tests

* config: changes to config

* feat: changes to global

* feat: changes to trading

* feat: changes to utils

* feat: changes to single sided lp

* feat: vault storage

* fix: misc fixes

* fix: staking vaults

* fix: solidity versions

* fix: test build

* fix: adding staking harness

* fix: adding initialization

* fix: initial test bugs

* fix: weETH valuation

* fix: deleverage collateral check

* fix: initial harness compiling

* fix: initial test running

* fix: acceptance tests passing

* test: migrated some tests

* fix: withdraw tests

* test: adding deleverage test

* fix: adding liquidation tests

* test: withdraw request

* test: finalize withdraws manual

* test: tests passing

* fix: single sided lp tests with vault rewarder

* fix: putting rewarder tests in

* fix: reward tests running

* fix: vault rewarder address

* fix: initial staking harness

* fix: adding staking harness

* fix: initial PT vault build

* fix: moving ethena vault code

* fix: moving etherfi code

* feat: adding pendle implementations

* fix: staking harness to use USDC

* fix: curve v2 adapter for trading

* test: basic tests passing

* fix: adding secondary trading on withdraw

* fix tests

* fix: trading on redemption

* fix: ethena vault config

* fix: switch ethena vault to sell sDAI

* fix warnings

* fix: more liquidation tests passing

* fix: ethan liquidation tests

* pendle harness build

* fix: initial tests passing

* fix: adding pendle oracle

* fix: test deal token error

* fix: changing pendle liquidation discount

* fix: all tests passing

* fix: etherfi borrow currency

* fix: adding more documentation

* change mainnet fork block

* properly update data seed files

* fix arbitrum tests

* fix test SingleSidedLP:Convex:crvUSD/[USDT]

* fix: can finalize withdraws

* fix: refactor withdraw valuation

* fix: pendle expiration tests

* fix: pendle pt valuation

* remove flag

* fix: remove redundant code path

* fix: initial commit

* fix: vault changes

* fix: vault changes

* fix: some tests passing

* fix: fixing more tests

* fix: updated remaining tests

* fix: split withdraw bug

* fix: new test

* fix: remaining tests

* fix: split withdraw reqest bug

* feat: add PendlePTKelp vault

* update oracle address, fix tests

* Address CR comments

* add test_canTriggerExtraStep

* fix tests

* fix: run tests

* feat: adding generic vault

* feat: update generate tests

* fix: changes from merge

* fix: adding has withdraw requests

* fix: update oracle address for network

* fix: merge kelp harness

* fix: base tests passing

* fix: move generation config

* fix: initial pendle test generation

* fix: mainnet tests passing

* fix: vault rewarder

* fix: more pendle tests

* fix: pendle dex test

* fix: adding camelot dex

* fix: update usde pt

* fix: adding camelot adapter

* fix: support configurable dex

* fix: adding more PT vaults

* fix: approval bug

* fix: update dex information

* fix: mainnet tests passing

* fix: update arbitrum pendle tests

* fix: update deployment addresses

* test: add balancer v2 batch trade

* fix: add given out batch trade

* fix: remove trade amount filling

* fix: add some comments

* fix: audit issue #60

* fix: switch to using getDecimals

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#73

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#72

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#70

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#66

* test: adding pendle oracle test

* fix:  sherlock-audit/2024-06-leveraged-vaults-judging#69

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#64

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#43

* fix: audit issue #18

* fix: move slippage check

* fix: add comment back

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#56

* test: adding test that catches math underflow

* fix: adding test for vault shares

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#44

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#6

* test: adds test to check split withdraw request value

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#78

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#80

* fix: updating valuations for tests

* fix: update run tests

* fix: remove stETH withdraws from Kelp in favor of ETH withdraws

* fix: update tests for pendle rs eth

* fix: resolve compile issues

* fix: rsETH oracle price

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#87

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#67

* fix: sherlock-audit/2024-06-leveraged-vaults-judging#6

* test: update tests for invalid splits

* fix: sherlock fix review comments

* merge: merged master into branch

* fix: empty reward tokens

* fix: claim rewards tests

* fix: liquidation tests

* fixing more tests

* fix: allowing unused reward pools

* test: migrating reward pools

* fix: rewarder test

* fix: claim rewards before withdrawing

* fix: deployed vault rewarder lib on arbitrum

* fix: deployed new tbtc vault

* docs: adding deployment documentation

* fix: update config

---------

Co-authored-by: sbuljac <[email protected]>
  • Loading branch information
jeffywu and sbuljac authored Sep 9, 2024
1 parent c6589e0 commit b1d3dd0
Show file tree
Hide file tree
Showing 120 changed files with 8,148 additions and 1,411 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ out_mainnet/
out_arbitrum/
node_modules/
hardhat.config.js
cache_hardhat/
tags
cspell.json
cache_hardhat/
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{
"cSpell.words": [
"AAVE",
"txns"
"cooldown",
"Ethena",
"Illiquidity",
"Pendle",
"txns",
"usde"
]
}
119 changes: 119 additions & 0 deletions DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Deploying a New Vault - Single Sided LP

## Prerequisites

- Ensure that any required oracle adapters have been deployed and listed in the `tests/config.py` file before proceeding.
- If new tokens are being used as rewards or inside the pool, add them to the list inside `tests/config.py` as well.

## Add Configuration to SingleSidedLP.yml

Add the required configuration parameters to the [SingleSidedLP.yml](tests/SingleSidedLP/SingleSidedLPTests.yml). This is an annotated example:

```
# This is an arbitrum vault so it needs to go in that section of the file.
# The vault name will follow the pattern: <strategy name>:<protocol>:[<borrowed token>]/<other tokens>/...
# This naming convention is important because it is parsed on the front end to
# determine how to display it properly.
- vaultName: SingleSidedLP:Convex:[WBTC]/tBTC
# The vault type will refer to the implementation that is deployed
vaultType: Curve2TokenConvex
# Select a fork block for testing after the pool, booster and any necessary
# oracles have been deployed and listed.
forkBlock: 215828254
# The list of valid symbols can be found in `tests/config.py`
primaryBorrowCurrency: WBTC
# Get these addresses from the relevant website.
rewardPool: "0x6B7B84F6EC1c019aF08C7A2F34D3C10cCB8A8eA6"
poolToken: "0x755D6688AD74661Add2FB29212ef9153D40fcA46"
lpToken: "0x755D6688AD74661Add2FB29212ef9153D40fcA46"
# This parameter is specific to different Curve pools
curveInterface: V1
# List the reward tokens expected for claim reward tests. See the list
# of valid symbols in `tests/config.py`
rewards: [CRV]
# List the required oracles for tests. See valid symbols in `tests/config.py`
oracles: [WBTC, tBTC]
# These are default settings for the initialization of the strategy vault settings
settings:
maxPoolShare: 4000
oraclePriceDeviationLimitPercent: 150
# These settings are used only in testing. Choose min and max deposits that are
# appropriate for the amount of liquidity on Notional at the fork block.
setUp:
minDeposit: 0.01e8
maxDeposit: 1e8
maxRelEntryValuation: 50
maxRelExitValuation: 50
# These are the vault configuration settings, when listing a new vault set a lower
# minAccountBorrowSize, maxPrimaryBorrow and minCollateralRatioBPS so that we can
# run an initial liquidation test.
config:
feeRate5BPS: 20
liquidationRate: 103
reserveFeeShare: 80
maxBorrowMarketIndex: 2
minCollateralRatioBPS: 800
maxRequiredAccountCollateralRatioBPS: 10_000
maxDeleverageCollateralRatioBPS: 2_300
minAccountBorrowSize: 0.05e8
maxPrimaryBorrow: 0.1e8
```

## Run Tests Before Deployment

Execute `bin/runTests.sh` which will run the entire test suite. A new file will be created with the name: `tests/generated/arbitrum/SingleSidedLP_Convex_tBTC_xWBTC.t.sol`. Note the naming convention here, the `x` precedes the borrowed token.

## Deploy the Vault

Execute the deployment script:

`scripts/deployVault.sh <arbitrum|mainnet> Convex tBTC_xWBTC WBTC --update`

Replace the parameters according to the name of the file generated above.

This script will deploy both the implementation and proxy addresses for the vault. The proxy will be initialized to point to the implementation. It will also create or update the files with the pattern:

`<vault address>.initVault.json`: upload to Gnosis safe to initialize the vault
`<vault address>.updateConfig.json`: upload to Gnosis safe to list the vault on Notional, the vault will not appear on the UI until it is explicitly whitelisted on the UI.
`vaults.json`: Will add the vault name and address
`emergency/**`: Will generate or update emergency exit calls for all the affected vaults.

## Backfill Vault APY Data

Add the new vault address to the vault-apy package and backfill the APY data. Create a new view for the vault address and add it to the `whitelisted_views` table in the database so it will start to synchronize to the website.

## Create Test Vault Position

After the Gnosis safe transactions have been executed, update the UI in order to create an initial vault position. This is done in two files:

[default-pools.ts](https://github.com/notional-finance/notional-monorepo/blob/v3/prod/packages/core-entities/src/exchanges/default-pools.ts): add an appropriate entry for the underlying liquidity pool for the vault. Make sure to properly register the LP token metadata and any other tokens that the pool holds that are not already listed on Notional.

[whitelisted-vaults.ts](https://github.com/notional-finance/notional-monorepo/blob/v3/prod/packages/core-entities/src/config/whitelisted-vaults.ts): add the vault address the list.

Next, redeploy the registry cache to get the new LP pool data synchronizing. This can be done with the command:

`yarn nx publish-wrangler-manual registry --env prod`

Now, you can run the website locally in order to create a test vault position

`yarn run serve web`

And navigate to localhost:3000 in your browser. Also be sure to check that the vault APY data shows up properly.

## Run Liquidation Test

Once a test position is created, you can increase the `minCollateralRatioBPS` in the `SingleSidedLP.yml` file at the top of this file. You can generate a new Gnosis safe JSON file using the command:

`scripts/updateConfig.sh <arbitrum|mainnet> Convex tBTC_xWBTC WBTC`

Once governance executes this update, the vault liquidator should pick up the under collateralized account and liquidate it.

## List the Vault on Prod

Create a PR using the changes made to the website code. Once merged, the vault will appear on the production site.


## Add Vault to Reward Reinvestment Bot

See PR: https://github.com/notional-finance/notional-monorepo/pull/968#pullrequestreview-2156755564

3 changes: 3 additions & 0 deletions contracts/global/Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,7 @@ library Constants {

uint256 internal constant CHAIN_ID_MAINNET = 1;
uint256 internal constant CHAIN_ID_ARBITRUM = 42161;

// All trading module exchange rates are normalized to 18 decimals
uint256 internal constant EXCHANGE_RATE_PRECISION = 1e18;
}
5 changes: 5 additions & 0 deletions contracts/global/TypeConvert.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ library TypeConvert {
require (x <= uint256(type(uint80).max));
return uint80(x);
}

function toUint128(uint256 x) internal pure returns (uint128) {
require (x <= uint256(type(uint128).max));
return uint128(x);
}
}
12 changes: 9 additions & 3 deletions contracts/global/arbitrum/Deployments.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {ICurveRouterV2} from "@interfaces/curve/ICurveRouterV2.sol";
import {ITradingModule} from "@interfaces/trading/ITradingModule.sol";
import {IWrappedfCashFactory} from "@interfaces/notional/IWrappedfCashFactory.sol";
import {AggregatorV2V3Interface} from "@interfaces/chainlink/AggregatorV2V3Interface.sol";
import {IPOracle, IPRouter} from "@interfaces/pendle/IPendle.sol";

library Deployments {
uint256 internal constant CHAIN_ID = Constants.CHAIN_ID_ARBITRUM;
Expand All @@ -26,14 +27,15 @@ library Deployments {
IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);

UniV3ISwapRouter internal constant UNIV3_ROUTER = UniV3ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
address internal constant CAMELOT_V3_ROUTER = 0x1F721E2E82F6676FCE4eA07A5958cF098D339e18;
address internal constant ZERO_EX = 0x0000000000001fF3684f28c67538d4D072C22734;
IUniV2Router2 internal constant UNIV2_ROUTER = IUniV2Router2(address(0));

address internal constant ALT_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

ICurveRouterV2 public constant CURVE_ROUTER_V2 = ICurveRouterV2(0x4c2Af2Df2a7E567B5155879720619EA06C5BB15D);
// Curve meta registry is not deployed on arbitrum
ICurveMetaRegistry public constant CURVE_META_REGISTRY = ICurveMetaRegistry(address(0));

address internal constant ALT_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

address internal constant CURVE_V1_HANDLER = address(0);
address internal constant CURVE_V2_HANDLER = address(0);
address internal constant CURVE_MINTER = 0xabC000d88f23Bb45525E447528DBF656A9D55bf5;
Expand All @@ -45,5 +47,9 @@ library Deployments {

// Chainlink L2 Sequencer Uptime: https://docs.chain.link/data-feeds/l2-sequencer-feeds/
AggregatorV2V3Interface internal constant SEQUENCER_UPTIME_ORACLE = AggregatorV2V3Interface(0xFdB631F5EE196F0ed6FAa767959853A9F217697D);
address internal constant VAULT_REWARDER_LIB = 0x54BB219281Fe0EeF1483bc4421e6502Fe1e30A97;

IPOracle internal constant PENDLE_ORACLE = IPOracle(0x9a9Fa8338dd5E5B2188006f1Cd2Ef26d921650C2);
IPRouter internal constant PENDLE_ROUTER = IPRouter(0x888888888889758F76e7103c6CbF23ABbF58F946);
address internal constant FLASH_LENDER_AAVE = 0x9D4D2C08b29A2Db1c614483cd8971734BFDCC9F2;
}
11 changes: 10 additions & 1 deletion contracts/global/mainnet/Deployments.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {ICurveRouterV2} from "@interfaces/curve/ICurveRouterV2.sol";
import {ITradingModule} from "@interfaces/trading/ITradingModule.sol";
import {IWrappedfCashFactory} from "@interfaces/notional/IWrappedfCashFactory.sol";
import {AggregatorV2V3Interface} from "@interfaces/chainlink/AggregatorV2V3Interface.sol";
import {IPRouter, IPOracle} from "@interfaces/pendle/IPendle.sol";

/// @title Hardcoded Deployment Addresses for Mainnet
library Deployments {
Expand All @@ -26,12 +27,13 @@ library Deployments {
IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);

UniV3ISwapRouter internal constant UNIV3_ROUTER = UniV3ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
address internal constant CAMELOT_V3_ROUTER = address(0);
address internal constant ZERO_EX = 0x0000000000001fF3684f28c67538d4D072C22734;
IUniV2Router2 internal constant UNIV2_ROUTER = IUniV2Router2(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);

address internal constant ALT_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

ICurveRouterV2 public constant CURVE_ROUTER_V2 = ICurveRouterV2(0x99a58482BD75cbab83b27EC03CA68fF489b5788f);
ICurveRouterV2 public constant CURVE_ROUTER_V2 = ICurveRouterV2(0xF0d4c12A5768D806021F80a262B4d39d26C58b8D);
ICurveMetaRegistry public constant CURVE_META_REGISTRY = ICurveMetaRegistry(0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC);
address internal constant CURVE_V1_HANDLER = 0x46a8a9CF4Fc8e99EC3A14558ACABC1D93A27de68;
address internal constant CURVE_V2_HANDLER = 0xC4F389020002396143B863F6325aA6ae481D19CE;
Expand All @@ -44,7 +46,14 @@ library Deployments {
address internal constant BALANCER_SPOT_PRICE = 0xA153B3E85833F8a323E60Dcdc08F6286eae28728;
IWrappedfCashFactory internal constant WRAPPED_FCASH_FACTORY = IWrappedfCashFactory(address(0));

// TODO: update this deployment
address internal constant VAULT_REWARDER_LIB = 0x0000dEb798bB3E4dFA0139dfa1b3D433CC23b72F;

// Chainlink L2 Sequencer Uptime: https://docs.chain.link/data-feeds/l2-sequencer-feeds/
AggregatorV2V3Interface internal constant SEQUENCER_UPTIME_ORACLE = AggregatorV2V3Interface(address(0));

// Pendle Oracle
IPOracle internal constant PENDLE_ORACLE = IPOracle(0x66a1096C6366b2529274dF4f5D8247827fe4CEA8);
IPRouter internal constant PENDLE_ROUTER = IPRouter(0x00000000005BBB0EF59571E58418F9a4357b68A0);
address internal constant FLASH_LENDER_AAVE = 0x0c86c636ed5593705b5675d370c831972C787841;
}
5 changes: 4 additions & 1 deletion contracts/liquidator/FlashLiquidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ contract FlashLiquidator is BoringOwnable {

uint256 currentBalance = IERC20(asset).balanceOf(address(this));
// force revert if there is no profit
require(currentBalance > amount);
require(currentBalance > (amount + fee), "Unprofitable Liquidation");

// Send profits back to the owner
if (withdraw) {
Expand Down Expand Up @@ -281,6 +281,9 @@ contract FlashLiquidator is BoringOwnable {
(int256 fCashDeposit, /* */) = NOTIONAL.getfCashRequiredToLiquidateCash(
params.currencyId, vaultAccount.maturity, cashBalance
);
// fCash deposit cannot exceed the account's debt
int256 maxFCashDeposit = -1 * vaultAccount.accountDebtUnderlying;
fCashDeposit = maxFCashDeposit < fCashDeposit ? maxFCashDeposit : fCashDeposit;

_lend(params.currencyId, vaultAccount.maturity, uint256(fCashDeposit), 0, asset);

Expand Down
Loading

0 comments on commit b1d3dd0

Please sign in to comment.