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

Feat/curve migration #921

Merged
merged 6 commits into from
Mar 30, 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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ fixtures/contracts-addresses/*
# - mainnet logs
# - sepolia testnet logs
packages/contracts/broadcast/*/*/*
!packages/contracts/broadcast/**/run-latest.json
!packages/contracts/broadcast/**/1/*
!packages/contracts/broadcast/**/11155111/*

Expand Down
19 changes: 5 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,9 @@ COLLATERAL_TOKEN_ADDRESS="0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"
# - testnet/anvil: deploys LUSD/USD chainlink price feed from scratch
COLLATERAL_TOKEN_CHAINLINK_PRICE_FEED_ADDRESS="0x3D7aE7E594f2f2091Ad8798313450130d0Aba3a0"

# Curve metapool address (Dollar-3CRVLP).
# By default set to the old Dollar-3CRV metapool which is about to be redeployed when
# new Dollar token is deployed.
# - mainnet: uses old Dollar-3CRVLP address
# - testnet/anvil: deploys metapool from scratch
CURVE_DOLLAR_METAPOOL_ADDRESS="0x20955CB69Ae1515962177D164dfC9522feef567E"
# Dollar amount in wei minted initially to provide liquidity to the Dollar-3CRV metapool
# By default set to 25k Dollar tokens
INITIAL_DOLLAR_MINT_AMOUNT_WEI="25000000000000000000000"

# Owner private key (grants access to updating Diamond facets and setting TWAP oracle address).
# By default set to the private key from the 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 address
Expand All @@ -110,15 +107,9 @@ OWNER_PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f

# RPC URL (used in contract migrations)
# - anvil: http://127.0.0.1:8545
# - testnet: https://ethereum-sepolia.publicnode.com
# - mainnet: https://eth.ubq.fi/v1/mainnet
# - testnet: https://sepolia.gateway.tenderly.co
# - mainnet: https://mainnet.gateway.tenderly.co
RPC_URL="http://127.0.0.1:8545"

# 3CRV LP token address (which you get if you deposit to Curve's TriPool (DAI/USDC/USDT)).
# By default set to 3CRV LP token address from mainnet.
# - mainet: uses values set in TOKEN_3CRV_ADDRESS
# - testnet/anvil: deploys 3CRV LP token from scratch
TOKEN_3CRV_ADDRESS="0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"
```

We provide an `.env.example` file pre-set with recommend testing environment variables but you are free to modify or experiment with different values on your local branch.
Expand Down
23 changes: 7 additions & 16 deletions packages/contracts/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Admin private key (grants access to restricted contracts methods).
# By default set to the private key from the 0x70997970c51812dc3a010c7d01b50e0d17dc79c8 address
# By default set to the private key from the 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 address
# which is the 2nd address derived from test mnemonic "test test test test test test test test test test test junk".
ADMIN_PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"

Expand All @@ -15,26 +15,17 @@ COLLATERAL_TOKEN_ADDRESS="0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"
# - testnet/anvil: deploys LUSD/USD chainlink price feed from scratch
COLLATERAL_TOKEN_CHAINLINK_PRICE_FEED_ADDRESS="0x3D7aE7E594f2f2091Ad8798313450130d0Aba3a0"

# Curve metapool address (Dollar-3CRVLP).
# By default set to the old Dollar-3CRV metapool which is about to be redeployed when
# new Dollar token is deployed.
# - mainnet: uses old Dollar-3CRVLP address
# - testnet/anvil: deploys metapool from scratch
CURVE_DOLLAR_METAPOOL_ADDRESS="0x20955CB69Ae1515962177D164dfC9522feef567E"
# Dollar amount in wei minted initially to provide liquidity to the Dollar-3CRV metapool
# By default set to 25k Dollar tokens
INITIAL_DOLLAR_MINT_AMOUNT_WEI="25000000000000000000000"

# Owner private key (grants access to updating Diamond facets and setting TWAP oracle address).
# By default set to the private key from the 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 address
# By default set to the private key from the 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 address
# which is the 1st address derived from test mnemonic "test test test test test test test test test test test junk".
OWNER_PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"

# RPC URL (used in contract migrations)
# - anvil: http://127.0.0.1:8545
# - testnet: https://ethereum-sepolia.publicnode.com
# - mainnet: https://eth.ubq.fi/v1/mainnet
# - testnet: https://sepolia.gateway.tenderly.co
# - mainnet: https://mainnet.gateway.tenderly.co
RPC_URL="http://127.0.0.1:8545"

# 3CRV LP token address (which you get if you deposit to Curve's TriPool (DAI/USDC/USDT)).
# By default set to 3CRV LP token address from mainnet.
# - mainet: uses value set in TOKEN_3CRV_ADDRESS
# - testnet/anvil: deploys 3CRV LP token from scratch
TOKEN_3CRV_ADDRESS="0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"
2,497 changes: 0 additions & 2,497 deletions packages/contracts/broadcast/05_StakingShare.s.sol/31337/run-latest.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
// env variables
uint256 adminPrivateKey;
uint256 ownerPrivateKey;
uint256 initialDollarMintAmountWei;

// threshold in seconds when price feed response should be considered stale
uint256 CHAINLINK_PRICE_FEED_THRESHOLD;
Expand Down Expand Up @@ -137,10 +138,19 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
// read env variables
adminPrivateKey = vm.envUint("ADMIN_PRIVATE_KEY");
ownerPrivateKey = vm.envUint("OWNER_PRIVATE_KEY");
initialDollarMintAmountWei = vm.envUint(
"INITIAL_DOLLAR_MINT_AMOUNT_WEI"
);

address adminAddress = vm.addr(adminPrivateKey);
address ownerAddress = vm.addr(ownerPrivateKey);

//==================
// Before scripts
//==================

beforeRun();

//===================
// Deploy Diamond
//===================
Expand Down Expand Up @@ -266,18 +276,6 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
// stop sending admin transactions
vm.stopBroadcast();

//==========================
// Collateral token setup
//==========================

// start sending owner transactions
vm.startBroadcast(ownerPrivateKey);

initCollateral();

// stop sending owner transactions
vm.stopBroadcast();

//=========================
// UbiquiPoolFacet setup
//=========================
Expand Down Expand Up @@ -313,12 +311,6 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
// stop sending admin transactions
vm.stopBroadcast();

//================================================================================
// Oracles (Curve Dollar-3CRVLP metapool + LUSD/USD chainlink price feed) setup
//================================================================================

initOracles();

//==================
// Dollar deploy
//==================
Expand Down Expand Up @@ -353,33 +345,50 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
ManagerFacet managerFacet = ManagerFacet(address(diamond));
managerFacet.setDollarTokenAddress(address(dollarToken));

// mint initial Dollar amount to owner for Curve's Dollar-3CRV metapool
dollarToken.mint(ownerAddress, initialDollarMintAmountWei);

// stop sending admin transactions
vm.stopBroadcast();

//=================
// After scripts
//=================

afterRun();
}

/**
* @notice Initializes collateral token
* @notice Runs before the main `run()` method
*
* @dev Initializes collateral token
* @dev Collateral token is different for mainnet and development:
* - mainnet: uses LUSD address from `COLLATERAL_TOKEN_ADDRESS` env variables
* - development: deploys mocked ERC20 token from scratch
*/
function initCollateral() public virtual {
function beforeRun() public virtual {
//=================================
// Collateral ERC20 token deploy
//=================================

// start sending owner transactions
vm.startBroadcast(ownerPrivateKey);

// deploy ERC20 mock token for ease of debugging
collateralToken = new MockERC20(
"Collateral test token",
"CLT_TEST",
18
);

// stop sending owner transactions
vm.stopBroadcast();
}

/**
* @notice Initializes oracle related contracts
* @notice Runs after the main `run()` method
*
* @dev Initializes oracle related contracts
* @dev Ubiquity protocol supports 2 oracles:
* 1. Curve's Dollar-3CRVLP metapool to fetch Dollar prices
* 2. Chainlink's price feed (used in UbiquityPool) to fetch collateral token prices in USD
Expand All @@ -393,7 +402,7 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
* - 3CRVLP ERC20 token
* - Curve's Dollar-3CRVLP metapool contract
*/
function initOracles() public virtual {
function afterRun() public virtual {
//========================================
// Chainlink LUSD/USD price feed deploy
//========================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {Deploy001_Diamond_Dollar as Deploy001_Diamond_Dollar_Development} from "../development/Deploy001_Diamond_Dollar.s.sol";
import {ManagerFacet} from "../../src/dollar/facets/ManagerFacet.sol";
import {UbiquityPoolFacet} from "../../src/dollar/facets/UbiquityPoolFacet.sol";
import {ICurveStableSwapFactoryNG} from "../../src/dollar/interfaces/ICurveStableSwapFactoryNG.sol";
import {ICurveStableSwapMetaNG} from "../../src/dollar/interfaces/ICurveStableSwapMetaNG.sol";

/// @notice Migration contract
Expand All @@ -17,13 +18,14 @@ contract Deploy001_Diamond_Dollar is Deploy001_Diamond_Dollar_Development {
}

/**
* @notice Initializes collateral token
* @notice Runs before the main `run()` method
*
* @dev Initializes collateral token
* @dev Collateral token is different for mainnet and development:
* - mainnet: uses LUSD address from `COLLATERAL_TOKEN_ADDRESS` env variables
* - development: deploys mocked ERC20 token from scratch
*/
function initCollateral() public override {
function beforeRun() public override {
// read env variables
address collateralTokenAddress = vm.envAddress(
"COLLATERAL_TOKEN_ADDRESS"
Expand All @@ -38,9 +40,11 @@ contract Deploy001_Diamond_Dollar is Deploy001_Diamond_Dollar_Development {
}

/**
* @notice Initializes oracle related contracts
* @notice Runs after the main `run()` method
*
* @dev We override `initOracles()` from `Deploy001_Diamond_Dollar_Development` because
* @dev Initializes oracle related contracts
*
* @dev We override `afterRun()` from `Deploy001_Diamond_Dollar_Development` because
* we need to use already deployed contracts while `Deploy001_Diamond_Dollar_Development`
* deploys all oracle related contracts from scratch for ease of debugging.
*
Expand All @@ -55,17 +59,12 @@ contract Deploy001_Diamond_Dollar is Deploy001_Diamond_Dollar_Development {
* Mainnet (i.e. production) migration uses already deployed contracts for:
* - Chainlink price feed contract
* - 3CRVLP ERC20 token
* - Curve's Dollar-3CRVLP metapool contract
*/
function initOracles() public override {
function afterRun() public override {
// read env variables
address chainlinkPriceFeedAddress = vm.envAddress(
"COLLATERAL_TOKEN_CHAINLINK_PRICE_FEED_ADDRESS"
);
address token3CrvAddress = vm.envAddress("TOKEN_3CRV_ADDRESS");
address curveDollarMetapoolAddress = vm.envAddress(
"CURVE_DOLLAR_METAPOOL_ADDRESS"
);

//=======================================
// Chainlink LUSD/USD price feed setup
Expand Down Expand Up @@ -99,24 +98,44 @@ contract Deploy001_Diamond_Dollar is Deploy001_Diamond_Dollar_Development {
// stop sending admin transactions
vm.stopBroadcast();

//=========================================
// Curve's Dollar-3CRVLP metapool deploy
//=========================================

// start sending owner transactions
vm.startBroadcast(ownerPrivateKey);

// deploy Curve Dollar-3CRV metapool
address curveDollarMetaPoolAddress = ICurveStableSwapFactoryNG(
0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf
).deploy_metapool(
0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7, // Curve 3pool (DAI-USDT-USDC) address
"Dollar/3CRV", // pool name
"Dollar3CRV", // LP token symbol
address(dollarToken), // main token
100, // amplification coefficient
40000000, // trade fee, 0.04%
20000000000, // off-peg fee multiplier
2597, // moving average time value, 2597 = 1800 seconds
0, // metapool implementation index
0, // asset type
"", // method id for oracle asset type (not applicable for Dollar)
address(0) // token oracle address (not applicable for Dollar)
);

// stop sending owner transactions
vm.stopBroadcast();

//========================================
// Curve's Dollar-3CRVLP metapool setup
//========================================

// start sending admin transactions
vm.startBroadcast(adminPrivateKey);

// init 3CRV token
curveTriPoolLpToken = IERC20(token3CrvAddress);

// init Dollar-3CRVLP Curve metapool
curveDollarMetaPool = ICurveStableSwapMetaNG(
curveDollarMetapoolAddress
);

// set curve's metapool in manager facet
ManagerFacet managerFacet = ManagerFacet(address(diamond));
managerFacet.setStableSwapMetaPoolAddress(address(curveDollarMetaPool));
managerFacet.setStableSwapMetaPoolAddress(curveDollarMetaPoolAddress);

// stop sending admin transactions
vm.stopBroadcast();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";

/**
* @notice Factory allows the permissionless deployment of up to
* eight-coin plain pools (ex: DAI-USDT-USDC) and metapools (ex: USDT-3CRV).
* Liquidity pool and LP token share the same contract.
*/
interface ICurveStableSwapFactoryNG {
/**
* @notice Deploys a stableswap NG metapool
* @param _base_pool Address of the base pool to pair the token with. For tripool (DAI-USDT-USDC) use its pool
* address at 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7.
* @param _name Name of the new metapool, ex: `Dollar/3CRV`
* @param _symbol Symbol for the new metapool’s LP token - will be concatenated with the base pool symbol, ex: `Dollar3CRV`
* @param _coin Address of the coin being used in the metapool, ex: use Dollar token address
* @param _A Amplification coefficient. If set to 0 then bonding curve acts like Uniswap. Any >0 value
* makes the bonding curve to swap at 1:1 constant price, the more `_A` the longer the constant price period.
* Curve recommends set it to 100 for crypto collateralizard stablecoins. This parameter can be updated later.
* @param _fee Trade fee, given as an integer with 1e10 precision, ex: 40000000 = 0.04% fee
* @param _offpeg_fee_multiplier Off-peg multiplier. Curve recommends set it to `20000000000`. This parameter can be updated
* later. More info: https://docs.curve.fi/stableswap-exchange/stableswap-ng/pools/overview/#dynamic-fees
* @param _ma_exp_time MA time; set as time_in_seconds / ln(2), ex: 866 = 600 seconds, 2597 = 1800 seconds.
* This parameter can be updated later.
* @param _implementation_idx Index of the metapool implementation to use. Can be retrieved
* via `ICurveStableSwapFactoryNG.metapool_implementations()`. There is only 1 metapool implementation right now
* so use index `0`.
* @param _asset_type Asset type of the pool as an integer. Available asset type indexes:
* - 0: Standard ERC20 token with no additional features
* - 1: Oracle - token with rate oracle (e.g. wstETH)
* - 2: Rebasing - token with rebase (e.g. stETH)
* - 3: ERC4626 - token with convertToAssets method (e.g. sDAI)
* Dollar is a standard ERC20 token so we should use asset type with index `0`.
* @param _method_id First four bytes of the Keccak-256 hash of the function signatures of
* the oracle addresses that give rate oracles. This is applied only to asset type `1` (Oracle).
* For Dollar token deployment set empty.
* @param _oracle Rate oracle address. This is applied only to asset type `1` (Oracle).
* For Dollar token deployment set empty address.
* @return Deployed metapool address
*/
function deploy_metapool(
address _base_pool,
string memory _name,
string memory _symbol,
address _coin,
uint256 _A,
uint256 _fee,
uint256 _offpeg_fee_multiplier,
uint256 _ma_exp_time,
uint256 _implementation_idx,
uint8 _asset_type,
bytes4 _method_id,
address _oracle
) external returns (address);
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ interface ICurveStableSwapMetaNG is IERC20 {
address _receiver
) external returns (uint256);

/**
* @notice Getter for the current balance of coin `i` within the pool
* @param i Coin index
* @return Coin balance
*/
function balances(uint256 i) external view returns (uint256);

/**
* @notice Estimates the amount of LP tokens minted or burned based on a deposit or withdrawal
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ contract MockCurveStableSwapMetaNG is ICurveStableSwapMetaNG, MockERC20 {
return result;
}

function balances(uint256 /* i */) external pure returns (uint256) {
return 0;
}

function calc_token_amount(
uint256[2] memory _amounts,
bool /* _is_deposit */
Expand Down
Loading
Loading