Skip to content

Commit

Permalink
Merge pull request #921 from rndquu/feat/curve-migration
Browse files Browse the repository at this point in the history
Feat/curve migration
  • Loading branch information
gitcoindev committed Mar 30, 2024
2 parents b06fada + cb82336 commit b595120
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 2,570 deletions.
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

0 comments on commit b595120

Please sign in to comment.