Skip to content

Commit

Permalink
feat: fractional mainnet migration (#924)
Browse files Browse the repository at this point in the history
* refactor: use a single migration

* feat: add fractional migration

* fix: set Governance token address
  • Loading branch information
rndquu authored Apr 11, 2024
1 parent 9181675 commit 2eddcfb
Show file tree
Hide file tree
Showing 10 changed files with 471 additions and 241 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ COLLATERAL_TOKEN_ADDRESS="0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"
# - testnet/anvil: deploys LUSD/USD chainlink price feed from scratch
COLLATERAL_TOKEN_CHAINLINK_PRICE_FEED_ADDRESS="0x3D7aE7E594f2f2091Ad8798313450130d0Aba3a0"

# Curve's Governance/WETH pool address.
# Used to fetch Governance/ETH price from built-in oracle.
# By default set to already deployed (production ready) Governance/WETH pool address.
# - mainnet: uses already deployed Governance/ETH pool address
# - testnet/anvil: deploys Governance/WETH pool from scratch
CURVE_GOVERNANCE_WETH_POOL_ADDRESS="0xaCDc85AFCD8B83Eb171AFFCbe29FaD204F6ae45C"

# Chainlink price feed address for ETH/USD pair.
# Used to calculate Governance token price in USD.
# By default set to ETH/USD price feed deployed on ethereum mainnet.
# - mainnet: uses already deployed ETH/USD chainlink price feed
# - testnet/anvil: deploys ETH/USD chainlink price feed from scratch
ETH_USD_CHAINLINK_PRICE_FEED_ADDRESS="0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"

# 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"
Expand Down
4 changes: 2 additions & 2 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"**/cspell.json",
"**/node_modules/**",
"packages/contracts/src/deprecated/*",
"packages/contracts/migrations/development/Deploy002_Governance.s.sol",
"packages/contracts/migrations/mainnet/Deploy002_Governance.s.sol"
"packages/contracts/migrations/development/Deploy001_Diamond_Dollar_Governance.s.sol",
"packages/contracts/migrations/mainnet/Deploy001_Diamond_Dollar_Governance.s.sol"
],
"readonly": true,
"useGitignore": true,
Expand Down
14 changes: 14 additions & 0 deletions packages/contracts/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ COLLATERAL_TOKEN_ADDRESS="0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"
# - testnet/anvil: deploys LUSD/USD chainlink price feed from scratch
COLLATERAL_TOKEN_CHAINLINK_PRICE_FEED_ADDRESS="0x3D7aE7E594f2f2091Ad8798313450130d0Aba3a0"

# Curve's Governance/WETH pool address.
# Used to fetch Governance/ETH price from built-in oracle.
# By default set to Governance/WETH pool address deployed on ethereum mainnet.
# - mainnet: uses already deployed (production ready) Governance/ETH pool address
# - testnet/anvil: deploys Governance/WETH pool from scratch
CURVE_GOVERNANCE_WETH_POOL_ADDRESS="0xaCDc85AFCD8B83Eb171AFFCbe29FaD204F6ae45C"

# Chainlink price feed address for ETH/USD pair.
# Used to calculate Governance token price in USD.
# By default set to ETH/USD price feed deployed on ethereum mainnet.
# - mainnet: uses already deployed ETH/USD chainlink price feed
# - testnet/anvil: deploys ETH/USD chainlink price feed from scratch
ETH_USD_CHAINLINK_PRICE_FEED_ADDRESS="0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"

# 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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {Script} from "forge-std/Script.sol";
import {UbiquityAlgorithmicDollarManager} from "../../src/deprecated/UbiquityAlgorithmicDollarManager.sol";
import {UbiquityGovernance} from "../../src/deprecated/UbiquityGovernance.sol";
import {Diamond, DiamondArgs} from "../../src/dollar/Diamond.sol";
import {UbiquityDollarToken} from "../../src/dollar/core/UbiquityDollarToken.sol";
import {AccessControlFacet} from "../../src/dollar/facets/AccessControlFacet.sol";
Expand All @@ -15,15 +17,17 @@ import {ManagerFacet} from "../../src/dollar/facets/ManagerFacet.sol";
import {OwnershipFacet} from "../../src/dollar/facets/OwnershipFacet.sol";
import {UbiquityPoolFacet} from "../../src/dollar/facets/UbiquityPoolFacet.sol";
import {ICurveStableSwapMetaNG} from "../../src/dollar/interfaces/ICurveStableSwapMetaNG.sol";
import {ICurveTwocryptoOptimized} from "../../src/dollar/interfaces/ICurveTwocryptoOptimized.sol";
import {IDiamondCut} from "../../src/dollar/interfaces/IDiamondCut.sol";
import {IDiamondLoupe} from "../../src/dollar/interfaces/IDiamondLoupe.sol";
import {IERC173} from "../../src/dollar/interfaces/IERC173.sol";
import {DEFAULT_ADMIN_ROLE, DOLLAR_TOKEN_MINTER_ROLE, DOLLAR_TOKEN_BURNER_ROLE, PAUSER_ROLE} from "../../src/dollar/libraries/Constants.sol";
import {DEFAULT_ADMIN_ROLE, DOLLAR_TOKEN_MINTER_ROLE, DOLLAR_TOKEN_BURNER_ROLE, GOVERNANCE_TOKEN_MINTER_ROLE, GOVERNANCE_TOKEN_BURNER_ROLE, PAUSER_ROLE} from "../../src/dollar/libraries/Constants.sol";
import {LibAccessControl} from "../../src/dollar/libraries/LibAccessControl.sol";
import {AppStorage, LibAppStorage, Modifiers} from "../../src/dollar/libraries/LibAppStorage.sol";
import {LibDiamond} from "../../src/dollar/libraries/LibDiamond.sol";
import {MockChainLinkFeed} from "../../src/dollar/mocks/MockChainLinkFeed.sol";
import {MockCurveStableSwapMetaNG} from "../../src/dollar/mocks/MockCurveStableSwapMetaNG.sol";
import {MockCurveTwocryptoOptimized} from "../../src/dollar/mocks/MockCurveTwocryptoOptimized.sol";
import {MockERC20} from "../../src/dollar/mocks/MockERC20.sol";
import {DiamondTestHelper} from "../../test/helpers/DiamondTestHelper.sol";

