Skip to content

Commit

Permalink
Merge pull request #24 from defi-wonderland/dev
Browse files Browse the repository at this point in the history
feat: v1.0.2 release
  • Loading branch information
piesrtasty authored Dec 7, 2023
2 parents 1162b34 + fc0546e commit 16273ba
Show file tree
Hide file tree
Showing 30 changed files with 1,145 additions and 171 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hai",
"version": "1.0.0",
"version": "1.0.2",
"description": "Multicollateral debt backed stablecoin",
"homepage": "https://github.com/hai-on-op/hai#readme",
"repository": {
Expand All @@ -26,8 +26,8 @@
"lint:fix": "sort-package-json && forge fmt && yarn lint:sol --fix",
"lint:sol": "cross-env solhint 'src/**/*.sol' 'test/**/*.sol'",
"prepare": "husky install",
"script:goerli": "bash -c 'source .env && forge script GoerliScript --with-gas-price 2000000000 -vvvvv --rpc-url $OP_GOERLI_RPC --broadcast --private-key $OP_GOERLI_GOVERNOR_PK --verify --etherscan-api-key $OP_ETHERSCAN_API_KEY'",
"script:goerli:delegate": "bash -c 'source .env && forge script GoerliDelegate --with-gas-price 2000000000 -vvvvv --rpc-url $OP_GOERLI_RPC --broadcast --private-key $OP_GOERLI_GOVERNOR_PK --verify --etherscan-api-key $OP_ETHERSCAN_API_KEY'",
"script:goerli": "bash -c 'source .env && forge script GoerliScript --with-gas-price 2000000000 -vvvvv --rpc-url $OP_GOERLI_RPC --broadcast --private-key $OP_GOERLI_DEPLOYER_PK --verify --etherscan-api-key $OP_ETHERSCAN_API_KEY'",
"script:mainnet": "bash -c 'source .env && forge script MainnetScript --with-gas-price 2000000000 -vvvvv --rpc-url $OP_MAINNET_RPC --broadcast --private-key $OP_MAINNET_DEPLOYER_PK --verify --etherscan-api-key $OP_ETHERSCAN_API_KEY'",
"test": "FOUNDRY_FUZZ_RUNS=128 FOUNDRY_FUZZ_MAX_TEST_REJECTS=10000000 FOUNDRY_FUZZ_SEED=69 forge test -vvv",
"test:e2e": "forge test --match-contract E2E -vvv",
"test:local": "FOUNDRY_FUZZ_RUNS=32 FOUNDRY_FUZZ_MAX_TEST_REJECTS=1000000 forge test -vvv",
Expand Down
73 changes: 62 additions & 11 deletions script/Common.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import '@script/Contracts.s.sol';
import '@script/Params.s.sol';
import '@script/Registry.s.sol';

import {TickMath} from '@uniswap/v3-core/contracts/libraries/TickMath.sol';

abstract contract Common is Contracts, Params {
uint256 internal _deployerPk = 69; // for tests
uint256 internal _governorPK;
Expand Down Expand Up @@ -74,6 +76,9 @@ abstract contract Common is Contracts, Params {
_revoke(accountingJob, _governor);
_revoke(liquidationJob, _governor);
_revoke(oracleJob, _governor);

// token distributor
if (address(tokenDistributor) != address(0)) _revoke(tokenDistributor, _governor);
}

function _revoke(IAuthorizable _contract, address _target) internal {
Expand Down Expand Up @@ -124,6 +129,9 @@ abstract contract Common is Contracts, Params {
_delegate(accountingJob, __delegate);
_delegate(liquidationJob, __delegate);
_delegate(oracleJob, __delegate);

// token distributor
if (address(tokenDistributor) != address(0)) _delegate(tokenDistributor, __delegate);
}

function _delegate(IAuthorizable _contract, address _target) internal {
Expand All @@ -139,6 +147,25 @@ abstract contract Common is Contracts, Params {
protocolToken = new ProtocolToken('Protocol Token', 'KITE');
}

function deployGovernance() public updateParams {
IHaiGovernor.HaiGovernorParams memory _emptyGovernorParams;
// if governor params are not empty, deploy governor
if (keccak256(abi.encode(_governorParams)) != keccak256(abi.encode(_emptyGovernorParams))) {
haiGovernor = new HaiGovernor(
protocolToken,
'HaiGovernor',
_governorParams
);

timelock = TimelockController(payable(haiGovernor.timelock()));

haiDelegatee = new HaiDelegatee(address(timelock));

// sets timelock as protocol governor
governor = address(timelock);
}
}

function deployContracts() public updateParams {
// deploy Base contracts
safeEngine = new SAFEEngine(_safeEngineParams);
Expand All @@ -154,6 +181,7 @@ abstract contract Common is Contracts, Params {
address(protocolToken),
_surplusAuctionHouseParams
);

debtAuctionHouse = new DebtAuctionHouse(
address(safeEngine),
address(protocolToken),
Expand All @@ -173,11 +201,15 @@ abstract contract Common is Contracts, Params {
_liquidationEngineParams
);

collateralAuctionHouseFactory =
new CollateralAuctionHouseFactory(address(safeEngine), address(liquidationEngine), address(oracleRelayer));
collateralAuctionHouseFactory = new CollateralAuctionHouseFactory(
address(safeEngine),
address(liquidationEngine),
address(oracleRelayer)
);

// deploy Token adapters
coinJoin = new CoinJoin(address(safeEngine), address(systemCoin));

collateralJoinFactory = new CollateralJoinFactory(address(safeEngine));
}

Expand Down Expand Up @@ -220,6 +252,21 @@ abstract contract Common is Contracts, Params {
);
}

function deployTokenDistributor() public updateParams {
ITokenDistributor.TokenDistributorParams memory _emptyTokenDistributorParams;
// if token distributor params are not empty, deploy token distributor
if (keccak256(abi.encode(_tokenDistributorParams)) != keccak256(abi.encode(_emptyTokenDistributorParams))) {
// Deploy aidrop distributor contract
tokenDistributor = new TokenDistributor(
ERC20Votes(address(protocolToken)),
_tokenDistributorParams
);

// Mint initial supply to the distributor
protocolToken.mint(address(tokenDistributor), _tokenDistributorParams.totalClaimable);
}
}

function _setupGlobalSettlement() internal {
// setup globalSettlement [auth: disableContract]
safeEngine.addAuthorization(address(globalSettlement));
Expand Down Expand Up @@ -331,20 +378,24 @@ abstract contract Common is Contracts, Params {
rewardedActions = new RewardedActions();
}

function _deployUniV3Pool() internal {
address _uniV3Pool = IUniswapV3Factory(UNISWAP_V3_FACTORY).createPool({
tokenA: address(systemCoin),
tokenB: address(collateral[WETH]),
fee: HAI_POOL_FEE_TIER
});
function _deployUniV3Pool(
address _uniV3Factory,
address _tokenA,
address _tokenB,
uint24 _fee,
uint16 _cardinality,
int24 _initialTick
) internal {
address _uniV3Pool = IUniswapV3Factory(_uniV3Factory).createPool({tokenA: _tokenA, tokenB: _tokenB, fee: _fee});

address _token0 = IUniswapV3Pool(_uniV3Pool).token0();
uint160 _sqrtPriceX96 =
_token0 == address(systemCoin) ? HAI_INITIAL_SQRT_PRICE_X96 : HAI_INITIAL_SQRT_PRICE_X96_INVERSE;
uint160 _sqrtPriceX96 = _token0 == address(_tokenA)
? TickMath.getSqrtRatioAtTick(_initialTick)
: TickMath.getSqrtRatioAtTick(-_initialTick);

IUniswapV3Pool(_uniV3Pool).initialize(_sqrtPriceX96);

for (uint256 _i; _i < HAI_POOL_OBSERVATION_CARDINALITY;) {
for (uint256 _i; _i < _cardinality;) {
IUniswapV3Pool(_uniV3Pool).increaseObservationCardinalityNext(500);
_i += 500;
}
Expand Down
14 changes: 13 additions & 1 deletion script/Contracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity 0.8.20;

// --- Base Contracts ---
import {SystemCoin, ISystemCoin} from '@contracts/tokens/SystemCoin.sol';
import {ProtocolToken, IProtocolToken} from '@contracts/tokens/ProtocolToken.sol';
import {ProtocolToken, IProtocolToken, ERC20Votes} from '@contracts/tokens/ProtocolToken.sol';
import {SAFEEngine, ISAFEEngine} from '@contracts/SAFEEngine.sol';
import {TaxCollector, ITaxCollector} from '@contracts/TaxCollector.sol';
import {AccountingEngine, IAccountingEngine} from '@contracts/AccountingEngine.sol';
Expand Down Expand Up @@ -78,6 +78,12 @@ import {HaiProxy} from '@contracts/proxies/HaiProxy.sol';
import {HaiProxyFactory} from '@contracts/proxies/HaiProxyFactory.sol';
import {HaiSafeManager} from '@contracts/proxies/HaiSafeManager.sol';

// --- Governance Contracts ---
import {TimelockController} from '@openzeppelin/contracts/governance/TimelockController.sol';
import {HaiGovernor, IHaiGovernor} from '@contracts/governance/HaiGovernor.sol';
import {TokenDistributor, ITokenDistributor} from '@contracts/tokens/TokenDistributor.sol';
import {HaiDelegatee} from '@contracts/governance/HaiDelegatee.sol';

/**
* @title Contracts
* @notice This contract initializes all the contracts, so that they're inherited and available throughout scripts scopes.
Expand Down Expand Up @@ -148,4 +154,10 @@ abstract contract Contracts {
PostSettlementSurplusBidActions public postSettlementSurplusBidActions;
GlobalSettlementActions public globalSettlementActions;
RewardedActions public rewardedActions;

// --- Governance contracts ---
TimelockController public timelock;
HaiGovernor public haiGovernor;
TokenDistributor public tokenDistributor;
HaiDelegatee public haiDelegatee;
}
53 changes: 37 additions & 16 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ abstract contract Deploy is Common, Script {
// Deploy tokens used to setup the environment
deployTokens();

// Deploy governance contracts
deployGovernance();

// Environment may be different for each network
setupEnvironment();

Expand Down Expand Up @@ -54,6 +57,9 @@ abstract contract Deploy is Common, Script {
// Deploy and setup contracts that rely on deployed environment
setupPostEnvironment();

// Deploy Merkle tree claim contract and mint protocol tokens to it
deployTokenDistributor();

if (delegate == address(0)) {
_revokeAllTo(governor);
} else if (delegate == deployer) {
Expand All @@ -76,14 +82,15 @@ contract DeployMainnet is MainnetParams, Deploy {
function setupEnvironment() public virtual override updateParams {
// Deploy oracle factories
chainlinkRelayerFactory = new ChainlinkRelayerFactory(OP_CHAINLINK_SEQUENCER_UPTIME_FEED);
uniV3RelayerFactory = new UniV3RelayerFactory();
uniV3RelayerFactory = new UniV3RelayerFactory(UNISWAP_V3_FACTORY);
denominatedOracleFactory = new DenominatedOracleFactory();
delayedOracleFactory = new DelayedOracleFactory();

// Setup oracle feeds
IBaseOracle _ethUSDPriceFeed = chainlinkRelayerFactory.deployChainlinkRelayer(OP_CHAINLINK_ETH_USD_FEED, 1 hours);
IBaseOracle _wstethETHPriceFeed =
chainlinkRelayerFactory.deployChainlinkRelayer(OP_CHAINLINK_WSTETH_ETH_FEED, 1 hours);
IBaseOracle _opUSDPriceFeed = chainlinkRelayerFactory.deployChainlinkRelayer(OP_CHAINLINK_OP_USD_FEED, 1 hours);

IBaseOracle _wstethUSDPriceFeed = denominatedOracleFactory.deployDenominatedOracle({
_priceSource: _wstethETHPriceFeed,
Expand All @@ -93,23 +100,18 @@ contract DeployMainnet is MainnetParams, Deploy {

delayedOracle[WETH] = delayedOracleFactory.deployDelayedOracle(_ethUSDPriceFeed, 1 hours);
delayedOracle[WSTETH] = delayedOracleFactory.deployDelayedOracle(_wstethUSDPriceFeed, 1 hours);
delayedOracle[OP] = delayedOracleFactory.deployDelayedOracle(_opUSDPriceFeed, 1 hours);

collateral[WETH] = IERC20Metadata(OP_WETH);
collateral[WSTETH] = IERC20Metadata(OP_WSTETH);
collateral[OP] = IERC20Metadata(OP_OPTIMISM);

collateralTypes.push(WETH);
collateralTypes.push(WSTETH);
collateralTypes.push(OP);

// Deploy HAI/WETH UniV3 pool
_deployUniV3Pool();

// Setup HAI oracle feed
systemCoinOracle = uniV3RelayerFactory.deployUniV3Relayer({
_baseToken: address(systemCoin),
_quoteToken: address(collateral[WETH]),
_feeTier: HAI_POOL_FEE_TIER,
_quotePeriod: 1 days
});
// NOTE: Deploying the PID Controller turned off until governance action
systemCoinOracle = new HardcodedOracle('HAI / USD', HAI_USD_INITIAL_PRICE); // 1 HAI = 1 USD
}

function setupPostEnvironment() public virtual override updateParams {}
Expand All @@ -122,16 +124,18 @@ contract DeployGoerli is GoerliParams, Deploy {
}

function setupEnvironment() public virtual override updateParams {
delegate = 0x8125aAa8F7912aEb500553a5b1710BB16f7A6C65; // EOA

// Deploy oracle factories
chainlinkRelayerFactory = new ChainlinkRelayerFactory(OP_GOERLI_CHAINLINK_SEQUENCER_UPTIME_FEED);
uniV3RelayerFactory = new UniV3RelayerFactory();
uniV3RelayerFactory = new UniV3RelayerFactory(OP_GOERLI_UNISWAP_V3_FACTORY);
denominatedOracleFactory = new DenominatedOracleFactory();
delayedOracleFactory = new DelayedOracleFactory();

// Setup oracle feeds

// HAI
systemCoinOracle = new HardcodedOracle('HAI / USD', HAI_INITIAL_PRICE); // 1 HAI = 1 USD
systemCoinOracle = new HardcodedOracle('HAI / USD', HAI_USD_INITIAL_PRICE); // 1 HAI = 1 USD

// WETH
collateral[WETH] = IERC20Metadata(OP_WETH);
Expand All @@ -152,13 +156,30 @@ contract DeployGoerli is GoerliParams, Deploy {
collateral[STONES] = new MintableERC20('Stones', 'STN', 3);
collateral[TOTEM] = new MintableERC20('Totem', 'TTM', 0);

// Deploy STN / WBTC UniV3 pool
_deployUniV3Pool(
OP_GOERLI_UNISWAP_V3_FACTORY,
address(collateral[STONES]),
address(collateral[WBTC]),
HAI_POOL_FEE_TIER,
HAI_POOL_OBSERVATION_CARDINALITY,
46_054 // 1000.000 STN = 1.00000000 wBTC
);

// BTC: live feed
IBaseOracle _wbtcUsdOracle =
chainlinkRelayerFactory.deployChainlinkRelayer(OP_GOERLI_CHAINLINK_BTC_USD_FEED, 1 hours);
// STN: denominated feed (1000 STN = 1 wBTC)
IBaseOracle _stonesWbtcOracle = new HardcodedOracle('STN / BTC', 0.001e18);

// STN: uniswap denominated feed
IBaseOracle _stonesWbtcOracle = uniV3RelayerFactory.deployUniV3Relayer({
_baseToken: address(collateral[STONES]),
_quoteToken: address(collateral[WBTC]),
_feeTier: HAI_POOL_FEE_TIER,
_quotePeriod: 1 hours
});
IBaseOracle _stonesOracle =
denominatedOracleFactory.deployDenominatedOracle(_stonesWbtcOracle, _wbtcUsdOracle, false);

// TTM: hardcoded feed (TTM price is 1)
IBaseOracle _totemOracle = new HardcodedOracle('TTM', 1e18);

Expand All @@ -179,7 +200,7 @@ contract DeployGoerli is GoerliParams, Deploy {
function setupPostEnvironment() public virtual override updateParams {
// Setup deviated oracle
systemCoinOracle = new DeviatedOracle({
_symbol: 'HAI/USD',
_symbol: 'HAI / USD',
_oracleRelayer: address(oracleRelayer),
_deviation: OP_GOERLI_HAI_PRICE_DEVIATION
});
Expand Down
Loading

0 comments on commit 16273ba

Please sign in to comment.