Expand Down Expand Up @@ -93,12 +97,16 @@ contract DiamondInit is Modifiers {
* - StakingFacet (staking is not a part of the initial deployment)
* - StakingFormulasFacet (staking is not a part of the initial deployment)
*/
contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
contract Deploy001_Diamond_Dollar_Governance is Script, DiamondTestHelper {
// env variables
uint256 adminPrivateKey;
uint256 ownerPrivateKey;
uint256 initialDollarMintAmountWei;

// owner and admin addresses derived from private keys store in `.env` file
address adminAddress;
address ownerAddress;

// threshold in seconds when price feed response should be considered stale
uint256 CHAINLINK_PRICE_FEED_THRESHOLD;

Expand All @@ -119,13 +127,19 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
UbiquityPoolFacet ubiquityPoolFacetImplementation;

// oracle related contracts
AggregatorV3Interface chainLinkPriceFeedEth; // chainlink ETH/USD price feed
AggregatorV3Interface chainLinkPriceFeedLusd; // chainlink LUSD/USD price feed
IERC20 curveTriPoolLpToken; // Curve's 3CRV-LP token
ICurveStableSwapMetaNG curveDollarMetaPool; // Curve's Dollar-3CRVLP metapool
ICurveTwocryptoOptimized curveGovernanceEthPool; // Curve's Governance-WETH crypto pool

// collateral ERC20 token used in UbiquityPoolFacet
IERC20 collateralToken;

// Governance token related contracts
UbiquityAlgorithmicDollarManager ubiquityAlgorithmicDollarManager;
UbiquityGovernance ubiquityGovernance;

// selectors for all of the facets
bytes4[] selectorsOfAccessControlFacet;
bytes4[] selectorsOfDiamondCutFacet;
Expand All @@ -142,8 +156,8 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
"INITIAL_DOLLAR_MINT_AMOUNT_WEI"
);

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

//==================
// Before scripts
Expand Down Expand Up @@ -307,6 +321,8 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
ubiquityPoolFacet.setRedemptionDelayBlocks(2);
// set mint price threshold to $1.01 and redeem price to $0.99
ubiquityPoolFacet.setPriceThresholds(1010000, 990000);
// set collateral ratio to 95%
ubiquityPoolFacet.setCollateralRatio(950_000);

// stop sending admin transactions
vm.stopBroadcast();
Expand Down Expand Up @@ -388,21 +404,37 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
/**
* @notice Runs after the main `run()` method
*
* @dev Initializes oracle related contracts
* @dev Ubiquity protocol supports 2 oracles:
* @dev Initializes:
* - oracle related contracts
* - Governance token related contracts
*
* @dev Ubiquity protocol supports 4 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
* 3. Chainlink's price feed (used in UbiquityPool) to fetch ETH/USD price
* 4. Curve's Governance-WETH crypto pool to fetch Governance/ETH price
*
* There are 2 migrations (deployment scripts):
* 1. Development (for usage in testnet and local anvil instance forked from mainnet)
* 1. Development (for usage in testnet and local anvil instance)
* 2. Mainnet (for production usage in mainnet)
*
* Development migration deploys (for ease of debugging) mocks of:
* - Chainlink price feed contract
* - Chainlink collateral price feed contract
* - Chainlink ETH/USD price feed contract
* - 3CRVLP ERC20 token
* - WETH token
* - Curve's Dollar-3CRVLP metapool contract
* - Curve's Governance-WETH crypto pool contract
*/
function afterRun() public virtual {
ManagerFacet managerFacet = ManagerFacet(address(diamond));
UbiquityPoolFacet ubiquityPoolFacet = UbiquityPoolFacet(
address(diamond)
);

// set threshold to 10 years (3650 days) for ease of debugging
CHAINLINK_PRICE_FEED_THRESHOLD = 3650 days;

//========================================
// Chainlink LUSD/USD price feed deploy
//========================================
Expand All @@ -423,9 +455,6 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
// start sending admin transactions
vm.startBroadcast(adminPrivateKey);

// set threshold to 10 years (3650 days) for ease of debugging
CHAINLINK_PRICE_FEED_THRESHOLD = 3650 days;

// set params for LUSD/USD chainlink price feed mock
MockChainLinkFeed(address(chainLinkPriceFeedLusd)).updateMockParams(
1, // round id
Expand All @@ -435,10 +464,6 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
1 // answered in round
);

UbiquityPoolFacet ubiquityPoolFacet = UbiquityPoolFacet(
address(diamond)
);

// set price feed address and threshold in seconds
ubiquityPoolFacet.setCollateralChainLinkPriceFeed(
address(collateralToken), // collateral token address
Expand Down Expand Up @@ -482,12 +507,141 @@ contract Deploy001_Diamond_Dollar is Script, DiamondTestHelper {
// start sending admin transactions
vm.startBroadcast(adminPrivateKey);

ManagerFacet managerFacet = ManagerFacet(address(diamond));

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

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

//===========================================
// Deploy UbiquityAlgorithmicDollarManager
//===========================================

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

ubiquityAlgorithmicDollarManager = new UbiquityAlgorithmicDollarManager(
ownerAddress
);

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

//=============================
// Deploy UbiquityGovernance
//=============================

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

ubiquityGovernance = new UbiquityGovernance(
address(ubiquityAlgorithmicDollarManager)
);

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

//==================================
// UbiquityGovernance token setup
//==================================

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

AccessControlFacet accessControlFacet = AccessControlFacet(
address(diamond)
);

// grant diamond Governance token minting and burning rights
accessControlFacet.grantRole(
GOVERNANCE_TOKEN_MINTER_ROLE,
address(diamond)
);
accessControlFacet.grantRole(
GOVERNANCE_TOKEN_BURNER_ROLE,
address(diamond)
);

// set Governance token address in manager facet
managerFacet.setGovernanceTokenAddress(address(ubiquityGovernance));

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

//=======================================
// Chainlink ETH/USD price feed deploy
//=======================================

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

// deploy ETH/USD chainlink mock price feed
chainLinkPriceFeedEth = new MockChainLinkFeed();

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

//======================================
// Chainlink ETH/USD price feed setup
//======================================

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

// set ETH/USD price feed mock params
MockChainLinkFeed(address(chainLinkPriceFeedEth)).updateMockParams(
1, // round id
3000_00000000, // answer, 3000_00000000 = $3000 (8 decimals)
block.timestamp, // started at
block.timestamp, // updated at
1 // answered in round
);

// set price feed for ETH/USD pair
ubiquityPoolFacet.setEthUsdChainLinkPriceFeed(
address(chainLinkPriceFeedEth), // price feed address
CHAINLINK_PRICE_FEED_THRESHOLD // price feed staleness threshold in seconds
);

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

//==============================================
// Curve's Governance-WETH crypto pool deploy
//==============================================

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

// init mock WETH token
IERC20 wethToken = new MockERC20("WETH", "WETH", 18);

// init Curve Governance-WETH crypto pool
curveGovernanceEthPool = new MockCurveTwocryptoOptimized(
address(ubiquityGovernance),
address(wethToken)
);

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

//=============================================
// Curve's Governance-WETH crypto pool setup
//=============================================

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

// set ETH/Governance price to 30k in Curve pool mock
MockCurveTwocryptoOptimized(address(curveGovernanceEthPool))
.updateMockParams(30_000e18);

// set Governance-ETH pool
ubiquityPoolFacet.setGovernanceEthPoolAddress(
address(curveGovernanceEthPool)
);

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

This file was deleted.

7 changes: 2 additions & 5 deletions packages/contracts/migrations/development/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,5 @@
# load env variables
source .env

# Deploy001_Diamond_Dollar (deploys Diamond and Dollar contracts)
forge script migrations/development/Deploy001_Diamond_Dollar.s.sol:Deploy001_Diamond_Dollar --rpc-url $RPC_URL --broadcast -vvvv

# Deploy002_Governance (deploys Governance token)
forge script migrations/development/Deploy002_Governance.s.sol:Deploy002_Governance --rpc-url $RPC_URL --broadcast -vvvv
# Deploy001_Diamond_Dollar_Governance (deploys Diamond, Dollar and Governance related contracts)
forge script migrations/development/Deploy001_Diamond_Dollar_Governance.s.sol:Deploy001_Diamond_Dollar_Governance --rpc-url $RPC_URL --broadcast -vvvv
Loading

0 comments on commit 2eddcfb

Please sign in to comment.