diff --git a/artifacts/index.ts b/artifacts/index.ts index 177ed8b..e0130e4 100644 --- a/artifacts/index.ts +++ b/artifacts/index.ts @@ -1,13 +1,9 @@ export { AssetPairManager } from './ts/AssetPairManager'; export { AssetPairManagerV2 } from './ts/AssetPairManagerV2'; export { BinaryAllocator } from './ts/BinaryAllocator'; -export { BTCDaiRebalancingManager } from './ts/BTCDaiRebalancingManager'; -export { BTCETHRebalancingManager } from './ts/BTCETHRebalancingManager'; -export { ETHDaiRebalancingManager } from './ts/ETHDaiRebalancingManager'; export { InverseMACOStrategyManager } from './ts/InverseMACOStrategyManager'; export { MACOStrategyManager } from './ts/MACOStrategyManager'; export { MACOStrategyManagerV2 } from './ts/MACOStrategyManagerV2'; -export { ManagerLibraryMock } from './ts/ManagerLibraryMock'; export { MovingAverageCrossoverTrigger } from './ts/MovingAverageCrossoverTrigger'; export { RSITrendingTrigger } from './ts/RSITrendingTrigger'; export { SocialAllocator } from './ts/SocialAllocator'; @@ -20,13 +16,9 @@ export { AssetPairManagerV2Contract, BaseContract, BinaryAllocatorContract, - BTCDaiRebalancingManagerContract, - BTCETHRebalancingManagerContract, - ETHDaiRebalancingManagerContract, InverseMACOStrategyManagerContract, MACOStrategyManagerContract, MACOStrategyManagerV2Contract, - ManagerLibraryMockContract, MovingAverageCrossoverTriggerContract, RSITrendingTriggerContract, SocialAllocatorContract, diff --git a/contracts/managers/BTCDaiRebalancingManager.sol b/contracts/managers/BTCDaiRebalancingManager.sol deleted file mode 100644 index 3cd2985..0000000 --- a/contracts/managers/BTCDaiRebalancingManager.sol +++ /dev/null @@ -1,350 +0,0 @@ -/* - Copyright 2018 Set Labs Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -pragma solidity 0.5.7; -pragma experimental "ABIEncoderV2"; - -import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import { AddressArrayUtils } from "set-protocol-contract-utils/contracts/lib/AddressArrayUtils.sol"; -import { ICore } from "set-protocol-contracts/contracts/core/interfaces/ICore.sol"; -import { IRebalancingSetToken } from "set-protocol-contracts/contracts/core/interfaces/IRebalancingSetToken.sol"; -import { ISetToken } from "set-protocol-contracts/contracts/core/interfaces/ISetToken.sol"; -import { RebalancingLibrary } from "set-protocol-contracts/contracts/core/lib/RebalancingLibrary.sol"; - -import { ManagerLibrary } from "./lib/ManagerLibrary.sol"; - - -/** - * @title BTCDaiRebalancingManager - * @author Set Protocol - * - * Contract used to manage a BTCDai Rebalancing Set Token - */ -contract BTCDaiRebalancingManager { - - using SafeMath for uint256; - using AddressArrayUtils for address[]; - - /* ============ Constants ============ */ - - uint256 constant PRICE_PRECISION = 1; - uint256 constant AUCTION_LIB_PRICE_DIVISOR = 1000; - - // Equal to $1 - uint256 constant DAI_PRICE = 10 ** 18; - uint256 constant DAI_DECIMALS = 18; - uint256 constant BTC_DECIMALS = 8; - uint256 constant DECIMAL_DIFF_MULTIPLIER = 10 ** 10; - - /* ============ State Variables ============ */ - - address public daiAddress; - address public btcAddress; - address public setTokenFactory; - - address public btcPriceFeed; - - address public coreAddress; - - address public auctionLibrary; - uint256 public auctionTimeToPivot; - uint256 public daiMultiplier; - uint256 public btcMultiplier; - - uint256 public maximumLowerThreshold; - uint256 public minimumUpperThreshold; - - /* ============ Events ============ */ - - event LogManagerProposal( - uint256 btcPrice - ); - - /* ============ Constructor ============ */ - - /* - * Rebalancing Token Manager constructor. - * The multipliers are used to calculate the allocation of the set token. Allocation - * is determined by a simple equation: - * daiAllocation = daiMultiplier/(daiMultiplier + btcMultiplier) - * Furthermore the total USD cost of any new Set Token allocation can be found from the - * following equation: - * SetTokenUSDPrice = (daiMultiplier + btcMultiplier)*max(btcPrice, daiPrice) - * - * @param _coreAddress The address of the Core contract - * @param _btcPriceFeedAddress The address of btc medianizer - * @param _daiAddress The address of the Dai contract - * @param _btcAddress The address of the wrapped btc contract - * @param _setTokenFactory The address of the SetTokenFactory - * @param _auctionLibrary The address of auction price curve to use in rebalance - * @param _auctionTimeToPivot The amount of time until pivot reached in rebalance - * @param _multipliers Token multipliers used to determine allocation - * @param _allocationBounds Bounds to stop proposal if not enough deviation from expected allocation - * set to be [lowerBound, upperBound] - */ - constructor( - address _coreAddress, - address _btcPriceFeedAddress, - address _daiAddress, - address _btcAddress, - address _setTokenFactory, - address _auctionLibrary, - uint256 _auctionTimeToPivot, - uint256[2] memory _multipliers, - uint256[2] memory _allocationBounds - ) - public - { - require( - _allocationBounds[1] >= _allocationBounds[0], - "RebalancingTokenManager.constructor: Upper allocation bound must be greater than lower." - ); - - coreAddress = _coreAddress; - - btcPriceFeed = _btcPriceFeedAddress; - - daiAddress = _daiAddress; - btcAddress = _btcAddress; - setTokenFactory = _setTokenFactory; - - auctionLibrary = _auctionLibrary; - auctionTimeToPivot = _auctionTimeToPivot; - daiMultiplier = _multipliers[0]; - btcMultiplier = _multipliers[1]; - - maximumLowerThreshold = _allocationBounds[0]; - minimumUpperThreshold = _allocationBounds[1]; - } - - /* ============ External ============ */ - - /* - * When allowed on RebalancingSetToken, anyone can call for a new rebalance proposal - * - * @param _rebalancingSetTokenAddress The address of Rebalancing Set Token to propose new allocation - */ - function propose( - address _rebalancingSetTokenAddress - ) - external - { - // Make sure the rebalancingSetToken is tracked by Core - require( - ICore(coreAddress).validSets(_rebalancingSetTokenAddress), - "RebalanceAuctionModule.bid: Invalid or disabled SetToken address" - ); - - // Create interface to interact with RebalancingSetToken - IRebalancingSetToken rebalancingSetInterface = IRebalancingSetToken(_rebalancingSetTokenAddress); - - ManagerLibrary.validateManagerPropose(rebalancingSetInterface); - - // Get price data - uint256 btcPrice = ManagerLibrary.queryPriceData(btcPriceFeed); - - // Require that allocation has changed sufficiently enough to justify rebalance - uint256 currentSetDollarAmount = checkSufficientAllocationChange( - btcPrice, - rebalancingSetInterface.currentSet() - ); - - // Create new Set Token that collateralizes Rebalancing Set Token - ( - address nextSetAddress, - uint256 nextSetDollarAmount - ) = createNewAllocationSetToken(btcPrice); - - // Calculate the auctionStartPrice and auctionPivotPrice of rebalance auction using dollar value - // of both the current and nextSet - ( - uint256 auctionStartPrice, - uint256 auctionPivotPrice - ) = ManagerLibrary.calculateAuctionPriceParameters( - currentSetDollarAmount, - nextSetDollarAmount, - AUCTION_LIB_PRICE_DIVISOR, - auctionTimeToPivot - ); - - // Propose new allocation to Rebalancing Set Token - rebalancingSetInterface.propose( - nextSetAddress, - auctionLibrary, - auctionTimeToPivot, - auctionStartPrice, - auctionPivotPrice - ); - - emit LogManagerProposal( - btcPrice - ); - } - - /* ============ Internal ============ */ - - /* - * Check there has been a sufficient change in allocation as defined by maximumUpperThreshold - * and minimumLowerThreshold and return USD value of currentSet. - * - * @param _btcPrice The 18 decimal dollar value of one full BTC - * @param _currentSetAddress The address of the Rebalancing Set Token's currentSet - * @return The currentSet's USD value (in cents) - */ - function checkSufficientAllocationChange( - uint256 _btcPrice, - address _currentSetAddress - ) - private - view - returns (uint256) - { - // Create current set interface - ISetToken currentSetTokenInterface = ISetToken(_currentSetAddress); - - // Get naturalUnit and units of currentSet - uint256 currentSetNaturalUnit = currentSetTokenInterface.naturalUnit(); - uint256[] memory currentSetUnits = currentSetTokenInterface.getUnits(); - - // // Calculate dai dollar value in currentSet (in cents) - uint256 daiDollarAmount = ManagerLibrary.calculateTokenAllocationAmountUSD( - DAI_PRICE, - currentSetNaturalUnit, - currentSetUnits[0], - DAI_DECIMALS - ); - - uint256[] memory assetPrices = new uint256[](2); - assetPrices[0] = DAI_PRICE; - assetPrices[1] = _btcPrice; - - uint256[] memory assetDecimals = new uint256[](2); - assetDecimals[0] = DAI_DECIMALS; - assetDecimals[1] = BTC_DECIMALS; - - uint256 currentSetDollarAmount = ManagerLibrary.calculateSetTokenDollarValue( - assetPrices, - currentSetNaturalUnit, - currentSetUnits, - assetDecimals - ); - - // Require that the allocation has changed enough to trigger buy or sell - require( - daiDollarAmount.mul(100).div(currentSetDollarAmount) >= minimumUpperThreshold || - daiDollarAmount.mul(100).div(currentSetDollarAmount) < maximumLowerThreshold, - "RebalancingTokenManager.proposeNewRebalance: Allocation must be further away from 50 percent" - ); - - return currentSetDollarAmount; - } - - /* - * Determine units and naturalUnit of nextSet to propose, calculate auction parameters, and - * create nextSet - * - * @param _btcPrice The 18 decimal dollar value of one full BTC - * @return address The address of nextSet - * @return uint256 The dollar value of the nextSet - */ - function createNewAllocationSetToken( - uint256 _btcPrice - ) - private - returns (address, uint256) - { - // Calculate the nextSet units and naturalUnit, determine dollar value of nextSet - ( - uint256 nextSetNaturalUnit, - uint256 nextSetDollarAmount, - uint256[] memory nextSetUnits - ) = calculateNextSetUnits( - _btcPrice - ); - - // Create static components array - address[] memory nextSetComponents = new address[](2); - nextSetComponents[0] = daiAddress; - nextSetComponents[1] = btcAddress; - - // Create the nextSetToken contract that collateralized the Rebalancing Set Token once rebalance - // is finished - address nextSetAddress = ICore(coreAddress).createSet( - setTokenFactory, - nextSetComponents, - nextSetUnits, - nextSetNaturalUnit, - bytes32("DAIBTC"), - bytes32("DAIBTC"), - "" - ); - - return (nextSetAddress, nextSetDollarAmount); - } - - /* - * Determine units and naturalUnit of nextSet to propose - * - * @param _btcPrice The 18 decimal value of one full BTC - * @return uint256 The naturalUnit of nextSet - * @return uint256 The dollar value of nextSet - * @return uint256[] The units of nextSet - */ - function calculateNextSetUnits( - uint256 _btcPrice - ) - private - returns (uint256, uint256, uint256[] memory) - { - // Initialize set token parameters - uint256[] memory nextSetUnits = new uint256[](2); - uint256 nextSetNaturalUnit = DECIMAL_DIFF_MULTIPLIER.mul(PRICE_PRECISION); - - if (_btcPrice >= DAI_PRICE) { - // Dai nextSetUnits is equal the USD Bitcoin price - uint256 daiUnits = _btcPrice.mul(DECIMAL_DIFF_MULTIPLIER).div(DAI_PRICE); - - // Create unit array and define natural unit - nextSetUnits[0] = daiUnits.mul(daiMultiplier).mul(PRICE_PRECISION); - nextSetUnits[1] = btcMultiplier.mul(PRICE_PRECISION); - } else { - // Calculate btc nextSetUnits as (daiPrice/btcPrice)*100. 100 is used to add - // precision. - uint256 btcDaiPrice = DAI_PRICE.mul(PRICE_PRECISION).div(_btcPrice); - - // Create unit array and define natural unit - nextSetUnits[0] = daiMultiplier.mul(DECIMAL_DIFF_MULTIPLIER).mul(PRICE_PRECISION); - nextSetUnits[1] = btcDaiPrice.mul(btcMultiplier); - } - - uint256[] memory assetPrices = new uint256[](2); - assetPrices[0] = DAI_PRICE; - assetPrices[1] = _btcPrice; - - uint256[] memory assetDecimals = new uint256[](2); - assetDecimals[0] = DAI_DECIMALS; - assetDecimals[1] = BTC_DECIMALS; - - uint256 nextSetDollarAmount = ManagerLibrary.calculateSetTokenDollarValue( - assetPrices, - nextSetNaturalUnit, - nextSetUnits, - assetDecimals - ); - - return (nextSetNaturalUnit, nextSetDollarAmount, nextSetUnits); - } -} diff --git a/contracts/managers/BTCETHRebalancingManager.sol b/contracts/managers/BTCETHRebalancingManager.sol deleted file mode 100644 index 1ecc647..0000000 --- a/contracts/managers/BTCETHRebalancingManager.sol +++ /dev/null @@ -1,377 +0,0 @@ -/* - Copyright 2018 Set Labs Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -pragma solidity 0.5.7; -pragma experimental "ABIEncoderV2"; - -import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import { AddressArrayUtils } from "set-protocol-contract-utils/contracts/lib/AddressArrayUtils.sol"; -import { ICore } from "set-protocol-contracts/contracts/core/interfaces/ICore.sol"; -import { IRebalancingSetToken } from "set-protocol-contracts/contracts/core/interfaces/IRebalancingSetToken.sol"; -import { ISetToken } from "set-protocol-contracts/contracts/core/interfaces/ISetToken.sol"; -import { RebalancingLibrary } from "set-protocol-contracts/contracts/core/lib/RebalancingLibrary.sol"; - -import { ManagerLibrary } from "./lib/ManagerLibrary.sol"; - - -/** - * @title BTCETHRebalancingManager - * @author Set Protocol - * - * Contract used to manage a BTCETH Rebalancing Set Token - */ -contract BTCETHRebalancingManager { - - using SafeMath for uint256; - using AddressArrayUtils for address[]; - - /* ============ Constants ============ */ - - uint256 constant PRICE_PRECISION = 100; - uint256 constant AUCTION_LIB_PRICE_DIVISOR = 1000; - uint256 constant BTC_DECIMALS = 8; - uint256 constant ETH_DECIMALS = 18; - uint256 constant DECIMAL_DIFF_MULTIPLIER = 10 ** 10; - - /* ============ State Variables ============ */ - - address public btcAddress; - address public ethAddress; - address public setTokenFactory; - - address public btcPriceFeed; - address public ethPriceFeed; - - address public coreAddress; - - address public auctionLibrary; - uint256 public auctionTimeToPivot; - uint256 public btcMultiplier; - uint256 public ethMultiplier; - - uint256 public maximumLowerThreshold; - uint256 public minimumUpperThreshold; - - /* ============ Events ============ */ - - event LogManagerProposal( - uint256 btcPrice, - uint256 ethPrice - ); - - /* ============ Constructor ============ */ - - /* - * Rebalancing Token Manager constructor. - * The multipliers are used to calculate the allocation of the set token. Allocation - * is determined by a simple equation: - * btcAllocation = btcMultiplier/(btcMultiplier + ethMultiplier) - * Furthermore the total USD cost of any new Set Token allocation can be found from the - * following equation: - * SetTokenUSDPrice = (btcMultiplier + ethMultiplier)*max(ethPrice, btcPrice) - * - * @param _coreAddress The address of the Core contract - * @param _btcPriceFeedAddress The address of BTC medianizer - * @param _ethPriceFeedAddress The address of ETH medianizer - * @param _btcAddress The address of the wrapped BTC contract - * @param _ethAddress The address of the wrapped ETH contract - * @param _setTokenFactory The address of the SetTokenFactory - * @param _auctionLibrary The address of auction price curve to use in rebalance - * @param _auctionTimeToPivot The amount of time until pivot reached in rebalance - * @param _btcMultiplier With _ethMultiplier, the ratio amount of wbtc to include - * @param _ethMultiplier With _btcMultiplier, the ratio amount of weth to include - */ - constructor( - address _coreAddress, - address _btcPriceFeedAddress, - address _ethPriceFeedAddress, - address _btcAddress, - address _ethAddress, - address _setTokenFactory, - address _auctionLibrary, - uint256 _auctionTimeToPivot, - uint256[2] memory _multipliers, - uint256[2] memory _allocationBounds - ) - public - { - require( - _allocationBounds[1] >= _allocationBounds[0], - "RebalancingTokenManager.constructor: Upper allocation bound must be greater than lower." - ); - - coreAddress = _coreAddress; - - btcPriceFeed = _btcPriceFeedAddress; - ethPriceFeed = _ethPriceFeedAddress; - - btcAddress = _btcAddress; - ethAddress = _ethAddress; - setTokenFactory = _setTokenFactory; - - auctionLibrary = _auctionLibrary; - auctionTimeToPivot = _auctionTimeToPivot; - btcMultiplier = _multipliers[0]; - ethMultiplier = _multipliers[1]; - - maximumLowerThreshold = _allocationBounds[0]; - minimumUpperThreshold = _allocationBounds[1]; - } - - /* ============ External ============ */ - - /* - * When allowed on RebalancingSetToken, anyone can call for a new rebalance proposal - * - * @param _rebalancingSetTokenAddress The address of Rebalancing Set Token to propose new allocation - */ - function propose( - address _rebalancingSetTokenAddress - ) - external - { - // Make sure the rebalancingSetToken is tracked by Core - require( - ICore(coreAddress).validSets(_rebalancingSetTokenAddress), - "RebalanceAuctionModule.bid: Invalid or disabled SetToken address" - ); - - // Create interface to interact with RebalancingSetToken - IRebalancingSetToken rebalancingSetInterface = IRebalancingSetToken(_rebalancingSetTokenAddress); - - ManagerLibrary.validateManagerPropose(rebalancingSetInterface); - - // Get price data - uint256 btcPrice = ManagerLibrary.queryPriceData(btcPriceFeed); - uint256 ethPrice = ManagerLibrary.queryPriceData(ethPriceFeed); - - // Require that allocation has changed sufficiently enough to justify rebalance - uint256 currentSetDollarAmount = checkSufficientAllocationChange( - btcPrice, - ethPrice, - rebalancingSetInterface.currentSet() - ); - - // Create new Set Token that collateralizes Rebalancing Set Token - // address nextSetAddress; - ( - address nextSetAddress, - uint256 nextSetDollarAmount - ) = createNewAllocationSetToken( - btcPrice, - ethPrice - ); - - // Calculate the auctionStartPrice and auctionPivotPrice of rebalance auction using dollar value - // of both the current and nextSet - uint256 auctionStartPrice; - uint256 auctionPivotPrice; - ( - auctionStartPrice, - auctionPivotPrice - ) = ManagerLibrary.calculateAuctionPriceParameters( - currentSetDollarAmount, - nextSetDollarAmount, - AUCTION_LIB_PRICE_DIVISOR, - auctionTimeToPivot - ); - - - // Propose new allocation to Rebalancing Set Token - rebalancingSetInterface.propose( - nextSetAddress, - auctionLibrary, - auctionTimeToPivot, - auctionStartPrice, - auctionPivotPrice - ); - - emit LogManagerProposal( - btcPrice, - ethPrice - ); - } - - /* ============ Internal ============ */ - - /* - * Check there has been a sufficient change in allocation (greater than 2%) and return - * USD value of currentSet. - * - * @param _btcPrice The 18 decimal value of one full BTC - * @param _ethPrice The 18 decimal value of one full ETH - * @param _currentSetAddress The address of the Rebalancing Set Token's currentSet - * @return The currentSet's USD value (in cents) - */ - function checkSufficientAllocationChange( - uint256 _btcPrice, - uint256 _ethPrice, - address _currentSetAddress - ) - private - view - returns (uint256) - { - // Create current set interface - ISetToken currentSetTokenInterface = ISetToken(_currentSetAddress); - - // Get naturalUnit and units of currentSet - uint256 currentSetNaturalUnit = currentSetTokenInterface.naturalUnit(); - uint256[] memory currentSetUnits = currentSetTokenInterface.getUnits(); - - // Calculate wbtc dollar value in currentSet (in cents) - uint256 btcDollarAmount = ManagerLibrary.calculateTokenAllocationAmountUSD( - _btcPrice, - currentSetNaturalUnit, - currentSetUnits[0], - BTC_DECIMALS - ); - - uint256[] memory assetPrices = new uint256[](2); - assetPrices[0] = _btcPrice; - assetPrices[1] = _ethPrice; - - uint256[] memory assetDecimals = new uint256[](2); - assetDecimals[0] = BTC_DECIMALS; - assetDecimals[1] = ETH_DECIMALS; - - uint256 currentSetDollarAmount = ManagerLibrary.calculateSetTokenDollarValue( - assetPrices, - currentSetNaturalUnit, - currentSetUnits, - assetDecimals - ); - - // Require that the allocation has changed more than 2% in order for a rebalance to be called - require( - btcDollarAmount.mul(100).div(currentSetDollarAmount) >= minimumUpperThreshold || - btcDollarAmount.mul(100).div(currentSetDollarAmount) < maximumLowerThreshold, - "RebalancingTokenManager.proposeNewRebalance: Allocation must be further away from 50 percent" - ); - - return currentSetDollarAmount; - } - - /* - * Determine units and naturalUnit of nextSet to propose, calculate auction parameters, and - * create nextSet - * - * @param _btcPrice The 18 decimal value of one full BTC - * @param _ethPrice The 18 decimal value of one full ETH - * @return address The address of nextSet - * @return uint256 The USD value of the nextSet - */ - function createNewAllocationSetToken( - uint256 _btcPrice, - uint256 _ethPrice - ) - private - returns (address, uint256) - { - // Calculate the nextSet units and naturalUnit, determine dollar value of nextSet - uint256 nextSetNaturalUnit; - uint256 nextSetDollarAmount; - uint256[] memory nextSetUnits; - ( - nextSetNaturalUnit, - nextSetDollarAmount, - nextSetUnits - ) = calculateNextSetUnits( - _btcPrice, - _ethPrice - ); - - // Create static components array - address[] memory nextSetComponents = new address[](2); - nextSetComponents[0] = btcAddress; - nextSetComponents[1] = ethAddress; - - // Create the nextSetToken contract that collateralized the Rebalancing Set Token once rebalance - // is finished - address nextSetAddress = ICore(coreAddress).createSet( - setTokenFactory, - nextSetComponents, - nextSetUnits, - nextSetNaturalUnit, - bytes32("BTCETH"), - bytes32("BTCETH"), - "" - ); - - return (nextSetAddress, nextSetDollarAmount); - } - - /* - * Determine units and naturalUnit of nextSet to propose - * - * @param _btcPrice The 18 decimal value of one full BTC - * @param _ethPrice The 18 decimal value of one full ETH - * @return uint256 The naturalUnit of nextSet - * @return uint256 The dollar value of nextSet - * @return uint256[] The units of nextSet - */ - function calculateNextSetUnits( - uint256 _btcPrice, - uint256 _ethPrice - ) - private - view - returns (uint256, uint256, uint256[] memory) - { - // Initialize set token parameters - uint256 nextSetNaturalUnit; - uint256[] memory nextSetUnits = new uint256[](2); - - if (_btcPrice >= _ethPrice) { - // Calculate ethereum nextSetUnits, determined by the following equation: - // (btcPrice / ethPrice) * (10 ** (ethDecimal - btcDecimal)) - uint256 ethUnits = _btcPrice.mul(DECIMAL_DIFF_MULTIPLIER).div(_ethPrice); - - // Create unit array and define natural unit - nextSetUnits[0] = btcMultiplier; - nextSetUnits[1] = ethUnits.mul(ethMultiplier); - nextSetNaturalUnit = 10 ** 10; - } else { - // Calculate btc nextSetUnits as (ethPrice / btcPrice) * 100. 100 is used to add - // precision. The increase in unit amounts is offset by increasing the - // nextSetNaturalUnit by two orders of magnitude so that issuance cost is still - // roughly the same - uint256 ethBtcPrice = _ethPrice.mul(PRICE_PRECISION).div(_btcPrice); - - // Create unit array and define natural unit - nextSetUnits[0] = ethBtcPrice.mul(btcMultiplier); - nextSetUnits[1] = PRICE_PRECISION.mul(DECIMAL_DIFF_MULTIPLIER).mul(ethMultiplier); - nextSetNaturalUnit = 10 ** 12; - } - - uint256[] memory assetPrices = new uint256[](2); - assetPrices[0] = _btcPrice; - assetPrices[1] = _ethPrice; - - uint256[] memory assetDecimals = new uint256[](2); - assetDecimals[0] = BTC_DECIMALS; - assetDecimals[1] = ETH_DECIMALS; - - uint256 nextSetDollarAmount = ManagerLibrary.calculateSetTokenDollarValue( - assetPrices, - nextSetNaturalUnit, - nextSetUnits, - assetDecimals - ); - - return (nextSetNaturalUnit, nextSetDollarAmount, nextSetUnits); - } -} diff --git a/contracts/managers/ETHDaiRebalancingManager.sol b/contracts/managers/ETHDaiRebalancingManager.sol deleted file mode 100644 index 8bcbda2..0000000 --- a/contracts/managers/ETHDaiRebalancingManager.sol +++ /dev/null @@ -1,351 +0,0 @@ -/* - Copyright 2018 Set Labs Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -pragma solidity 0.5.7; -pragma experimental "ABIEncoderV2"; - -import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import { AddressArrayUtils } from "set-protocol-contract-utils/contracts/lib/AddressArrayUtils.sol"; -import { ICore } from "set-protocol-contracts/contracts/core/interfaces/ICore.sol"; -import { IRebalancingSetToken } from "set-protocol-contracts/contracts/core/interfaces/IRebalancingSetToken.sol"; -import { ISetToken } from "set-protocol-contracts/contracts/core/interfaces/ISetToken.sol"; -import { RebalancingLibrary } from "set-protocol-contracts/contracts/core/lib/RebalancingLibrary.sol"; - -import { ManagerLibrary } from "./lib/ManagerLibrary.sol"; - - -/** - * @title ETHDaiRebalancingManager - * @author Set Protocol - * - * Contract used to manage a ETHDai Rebalancing Set Token - */ -contract ETHDaiRebalancingManager { - - using SafeMath for uint256; - using AddressArrayUtils for address[]; - - /* ============ Constants ============ */ - - uint256 constant PRICE_PRECISION = 100; - uint256 constant AUCTION_LIB_PRICE_DIVISOR = 1000; - - // Equal to $1 - uint256 constant DAI_PRICE = 10 ** 18; - uint256 constant DAI_DECIMALS = 18; - uint256 constant ETH_DECIMALS = 18; - - /* ============ State Variables ============ */ - - address public daiAddress; - address public ethAddress; - address public setTokenFactory; - - address public ethPriceFeed; - - address public coreAddress; - - address public auctionLibrary; - uint256 public auctionTimeToPivot; - uint256 public daiMultiplier; - uint256 public ethMultiplier; - - uint256 public maximumLowerThreshold; - uint256 public minimumUpperThreshold; - - /* ============ Events ============ */ - - event LogManagerProposal( - uint256 ethPrice - ); - - /* ============ Constructor ============ */ - - /* - * Rebalancing Token Manager constructor. - * The multipliers are used to calculate the allocation of the set token. Allocation - * is determined by a simple equation: - * daiAllocation = daiMultiplier/(daiMultiplier + ethMultiplier) - * Furthermore the total USD cost of any new Set Token allocation can be found from the - * following equation: - * SetTokenUSDPrice = (daiMultiplier + ethMultiplier)*max(ethPrice, daiPrice) - * - * @param _coreAddress The address of the Core contract - * @param _ethPriceFeedAddress The address of ETH medianizer - * @param _daiAddress The address of the Dai contract - * @param _ethAddress The address of the wrapped ETH contract - * @param _setTokenFactory The address of the SetTokenFactory - * @param _auctionLibrary The address of auction price curve to use in rebalance - * @param _auctionTimeToPivot The amount of time until pivot reached in rebalance - * @param _multipliers Token multipliers used to determine allocation - * @param _allocationBounds Bounds to stop proposal if not enough deviation from expected allocation - * set to be [lowerBound, upperBound] - */ - constructor( - address _coreAddress, - address _ethPriceFeedAddress, - address _daiAddress, - address _ethAddress, - address _setTokenFactory, - address _auctionLibrary, - uint256 _auctionTimeToPivot, - uint256[2] memory _multipliers, - uint256[2] memory _allocationBounds - ) - public - { - require( - _allocationBounds[1] >= _allocationBounds[0], - "RebalancingTokenManager.constructor: Upper allocation bound must be greater than lower." - ); - - coreAddress = _coreAddress; - - ethPriceFeed = _ethPriceFeedAddress; - - daiAddress = _daiAddress; - ethAddress = _ethAddress; - setTokenFactory = _setTokenFactory; - - auctionLibrary = _auctionLibrary; - auctionTimeToPivot = _auctionTimeToPivot; - daiMultiplier = _multipliers[0]; - ethMultiplier = _multipliers[1]; - - maximumLowerThreshold = _allocationBounds[0]; - minimumUpperThreshold = _allocationBounds[1]; - } - - /* ============ External ============ */ - - /* - * When allowed on RebalancingSetToken, anyone can call for a new rebalance proposal - * - * @param _rebalancingSetTokenAddress The address of Rebalancing Set Token to propose new allocation - */ - function propose( - address _rebalancingSetTokenAddress - ) - external - { - // Make sure the rebalancingSetToken is tracked by Core - require( - ICore(coreAddress).validSets(_rebalancingSetTokenAddress), - "RebalanceAuctionModule.bid: Invalid or disabled SetToken address" - ); - - // Create interface to interact with RebalancingSetToken - IRebalancingSetToken rebalancingSetInterface = IRebalancingSetToken(_rebalancingSetTokenAddress); - - ManagerLibrary.validateManagerPropose(rebalancingSetInterface); - - // Get price data - uint256 ethPrice = ManagerLibrary.queryPriceData(ethPriceFeed); - - // Require that allocation has changed sufficiently enough to justify rebalance - uint256 currentSetDollarAmount = checkSufficientAllocationChange( - ethPrice, - rebalancingSetInterface.currentSet() - ); - - // Create new Set Token that collateralizes Rebalancing Set Token - ( - address nextSetAddress, - uint256 nextSetDollarAmount - ) = createNewAllocationSetToken( - ethPrice - ); - - // Calculate the auctionStartPrice and auctionPivotPrice of rebalance auction using dollar value - // of both the current and nextSet - ( - uint256 auctionStartPrice, - uint256 auctionPivotPrice - ) = ManagerLibrary.calculateAuctionPriceParameters( - currentSetDollarAmount, - nextSetDollarAmount, - AUCTION_LIB_PRICE_DIVISOR, - auctionTimeToPivot - ); - - // Propose new allocation to Rebalancing Set Token - rebalancingSetInterface.propose( - nextSetAddress, - auctionLibrary, - auctionTimeToPivot, - auctionStartPrice, - auctionPivotPrice - ); - - emit LogManagerProposal( - ethPrice - ); - } - - /* ============ Internal ============ */ - - /* - * Check there has been a sufficient change in allocation as defined by maximumUpperThreshold - * and minimumLowerThreshold and return USD value of currentSet. - * - * @param _ethPrice The 18 decimal value of one full ETH - * @param _currentSetAddress The address of the Rebalancing Set Token's currentSet - * @return The currentSet's USD value (in cents) - */ - function checkSufficientAllocationChange( - uint256 _ethPrice, - address _currentSetAddress - ) - private - view - returns (uint256) - { - // Create current set interface - ISetToken currentSetTokenInterface = ISetToken(_currentSetAddress); - - // Get naturalUnit and units of currentSet - uint256 currentSetNaturalUnit = currentSetTokenInterface.naturalUnit(); - uint256[] memory currentSetUnits = currentSetTokenInterface.getUnits(); - - // Calculate dai dollar value in currentSet (in cents) - uint256 daiDollarAmount = ManagerLibrary.calculateTokenAllocationAmountUSD( - DAI_PRICE, - currentSetNaturalUnit, - currentSetUnits[0], - DAI_DECIMALS - ); - - uint256[] memory assetPrices = new uint256[](2); - assetPrices[0] = DAI_PRICE; - assetPrices[1] = _ethPrice; - - uint256[] memory assetDecimals = new uint256[](2); - assetDecimals[0] = DAI_DECIMALS; - assetDecimals[1] = ETH_DECIMALS; - - uint256 currentSetDollarAmount = ManagerLibrary.calculateSetTokenDollarValue( - assetPrices, - currentSetNaturalUnit, - currentSetUnits, - assetDecimals - ); - - // Require that the allocation has changed enough to trigger buy or sell - require( - daiDollarAmount.mul(100).div(currentSetDollarAmount) >= minimumUpperThreshold || - daiDollarAmount.mul(100).div(currentSetDollarAmount) < maximumLowerThreshold, - "RebalancingTokenManager.proposeNewRebalance: Allocation must be further away from 50 percent" - ); - - return currentSetDollarAmount; - } - - /* - * Determine units and naturalUnit of nextSet to propose, calculate auction parameters, and - * create nextSet - * - * @param _ethPrice The 18 decimal value of one full ETH - * @return address The address of nextSet - * @return uint256 The value in USD of the next set - */ - function createNewAllocationSetToken( - uint256 _ethPrice - ) - private - returns (address, uint256) - { - // Calculate the nextSet units and naturalUnit, determine dollar value of nextSet - ( - uint256 nextSetNaturalUnit, - uint256 nextSetDollarAmount, - uint256[] memory nextSetUnits - ) = calculateNextSetUnits( - _ethPrice - ); - - // Create static components array - address[] memory nextSetComponents = new address[](2); - nextSetComponents[0] = daiAddress; - nextSetComponents[1] = ethAddress; - - // Create the nextSetToken contract that collateralized the Rebalancing Set Token once rebalance - // is finished - address nextSetAddress = ICore(coreAddress).createSet( - setTokenFactory, - nextSetComponents, - nextSetUnits, - nextSetNaturalUnit, - bytes32("DAIETH"), - bytes32("DAIETH"), - "" - ); - - return (nextSetAddress, nextSetDollarAmount); - } - - /* - * Determine units and naturalUnit of nextSet to propose - * - * @param _ethPrice The 18 decimal value of one full ETH - * @return uint256 The naturalUnit of nextSet - * @return uint256 The dollar value of nextSet - * @return uint256[] The units of nextSet - */ - function calculateNextSetUnits( - uint256 _ethPrice - ) - private - returns (uint256, uint256, uint256[] memory) - { - // Initialize set token parameters - uint256[] memory nextSetUnits = new uint256[](2); - uint256 nextSetNaturalUnit = PRICE_PRECISION; - - if (_ethPrice >= DAI_PRICE) { - // Dai nextSetUnits is equal the USD Ethereum price - uint256 daiUnits = _ethPrice.mul(PRICE_PRECISION).div(DAI_PRICE); - - // Create unit array and define natural unit - nextSetUnits[0] = daiUnits.mul(daiMultiplier); - nextSetUnits[1] = ethMultiplier.mul(PRICE_PRECISION); - } else { - // Calculate dai nextSetUnits as (daiPrice/ethPrice)*100. 100 is used to add - // precision. - uint256 ethDaiPrice = DAI_PRICE.mul(PRICE_PRECISION).div(_ethPrice); - - // Create unit array and define natural unit - nextSetUnits[0] = daiMultiplier.mul(PRICE_PRECISION); - nextSetUnits[1] = ethDaiPrice.mul(ethMultiplier); - } - - uint256[] memory assetPrices = new uint256[](2); - assetPrices[0] = DAI_PRICE; - assetPrices[1] = _ethPrice; - - uint256[] memory assetDecimals = new uint256[](2); - assetDecimals[0] = DAI_DECIMALS; - assetDecimals[1] = ETH_DECIMALS; - - uint256 nextSetDollarAmount = ManagerLibrary.calculateSetTokenDollarValue( - assetPrices, - nextSetNaturalUnit, - nextSetUnits, - assetDecimals - ); - - return (nextSetNaturalUnit, nextSetDollarAmount, nextSetUnits); - } -} diff --git a/contracts/managers/lib/ManagerLibrary.sol b/contracts/managers/lib/ManagerLibrary.sol deleted file mode 100644 index 1e7fcde..0000000 --- a/contracts/managers/lib/ManagerLibrary.sol +++ /dev/null @@ -1,194 +0,0 @@ -/* - Copyright 2018 Set Labs Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -pragma solidity 0.5.7; -pragma experimental "ABIEncoderV2"; - -import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import { IRebalancingSetToken } from "set-protocol-contracts/contracts/core/interfaces/IRebalancingSetToken.sol"; -import { RebalancingLibrary } from "set-protocol-contracts/contracts/core/lib/RebalancingLibrary.sol"; -import { IMedian } from "set-protocol-oracles/contracts/external/DappHub/interfaces/IMedian.sol"; - - -/** - * @title ManagerLibrary - * @author Set Protocol - * - * The ManagerLibrary contains functions for helping Managers create proposals - * - */ -library ManagerLibrary { - using SafeMath for uint256; - - /* - * Validates whether the Rebalancing Set is in the correct state and sufficient time has elapsed. - * - * @param _rebalancingSetInterface Instance of the Rebalancing Set Token - */ - function validateManagerPropose( - IRebalancingSetToken _rebalancingSetInterface - ) - internal - { - // Require that enough time has passed from last rebalance - uint256 lastRebalanceTimestamp = _rebalancingSetInterface.lastRebalanceTimestamp(); - uint256 rebalanceInterval = _rebalancingSetInterface.rebalanceInterval(); - require( - block.timestamp >= lastRebalanceTimestamp.add(rebalanceInterval), - "ManagerLibrary.proposeNewRebalance: Rebalance interval not elapsed" - ); - - // Require that Rebalancing Set Token is in Default state, won't allow for re-proposals - // because malicious actor could prevent token from ever rebalancing - require( - _rebalancingSetInterface.rebalanceState() == RebalancingLibrary.State.Default, - "ManagerLibrary.proposeNewRebalance: State must be in Default" - ); - } - - /* - * Calculates the auction price parameters, utilizing targetting 1% slippage every 30 minutes - * and auctions beginning +50% and -50% relative to fair value. - * - * @param _currentSetDollarAmount The 18 decimal value of one currenSet - * @param _nextSetDollarAmount The 18 decimal value of one nextSet - * @param _auctionLibraryPriceDivisor The auction library price divisor - * @param _auctionTimeToPivot The auction time to pivot - * @return uint256 The auctionStartPrice for rebalance auction - * @return uint256 The auctionPivotPrice for rebalance auction - */ - function calculateAuctionPriceParameters( - uint256 _currentSetDollarAmount, - uint256 _nextSetDollarAmount, - uint256 _auctionLibraryPriceDivisor, - uint256 _auctionTimeToPivot - ) - internal - view - returns (uint256, uint256) - { - // Determine fair value of nextSet/currentSet and put in terms of auction library price divisor - uint256 fairValue = _nextSetDollarAmount.mul(_auctionLibraryPriceDivisor).div(_currentSetDollarAmount); - // Calculate how much one percent slippage from fair value is - uint256 onePercentSlippage = fairValue.div(100); - - // Calculate how many 30 minute periods are in auctionTimeToPivot - uint256 THIRTY_MINUTES_IN_SECONDS = 1800; - uint256 thirtyMinutePeriods = _auctionTimeToPivot.div(THIRTY_MINUTES_IN_SECONDS); - // Since we are targeting a 1% slippage every 30 minutes the price range is defined as - // the price of a 1% move multiplied by the amount of 30 second intervals in the auctionTimeToPivot - // This value is then divided by two to get half the price range - uint256 halfPriceRange = thirtyMinutePeriods.mul(onePercentSlippage).div(2); - - // Auction start price is fair value minus half price range to center the auction at fair value - uint256 auctionStartPrice = fairValue.sub(halfPriceRange); - // Auction pivot price is fair value plus half price range to center the auction at fair value - uint256 auctionPivotPrice = fairValue.add(halfPriceRange); - - return (auctionStartPrice, auctionPivotPrice); - } - - /* - * Query the Medianizer price feeds for a value that is returned as a Uint. Prices - * have 18 decimals. - * - * @param _priceFeedAddress Address of the medianizer price feed - * @return uint256 The price from the price feed with 18 decimals - */ - function queryPriceData( - address _priceFeedAddress - ) - internal - view - returns (uint256) - { - // Get prices from oracles - bytes32 priceInBytes = IMedian(_priceFeedAddress).read(); - - return uint256(priceInBytes); - } - - /* - * Calculates the USD Value of a Set Token - by taking the individual token prices, units - * and decimals. - * - * @param _tokenPrices The 18 decimal values of components - * @param _naturalUnit The naturalUnit of the set being component belongs to - * @param _units The units of the components in the Set - * @param _tokenDecimals The components decimal values - * @return uint256 The USD value of the Set (in cents) - */ - function calculateSetTokenDollarValue( - uint256[] memory _tokenPrices, - uint256 _naturalUnit, - uint256[] memory _units, - uint256[] memory _tokenDecimals - ) - internal - view - returns (uint256) - { - uint256 setDollarAmount = 0; - - // Loop through assets - for (uint256 i = 0; i < _tokenPrices.length; i++) { - uint256 tokenDollarValue = calculateTokenAllocationAmountUSD( - _tokenPrices[i], - _naturalUnit, - _units[i], - _tokenDecimals[i] - ); - - setDollarAmount = setDollarAmount.add(tokenDollarValue); - } - - return setDollarAmount; - } - - /* - * Get USD value of one component in a Set - * - * @param _tokenPrice The 18 decimal value of one full token - * @param _naturalUnit The naturalUnit of the set being component belongs to - * @param _unit The unit of the component in the set - * @param _tokenDecimals The component token's decimal value - * @return uint256 The USD value of the component's allocation in the Set (in cents) - */ - function calculateTokenAllocationAmountUSD( - uint256 _tokenPrice, - uint256 _naturalUnit, - uint256 _unit, - uint256 _tokenDecimals - ) - internal - view - returns (uint256) - { - uint256 SET_TOKEN_DECIMALS = 18; - uint256 VALUE_TO_CENTS_CONVERSION = 10 ** 16; - - // Calculate the amount of component base units are in one full set token - uint256 componentUnitsInFullToken = _unit - .mul(10 ** SET_TOKEN_DECIMALS) - .div(_naturalUnit); - - // Return value of component token in one full set token, divide by 10 ** 16 to turn tokenPrice into cents - return _tokenPrice - .mul(componentUnitsInFullToken) - .div(10 ** _tokenDecimals) - .div(VALUE_TO_CENTS_CONVERSION); - } -} diff --git a/contracts/mocks/managers/ManagerLibraryMock.sol b/contracts/mocks/managers/ManagerLibraryMock.sol deleted file mode 100644 index 21d1a38..0000000 --- a/contracts/mocks/managers/ManagerLibraryMock.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity 0.5.7; -pragma experimental "ABIEncoderV2"; - -import { ManagerLibrary } from "../../managers/lib/ManagerLibrary.sol"; - -// Mock contract implementation of ManagerLibrary functions -contract ManagerLibraryMock { - function calculateAuctionPriceParameters( - uint256 _currentSetDollarAmount, - uint256 _nextSetDollarAmount, - uint256 _auctionLibraryPriceDivisor, - uint256 _auctionTimeToPivot - ) - external - returns (uint256, uint256) - { - return ManagerLibrary.calculateAuctionPriceParameters( - _currentSetDollarAmount, - _nextSetDollarAmount, - _auctionLibraryPriceDivisor, - _auctionTimeToPivot - ); - } -} diff --git a/test/contracts/managers/btcDaiRebalancingManager.spec.ts b/test/contracts/managers/btcDaiRebalancingManager.spec.ts deleted file mode 100644 index 58fb47f..0000000 --- a/test/contracts/managers/btcDaiRebalancingManager.spec.ts +++ /dev/null @@ -1,773 +0,0 @@ -require('module-alias/register'); - -import * as _ from 'lodash'; -import * as ABIDecoder from 'abi-decoder'; -import * as chai from 'chai'; -import * as setProtocolUtils from 'set-protocol-utils'; -import { Address } from 'set-protocol-utils'; -import { BigNumber } from 'bignumber.js'; - -import ChaiSetup from '@utils/chaiSetup'; -import { BigNumberSetup } from '@utils/bigNumberSetup'; -import { - CoreContract, - LinearAuctionPriceCurveContract, - SetTokenContract, - RebalanceAuctionModuleContract, - RebalancingSetTokenContract, - RebalancingSetTokenFactoryContract, - SetTokenFactoryContract, - StandardTokenMockContract, - TransferProxyContract, -} from 'set-protocol-contracts'; -import { - MedianContract, -} from 'set-protocol-oracles'; -import { - BTCDaiRebalancingManagerContract, -} from '@utils/contracts'; -import { Blockchain } from 'set-protocol-contracts'; -import { ether } from '@utils/units'; -import { - DEFAULT_GAS, - ONE_DAY_IN_SECONDS, -} from '@utils/constants'; -import { expectRevertError } from '@utils/tokenAssertions'; -import { getWeb3 } from '@utils/web3Helper'; -import { LogManagerProposal } from '@utils/contract_logs/btcDaiRebalancingManager'; - -import { ProtocolHelper } from '@utils/helpers/protocolHelper'; -import { ERC20Helper } from '@utils/helpers/erc20Helper'; -import { OracleHelper } from 'set-protocol-oracles'; -import { ManagerHelper } from '@utils/helpers/managerHelper'; - -const Core = require('set-protocol-contracts/dist/artifacts/ts/Core').Core; -const RebalancingSetToken = require('set-protocol-contracts/dist/artifacts/ts/RebalancingSetToken').RebalancingSetToken; - -BigNumberSetup.configure(); -ChaiSetup.configure(); -const web3 = getWeb3(); -const BTCDaiRebalancingManager = artifacts.require('BTCDaiRebalancingManager'); -const { expect } = chai; -const blockchain = new Blockchain(web3); -const { SetProtocolTestUtils: SetTestUtils } = setProtocolUtils; -const setTestUtils = new SetTestUtils(web3); - -contract('BTCDaiRebalancingManager', accounts => { - const [ - deployerAccount, - otherAccount, - ] = accounts; - - let rebalancingSetToken: RebalancingSetTokenContract; - - let core: CoreContract; - let transferProxy: TransferProxyContract; - let rebalanceAuctionModule: RebalanceAuctionModuleContract; - let factory: SetTokenFactoryContract; - let rebalancingFactory: RebalancingSetTokenFactoryContract; - let linearAuctionPriceCurve: LinearAuctionPriceCurveContract; - let btcDaiRebalancingManager: BTCDaiRebalancingManagerContract; - let btcMedianizer: MedianContract; - let daiMock: StandardTokenMockContract; - let wrappedBTC: StandardTokenMockContract; - - const protocolHelper = new ProtocolHelper(deployerAccount); - const erc20Helper = new ERC20Helper(deployerAccount); - const managerHelper = new ManagerHelper(deployerAccount); - const oracleHelper = new OracleHelper(deployerAccount); - - before(async () => { - ABIDecoder.addABI(Core.abi); - ABIDecoder.addABI(RebalancingSetToken.abi); - ABIDecoder.addABI(BTCDaiRebalancingManager.abi); - }); - - after(async () => { - ABIDecoder.removeABI(Core.abi); - ABIDecoder.removeABI(RebalancingSetToken.abi); - ABIDecoder.removeABI(BTCDaiRebalancingManager.abi); - }); - - beforeEach(async () => { - blockchain.saveSnapshotAsync(); - - transferProxy = await protocolHelper.getDeployedTransferProxyAsync(); - core = await protocolHelper.getDeployedCoreAsync(); - rebalanceAuctionModule = await protocolHelper.getDeployedRebalanceAuctionModuleAsync(); - - factory = await protocolHelper.getDeployedSetTokenFactoryAsync(); - rebalancingFactory = await protocolHelper.getDeployedRebalancingSetTokenFactoryAsync(); - linearAuctionPriceCurve = await protocolHelper.getDeployedLinearAuctionPriceCurveAsync(); - - btcMedianizer = await protocolHelper.getDeployedWBTCMedianizerAsync(); - await oracleHelper.addPriceFeedOwnerToMedianizer(btcMedianizer, deployerAccount); - - daiMock = await protocolHelper.getDeployedDAIAsync(); - wrappedBTC = await protocolHelper.getDeployedWBTCAsync(); - await erc20Helper.approveTransfersAsync( - [daiMock, wrappedBTC], - transferProxy.address - ); - }); - - afterEach(async () => { - blockchain.revertAsync(); - }); - - describe('#constructor', async () => { - let subjectCoreAddress: Address; - let subjectBtcPriceFeedAddress: Address; - let subjectDaiAddress: Address; - let subjectBtcAddress: Address; - let subjectSetTokenFactory: Address; - let subjectAuctionLibrary: Address; - let subjectAuctionTimeToPivot: BigNumber; - let subjectDaiMultiplier: BigNumber; - let subjectBtcMultiplier: BigNumber; - let subjectLowerAllocationBound: BigNumber; - let subjectUpperAllocationBound: BigNumber; - - beforeEach(async () => { - subjectCoreAddress = core.address; - subjectBtcPriceFeedAddress = btcMedianizer.address; - subjectDaiAddress = daiMock.address; - subjectBtcAddress = wrappedBTC.address; - subjectSetTokenFactory = factory.address; - subjectAuctionLibrary = linearAuctionPriceCurve.address; - subjectAuctionTimeToPivot = ONE_DAY_IN_SECONDS; - subjectDaiMultiplier = new BigNumber(1); - subjectBtcMultiplier = new BigNumber(1); - subjectLowerAllocationBound = new BigNumber(48); - subjectUpperAllocationBound = new BigNumber(52); - }); - - async function subject(): Promise { - return managerHelper.deployBTCDaiRebalancingManagerAsync( - subjectCoreAddress, - subjectBtcPriceFeedAddress, - subjectDaiAddress, - subjectBtcAddress, - subjectSetTokenFactory, - subjectAuctionLibrary, - subjectAuctionTimeToPivot, - [subjectDaiMultiplier, subjectBtcMultiplier], - [subjectLowerAllocationBound, subjectUpperAllocationBound] - ); - } - - it('sets dai address', async () => { - const rebalancingManager = await subject(); - - const actualDaiAddress = await rebalancingManager.daiAddress.callAsync(); - - expect(actualDaiAddress).to.be.equal(subjectDaiAddress); - }); - - it('sets wbtc address', async () => { - const rebalancingManager = await subject(); - - const actualBtcAddress = await rebalancingManager.btcAddress.callAsync(); - - expect(actualBtcAddress).to.be.equal(subjectBtcAddress); - }); - - it('sets set token factory', async () => { - const rebalancingManager = await subject(); - - const actualSetTokenFactory = await rebalancingManager.setTokenFactory.callAsync(); - - expect(actualSetTokenFactory).to.be.equal(subjectSetTokenFactory); - }); - - it('sets auction library', async () => { - const rebalancingManager = await subject(); - - const actualAuctionLibrary = await rebalancingManager.auctionLibrary.callAsync(); - - expect(actualAuctionLibrary).to.be.equal(subjectAuctionLibrary); - }); - - it('sets correct auctionTimeToPivot', async () => { - const rebalancingManager = await subject(); - - const actualAuctionTimeToPivot = await rebalancingManager.auctionTimeToPivot.callAsync(); - - expect(actualAuctionTimeToPivot).to.be.bignumber.eql(subjectAuctionTimeToPivot); - }); - - it('sets correct daiMultiplier', async () => { - const rebalancingManager = await subject(); - - const actualDaiMultiplier = await rebalancingManager.daiMultiplier.callAsync(); - - expect(actualDaiMultiplier).to.be.bignumber.eql(subjectDaiMultiplier); - }); - - it('sets correct btcMultiplier', async () => { - const rebalancingManager = await subject(); - - const actualBtcMultiplier = await rebalancingManager.btcMultiplier.callAsync(); - - expect(actualBtcMultiplier).to.be.bignumber.eql(subjectBtcMultiplier); - }); - - it('sets correct btcPriceFeed', async () => { - const rebalancingManager = await subject(); - - const btcPriceFeed = await rebalancingManager.btcPriceFeed.callAsync(); - - expect(btcPriceFeed).to.be.bignumber.eql(subjectBtcPriceFeedAddress); - }); - - it('sets correct maximumLowerThreshold', async () => { - const rebalancingManager = await subject(); - - const maximumLowerThreshold = await rebalancingManager.maximumLowerThreshold.callAsync(); - - expect(maximumLowerThreshold).to.be.bignumber.eql(subjectLowerAllocationBound); - }); - - it('sets correct minimumUpperThreshold', async () => { - const rebalancingManager = await subject(); - - const minimumUpperThreshold = await rebalancingManager.minimumUpperThreshold.callAsync(); - - expect(minimumUpperThreshold).to.be.bignumber.eql(subjectUpperAllocationBound); - }); - - describe('when lower allocation bound is greater than upper', async () => { - beforeEach(async () => { - subjectLowerAllocationBound = new BigNumber(52); - subjectUpperAllocationBound = new BigNumber(48); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); - - describe('#propose', async () => { - let subjectRebalancingSetToken: Address; - let subjectCaller: Address; - let subjectTimeFastForward: BigNumber; - - let proposalPeriod: BigNumber; - let daiMultiplier: BigNumber; - let btcMultiplier: BigNumber; - let lowerAllocationBound: BigNumber; - let upperAllocationBound: BigNumber; - let btcPrice: BigNumber; - let daiUnit: BigNumber; - - const DAI_PRICE: BigNumber = new BigNumber(10 ** 18); - const DAI_DECIMALS: BigNumber = new BigNumber(10 ** 18); - const BTC_DECIMALS: BigNumber = new BigNumber(10 ** 8); - const PRICE_PRECISION: BigNumber = new BigNumber(1); - - let initialAllocationToken: SetTokenContract; - - before(async () => { - daiMultiplier = new BigNumber(1); - btcMultiplier = new BigNumber(1); - - btcPrice = new BigNumber(3200 * 10 ** 18); - daiUnit = new BigNumber(2800); - }); - - beforeEach(async () => { - lowerAllocationBound = new BigNumber(48); - upperAllocationBound = new BigNumber(52); - btcDaiRebalancingManager = await managerHelper.deployBTCDaiRebalancingManagerAsync( - core.address, - btcMedianizer.address, - daiMock.address, - wrappedBTC.address, - factory.address, - linearAuctionPriceCurve.address, - ONE_DAY_IN_SECONDS, - [daiMultiplier, btcMultiplier], - [lowerAllocationBound, upperAllocationBound] - ); - - const decimalDifference = DAI_DECIMALS.div(BTC_DECIMALS); - initialAllocationToken = await protocolHelper.createSetTokenAsync( - core, - factory.address, - [daiMock.address, wrappedBTC.address], - [daiUnit.mul(daiMultiplier).mul(decimalDifference).mul(PRICE_PRECISION), btcMultiplier.mul(PRICE_PRECISION)], - PRICE_PRECISION.mul(decimalDifference), - ); - - proposalPeriod = ONE_DAY_IN_SECONDS; - rebalancingSetToken = await protocolHelper.createDefaultRebalancingSetTokenAsync( - core, - rebalancingFactory.address, - btcDaiRebalancingManager.address, - initialAllocationToken.address, - proposalPeriod - ); - - subjectRebalancingSetToken = rebalancingSetToken.address; - subjectCaller = otherAccount; - subjectTimeFastForward = ONE_DAY_IN_SECONDS.add(1); - - await oracleHelper.updateMedianizerPriceAsync( - btcMedianizer, - btcPrice, - SetTestUtils.generateTimestamp(1000), - ); - - // Issue currentSetToken - await core.issue.sendTransactionAsync( - initialAllocationToken.address, - ether(9), - {from: deployerAccount, gas: DEFAULT_GAS}, - ); - await erc20Helper.approveTransfersAsync([initialAllocationToken], transferProxy.address); - - // Use issued currentSetToken to issue rebalancingSetToken - await core.issue.sendTransactionAsync( - rebalancingSetToken.address, - ether(7), - { from: deployerAccount, gas: DEFAULT_GAS }); - }); - - async function subject(): Promise { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - return btcDaiRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - { from: subjectCaller, gas: DEFAULT_GAS} - ); - } - - describe('when proposeNewRebalance is called from the Default state', async () => { - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS.div(BTC_DECIMALS), - PRICE_PRECISION, - ); - - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS.div(BTC_DECIMALS), - PRICE_PRECISION, - ); - - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - - it('updates new set token to the correct components', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetComponents = await nextSet.getComponents.callAsync(); - - const expectedNextSetComponents = [daiMock.address, wrappedBTC.address]; - expect(JSON.stringify(nextSetComponents)).to.be.eql(JSON.stringify(expectedNextSetComponents)); - }); - - it('updates to the new auction library correctly', async () => { - await subject(); - - const newAuctionLibrary = await rebalancingSetToken.auctionLibrary.callAsync(); - expect(newAuctionLibrary).to.equal(linearAuctionPriceCurve.address); - }); - - it('updates the time to pivot correctly', async () => { - await subject(); - - const auctionPriceParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionTimeToPivot = auctionPriceParameters[1]; - expect(newAuctionTimeToPivot).to.be.bignumber.equal(ONE_DAY_IN_SECONDS); - }); - - it('updates the auction start price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedGeneralAuctionParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS, - BTC_DECIMALS, - PRICE_PRECISION, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[2]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionStartPrice']); - }); - - it('updates the auction pivot price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedGeneralAuctionParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS, - BTC_DECIMALS, - PRICE_PRECISION, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[3]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionPivotPrice']); - }); - - it('emits correct LogProposal event', async () => { - const txHash = await subject(); - - const formattedLogs = await setTestUtils.getLogsFromTxHash(txHash); - const expectedLogs = LogManagerProposal( - btcPrice, - btcDaiRebalancingManager.address - ); - - await SetTestUtils.assertLogEquivalence(formattedLogs, expectedLogs); - }); - - describe('when the new allocation is 75/25', async () => { - before(async () => { - daiMultiplier = new BigNumber(3); - btcMultiplier = new BigNumber(1); - }); - - after(async () => { - daiMultiplier = new BigNumber(1); - btcMultiplier = new BigNumber(1); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS.div(BTC_DECIMALS), - PRICE_PRECISION, - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS.div(BTC_DECIMALS), - PRICE_PRECISION, - ); - - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - }); - - describe('but the price of Dai is greater than btc', async () => { - before(async () => { - btcPrice = new BigNumber(7 * 10 ** 17); - daiUnit = new BigNumber(1); - }); - - after(async () => { - btcPrice = new BigNumber(3200 * 10 ** 18); - daiUnit = new BigNumber(2800); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS.div(BTC_DECIMALS), - PRICE_PRECISION, - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS.div(BTC_DECIMALS), - PRICE_PRECISION, - ); - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - - it('updates the auction start price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedGeneralAuctionParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS, - BTC_DECIMALS, - PRICE_PRECISION, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[2]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionStartPrice']); - }); - - it('updates the auction pivot price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedGeneralAuctionParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS, - BTC_DECIMALS, - PRICE_PRECISION, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[3]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionPivotPrice']); - }); - - describe('but the new allocation is 75/25', async () => { - before(async () => { - daiMultiplier = new BigNumber(3); - btcMultiplier = new BigNumber(1); - }); - - after(async () => { - daiMultiplier = new BigNumber(1); - btcMultiplier = new BigNumber(1); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS.div(BTC_DECIMALS), - PRICE_PRECISION, - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - btcPrice, - daiMultiplier, - btcMultiplier, - DAI_DECIMALS.div(BTC_DECIMALS), - PRICE_PRECISION, - ); - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - }); - }); - - describe('but the passed rebalancing set address was not created by Core', async () => { - beforeEach(async () => { - const unTrackedSetToken = await protocolHelper.createDefaultRebalancingSetTokenAsync( - core, - rebalancingFactory.address, - btcDaiRebalancingManager.address, - initialAllocationToken.address, - proposalPeriod, - ); - - await core.disableSet.sendTransactionAsync( - unTrackedSetToken.address, - { from: deployerAccount, gas: DEFAULT_GAS }, - ); - - subjectRebalancingSetToken = unTrackedSetToken.address; - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('but the computed token allocation is too close to the bounds', async () => { - before(async () => { - btcPrice = new BigNumber(2750 * 10 ** 18); - }); - - after(async () => { - btcPrice = new BigNumber(3200 * 10 ** 18); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('but the rebalance interval has not elapsed', async () => { - beforeEach(async () => { - subjectTimeFastForward = ONE_DAY_IN_SECONDS.sub(10); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); - - describe('when proposeNewRebalance is called from Proposal state', async () => { - let timeJump: BigNumber; - - beforeEach(async () => { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await btcDaiRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - timeJump = new BigNumber(1000); - await blockchain.increaseTimeAsync(timeJump); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('when proposeNewRebalance is called from Rebalance state', async () => { - beforeEach(async () => { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await btcDaiRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - // Transition to rebalance - await blockchain.increaseTimeAsync(ONE_DAY_IN_SECONDS.add(1)); - await rebalancingSetToken.startRebalance.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS } - ); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('when proposeNewRebalance is called from Drawdown State', async () => { - beforeEach(async () => { - // propose rebalance - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await btcDaiRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - // Transition to rebalance - await blockchain.increaseTimeAsync(ONE_DAY_IN_SECONDS.add(1)); - - await rebalancingSetToken.startRebalance.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS } - ); - - const defaultTimeToPivot = new BigNumber(100000); - await blockchain.increaseTimeAsync(defaultTimeToPivot.add(1)); - - const biddingParameters = await rebalancingSetToken.biddingParameters.callAsync(); - const minimumBid = biddingParameters[0]; - await rebalanceAuctionModule.bid.sendTransactionAsync( - rebalancingSetToken.address, - minimumBid, - false, - { from: deployerAccount, gas: DEFAULT_GAS } - ); - - await rebalancingSetToken.endFailedAuction.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS} - ); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); -}); diff --git a/test/contracts/managers/btcEthRebalancingManager.spec.ts b/test/contracts/managers/btcEthRebalancingManager.spec.ts deleted file mode 100644 index c3c29c9..0000000 --- a/test/contracts/managers/btcEthRebalancingManager.spec.ts +++ /dev/null @@ -1,762 +0,0 @@ -require('module-alias/register'); - -import * as _ from 'lodash'; -import * as ABIDecoder from 'abi-decoder'; -import * as chai from 'chai'; -import * as setProtocolUtils from 'set-protocol-utils'; -import { Address } from 'set-protocol-utils'; -import { BigNumber } from 'bignumber.js'; - -import ChaiSetup from '@utils/chaiSetup'; -import { BigNumberSetup } from '@utils/bigNumberSetup'; -import { - CoreContract, - LinearAuctionPriceCurveContract, - SetTokenContract, - RebalanceAuctionModuleContract, - RebalancingSetTokenContract, - RebalancingSetTokenFactoryContract, - SetTokenFactoryContract, - StandardTokenMockContract, - TransferProxyContract, - WethMockContract, -} from 'set-protocol-contracts'; -import { - MedianContract, -} from 'set-protocol-oracles'; -import { - BTCETHRebalancingManagerContract, -} from '@utils/contracts'; - -import { Blockchain } from 'set-protocol-contracts'; -import { ether } from '@utils/units'; -import { - DEFAULT_GAS, - ONE_DAY_IN_SECONDS -} from '@utils/constants'; -import { expectRevertError } from '@utils/tokenAssertions'; -import { getDeployedAddress } from '@utils/snapshotUtils'; -import { getWeb3 } from '@utils/web3Helper'; -import { LogManagerProposal } from '@utils/contract_logs/btcEthRebalancingManager'; - -import { ProtocolHelper } from '@utils/helpers/protocolHelper'; -import { ERC20Helper } from '@utils/helpers/erc20Helper'; -import { OracleHelper } from 'set-protocol-oracles'; -import { ManagerHelper } from '@utils/helpers/managerHelper'; - -const Core = require('set-protocol-contracts/dist/artifacts/ts/Core').Core; - -BigNumberSetup.configure(); -ChaiSetup.configure(); -const web3 = getWeb3(); -const BTCETHRebalancingManager = artifacts.require('BTCETHRebalancingManager'); -const { expect } = chai; -const blockchain = new Blockchain(web3); -const { SetProtocolTestUtils: SetTestUtils } = setProtocolUtils; -const setTestUtils = new SetTestUtils(web3); - -contract('BTCETHRebalancingManager', accounts => { - const [ - deployerAccount, - otherAccount, - ] = accounts; - - let rebalancingSetToken: RebalancingSetTokenContract; - - let core: CoreContract; - let transferProxy: TransferProxyContract; - let rebalanceAuctionModule: RebalanceAuctionModuleContract; - let factory: SetTokenFactoryContract; - let rebalancingFactory: RebalancingSetTokenFactoryContract; - let linearAuctionPriceCurve: LinearAuctionPriceCurveContract; - let btcethRebalancingManager: BTCETHRebalancingManagerContract; - let btcMedianizer: MedianContract; - let ethMedianizer: MedianContract; - let wrappedBTC: StandardTokenMockContract; - let wrappedETH: WethMockContract; - - const protocolHelper = new ProtocolHelper(deployerAccount); - const erc20Helper = new ERC20Helper(deployerAccount); - const managerHelper = new ManagerHelper(deployerAccount); - const oracleHelper = new OracleHelper(deployerAccount); - - before(async () => { - ABIDecoder.addABI(Core.abi); - ABIDecoder.addABI(BTCETHRebalancingManager.abi); - }); - - after(async () => { - ABIDecoder.removeABI(Core.abi); - ABIDecoder.removeABI(BTCETHRebalancingManager.abi); - }); - - beforeEach(async () => { - blockchain.saveSnapshotAsync(); - - core = await protocolHelper.getDeployedCoreAsync(); - transferProxy = await protocolHelper.getDeployedTransferProxyAsync(); - wrappedBTC = await protocolHelper.getDeployedWBTCAsync(); - wrappedETH = await protocolHelper.getDeployedWETHAsync(); - factory = await protocolHelper.getDeployedSetTokenFactoryAsync(); - rebalancingFactory = await protocolHelper.getDeployedRebalancingSetTokenFactoryAsync(); - rebalanceAuctionModule = await protocolHelper.getDeployedRebalanceAuctionModuleAsync(); - - linearAuctionPriceCurve = await protocolHelper.getDeployedLinearAuctionPriceCurveAsync(); - - ethMedianizer = await protocolHelper.getDeployedWETHMedianizerAsync(); - btcMedianizer = await protocolHelper.getDeployedWBTCMedianizerAsync(); - }); - - afterEach(async () => { - blockchain.revertAsync(); - }); - - describe('#constructor', async () => { - let subjectCoreAddress: Address; - let subjectBtcPriceFeedAddress: Address; - let subjectEthPriceFeedAddress: Address; - let subjectBtcAddress: Address; - let subjectEthAddress: Address; - let subjectSetTokenFactory: Address; - let subjectAuctionLibrary: Address; - let subjectAuctionTimeToPivot: BigNumber; - let subjectBtcMultiplier: BigNumber; - let subjectEthMultiplier: BigNumber; - let subjectLowerAllocationBound: BigNumber; - let subjectUpperAllocationBound: BigNumber; - - beforeEach(async () => { - subjectCoreAddress = getDeployedAddress(Core.contractName); - subjectBtcPriceFeedAddress = getDeployedAddress('WBTC_MEDIANIZER'); - subjectEthPriceFeedAddress = getDeployedAddress('WETH_MEDIANIZER'); - subjectBtcAddress = getDeployedAddress('WBTC'); - subjectEthAddress = getDeployedAddress('WETH'); - subjectSetTokenFactory = getDeployedAddress('SetTokenFactory'); - subjectAuctionLibrary = getDeployedAddress('LinearAuctionPriceCurve'); - subjectAuctionTimeToPivot = ONE_DAY_IN_SECONDS; - subjectBtcMultiplier = new BigNumber(1); - subjectEthMultiplier = new BigNumber(1); - subjectLowerAllocationBound = new BigNumber(48); - subjectUpperAllocationBound = new BigNumber(52); - }); - - async function subject(): Promise { - return managerHelper.deployBTCETHRebalancingManagerAsync( - subjectCoreAddress, - subjectBtcPriceFeedAddress, - subjectEthPriceFeedAddress, - subjectBtcAddress, - subjectEthAddress, - subjectSetTokenFactory, - subjectAuctionLibrary, - subjectAuctionTimeToPivot, - [subjectBtcMultiplier, subjectEthMultiplier], - [subjectLowerAllocationBound, subjectUpperAllocationBound] - ); - } - - it('sets wbtc address', async () => { - const rebalancingManager = await subject(); - - const actualBtcAddress = await rebalancingManager.btcAddress.callAsync(); - - expect(actualBtcAddress).to.be.equal(subjectBtcAddress); - }); - - it('sets weth address', async () => { - const rebalancingManager = await subject(); - - const actualEthAddress = await rebalancingManager.ethAddress.callAsync(); - - expect(actualEthAddress).to.be.equal(subjectEthAddress); - }); - - it('sets set token factory', async () => { - const rebalancingManager = await subject(); - - const actualSetTokenFactory = await rebalancingManager.setTokenFactory.callAsync(); - - expect(actualSetTokenFactory).to.be.equal(subjectSetTokenFactory); - }); - - it('sets auction library', async () => { - const rebalancingManager = await subject(); - - const actualAuctionLibrary = await rebalancingManager.auctionLibrary.callAsync(); - - expect(actualAuctionLibrary).to.be.equal(subjectAuctionLibrary); - }); - - it('sets correct auctionTimeToPivot', async () => { - const rebalancingManager = await subject(); - - const actualAuctionTimeToPivot = await rebalancingManager.auctionTimeToPivot.callAsync(); - - expect(actualAuctionTimeToPivot).to.be.bignumber.eql(subjectAuctionTimeToPivot); - }); - - it('sets correct btcMultiplier', async () => { - const rebalancingManager = await subject(); - - const actualBtcMultiplier = await rebalancingManager.btcMultiplier.callAsync(); - - expect(actualBtcMultiplier).to.be.bignumber.eql(subjectBtcMultiplier); - }); - - it('sets correct ethMultiplier', async () => { - const rebalancingManager = await subject(); - - const actualEthMultiplier = await rebalancingManager.ethMultiplier.callAsync(); - - expect(actualEthMultiplier).to.be.bignumber.eql(subjectEthMultiplier); - }); - - it('sets correct btcPriceFeed', async () => { - const rebalancingManager = await subject(); - - const btcPriceFeed = await rebalancingManager.btcPriceFeed.callAsync(); - - expect(btcPriceFeed).to.be.bignumber.eql(subjectBtcPriceFeedAddress); - }); - - it('sets correct ethPriceFeed', async () => { - const rebalancingManager = await subject(); - - const ethPriceFeed = await rebalancingManager.ethPriceFeed.callAsync(); - - expect(ethPriceFeed).to.be.bignumber.eql(subjectEthPriceFeedAddress); - }); - - it('sets correct maximumLowerThreshold', async () => { - const rebalancingManager = await subject(); - - const maximumLowerThreshold = await rebalancingManager.maximumLowerThreshold.callAsync(); - - expect(maximumLowerThreshold).to.be.bignumber.eql(subjectLowerAllocationBound); - }); - - it('sets correct minimumUpperThreshold', async () => { - const rebalancingManager = await subject(); - - const minimumUpperThreshold = await rebalancingManager.minimumUpperThreshold.callAsync(); - - expect(minimumUpperThreshold).to.be.bignumber.eql(subjectUpperAllocationBound); - }); - - describe('when lower allocation bound is greater than upper', async () => { - beforeEach(async () => { - subjectLowerAllocationBound = new BigNumber(52); - subjectUpperAllocationBound = new BigNumber(48); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); - - describe('#propose', async () => { - let subjectRebalancingSetToken: Address; - let subjectCaller: Address; - let subjectTimeFastForward: BigNumber; - - let proposalPeriod: BigNumber; - let btcMultiplier: BigNumber; - let ethMultiplier: BigNumber; - let lowerAllocationBound: BigNumber; - let upperAllocationBound: BigNumber; - let btcPrice: BigNumber; - let ethPrice: BigNumber; - let ethUnit: BigNumber; - - let initialAllocationToken: SetTokenContract; - - before(async () => { - btcMultiplier = new BigNumber(1); - ethMultiplier = new BigNumber(1); - - btcPrice = new BigNumber(4082 * 10 ** 18); - ethPrice = new BigNumber(128 * 10 ** 18); - ethUnit = new BigNumber(28.999 * 10 ** 10); - }); - - beforeEach(async () => { - lowerAllocationBound = new BigNumber(48); - upperAllocationBound = new BigNumber(52); - btcethRebalancingManager = await managerHelper.deployBTCETHRebalancingManagerAsync( - core.address, - btcMedianizer.address, - ethMedianizer.address, - wrappedBTC.address, - wrappedETH.address, - factory.address, - linearAuctionPriceCurve.address, - ONE_DAY_IN_SECONDS, - [btcMultiplier, ethMultiplier], - [lowerAllocationBound, upperAllocationBound] - ); - - initialAllocationToken = await protocolHelper.createSetTokenAsync( - core, - factory.address, - [wrappedBTC.address, wrappedETH.address], - [new BigNumber(1).mul(btcMultiplier), ethUnit.mul(ethMultiplier)], - new BigNumber(10 ** 10), - ); - - proposalPeriod = ONE_DAY_IN_SECONDS; - rebalancingSetToken = await protocolHelper.createDefaultRebalancingSetTokenAsync( - core, - rebalancingFactory.address, - btcethRebalancingManager.address, - initialAllocationToken.address, - proposalPeriod - ); - - subjectRebalancingSetToken = rebalancingSetToken.address; - subjectCaller = otherAccount; - subjectTimeFastForward = ONE_DAY_IN_SECONDS.add(1); - - await oracleHelper.addPriceFeedOwnerToMedianizer(btcMedianizer, deployerAccount); - await oracleHelper.updateMedianizerPriceAsync( - btcMedianizer, - btcPrice, - SetTestUtils.generateTimestamp(1000), - ); - - await oracleHelper.addPriceFeedOwnerToMedianizer(ethMedianizer, deployerAccount); - await oracleHelper.updateMedianizerPriceAsync( - ethMedianizer, - ethPrice, - SetTestUtils.generateTimestamp(1000), - ); - - await erc20Helper.approveTransfersAsync([wrappedBTC, wrappedETH], transferProxy.address); - - // Issue currentSetToken - await core.issue.sendTransactionAsync( - initialAllocationToken.address, - ether(9), - {from: deployerAccount, gas: DEFAULT_GAS}, - ); - - await erc20Helper.approveTransfersAsync([initialAllocationToken], transferProxy.address); - - // Use issued currentSetToken to issue rebalancingSetToken - await core.issue.sendTransactionAsync(rebalancingSetToken.address, ether(7), { - from: deployerAccount, gas: DEFAULT_GAS, - }); - }); - - async function subject(): Promise { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - return btcethRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - { from: subjectCaller, gas: DEFAULT_GAS} - ); - } - - describe('when proposeNewRebalance is called from the Default state', async () => { - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier - ); - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - - it('updates new set token to the correct components', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetComponents = await nextSet.getComponents.callAsync(); - - const expectedNextSetComponents = [wrappedBTC.address, wrappedETH.address]; - expect(JSON.stringify(nextSetComponents)).to.be.eql(JSON.stringify(expectedNextSetComponents)); - }); - - it('updates to the new auction library correctly', async () => { - await subject(); - - const newAuctionLibrary = await rebalancingSetToken.auctionLibrary.callAsync(); - expect(newAuctionLibrary).to.equal(linearAuctionPriceCurve.address); - }); - - it('updates the time to pivot correctly', async () => { - await subject(); - - const auctionPriceParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionTimeToPivot = auctionPriceParameters[1]; - expect(newAuctionTimeToPivot).to.be.bignumber.equal(ONE_DAY_IN_SECONDS); - }); - - it('updates the auction start price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedBtcEthAuctionParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[2]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionStartPrice']); - }); - - it('updates the auction pivot price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedBtcEthAuctionParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[3]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionPivotPrice']); - }); - - it('emits correct LogProposal event', async () => { - const txHash = await subject(); - - const formattedLogs = await setTestUtils.getLogsFromTxHash(txHash); - const expectedLogs = LogManagerProposal( - btcPrice, - ethPrice, - btcethRebalancingManager.address - ); - - await SetTestUtils.assertLogEquivalence(formattedLogs, expectedLogs); - }); - - describe('when the new allocation is 75/25', async () => { - before(async () => { - btcMultiplier = new BigNumber(3); - ethMultiplier = new BigNumber(1); - }); - - after(async () => { - btcMultiplier = new BigNumber(1); - ethMultiplier = new BigNumber(1); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier - ); - - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - }); - - describe('but the price of ETH is greater than BTC', async () => { - before(async () => { - btcPrice = new BigNumber(2000 * 10 ** 18); - ethPrice = new BigNumber(2500 * 10 ** 18); - ethUnit = new BigNumber(10 ** 10); - }); - - after(async () => { - btcPrice = new BigNumber(3500 * 10 ** 18); - ethPrice = new BigNumber(150 * 10 ** 18); - ethUnit = new BigNumber(40 * 10 ** 10); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier - ); - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - - it('updates the auction start price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedBtcEthAuctionParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[2]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionStartPrice']); - }); - - it('updates the auction pivot price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedBtcEthAuctionParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[3]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionPivotPrice']); - }); - - describe('but the new allocation is 75/25', async () => { - before(async () => { - btcMultiplier = new BigNumber(3); - ethMultiplier = new BigNumber(1); - }); - - after(async () => { - btcMultiplier = new BigNumber(1); - ethMultiplier = new BigNumber(1); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier - ); - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - }); - }); - - describe('but the passed rebalancing set address was not created by Core', async () => { - beforeEach(async () => { - const unTrackedSetToken = await protocolHelper.createDefaultRebalancingSetTokenAsync( - core, - rebalancingFactory.address, - btcethRebalancingManager.address, - initialAllocationToken.address, - proposalPeriod, - ); - - await core.disableSet.sendTransactionAsync( - unTrackedSetToken.address, - { from: deployerAccount, gas: DEFAULT_GAS }, - ); - - subjectRebalancingSetToken = unTrackedSetToken.address; - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('but the computed token allocation is too close to the bounds', async () => { - before(async () => { - btcPrice = new BigNumber(4000 * 10 ** 18); - ethPrice = new BigNumber(100 * 10 ** 18); - }); - - after(async () => { - btcPrice = new BigNumber(3500 * 10 ** 18); - ethPrice = new BigNumber(150 * 10 ** 18); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('but the rebalance interval has not elapsed', async () => { - beforeEach(async () => { - subjectTimeFastForward = ONE_DAY_IN_SECONDS.sub(10); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); - - describe('when proposeNewRebalance is called from Proposal state', async () => { - let timeJump: BigNumber; - - beforeEach(async () => { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await btcethRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - timeJump = new BigNumber(1000); - await blockchain.increaseTimeAsync(timeJump); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('when proposeNewRebalance is called from Rebalance state', async () => { - beforeEach(async () => { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await btcethRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - // Transition to rebalance - await blockchain.increaseTimeAsync(ONE_DAY_IN_SECONDS.add(1)); - await rebalancingSetToken.startRebalance.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS } - ); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('when proposeNewRebalance is called from Drawdown State', async () => { - beforeEach(async () => { - // propose rebalance - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await btcethRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - // Transition to rebalance - await blockchain.increaseTimeAsync(ONE_DAY_IN_SECONDS.add(1)); - - await rebalancingSetToken.startRebalance.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS } - ); - - const defaultTimeToPivot = new BigNumber(100000); - await blockchain.increaseTimeAsync(defaultTimeToPivot.add(1)); - - const biddingParameters = await rebalancingSetToken.biddingParameters.callAsync(); - const minimumBid = biddingParameters[0]; - await rebalanceAuctionModule.bid.sendTransactionAsync( - rebalancingSetToken.address, - minimumBid, - false, - { from: deployerAccount, gas: DEFAULT_GAS} - ); - - await rebalancingSetToken.endFailedAuction.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS} - ); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); -}); diff --git a/test/contracts/managers/ethDaiRebalancingManager.spec.ts b/test/contracts/managers/ethDaiRebalancingManager.spec.ts deleted file mode 100644 index 4b3d956..0000000 --- a/test/contracts/managers/ethDaiRebalancingManager.spec.ts +++ /dev/null @@ -1,771 +0,0 @@ -require('module-alias/register'); - -import * as _ from 'lodash'; -import * as ABIDecoder from 'abi-decoder'; -import * as chai from 'chai'; -import * as setProtocolUtils from 'set-protocol-utils'; -import { Address } from 'set-protocol-utils'; -import { BigNumber } from 'bignumber.js'; - -import ChaiSetup from '@utils/chaiSetup'; -import { BigNumberSetup } from '@utils/bigNumberSetup'; -import { - CoreContract, - LinearAuctionPriceCurveContract, - RebalanceAuctionModuleContract, - RebalancingSetTokenContract, - RebalancingSetTokenFactoryContract, - SetTokenContract, - SetTokenFactoryContract, - StandardTokenMockContract, - TransferProxyContract, - WethMockContract, -} from 'set-protocol-contracts'; -import { - MedianContract, -} from 'set-protocol-oracles'; - -import { ETHDaiRebalancingManagerContract } from '@utils/contracts'; -import { Blockchain } from 'set-protocol-contracts'; -import { ether } from '@utils/units'; -import { - DEFAULT_GAS, - ONE_DAY_IN_SECONDS, -} from '@utils/constants'; -import { expectRevertError } from '@utils/tokenAssertions'; -import { getWeb3 } from '@utils/web3Helper'; -import { LogManagerProposal } from '@utils/contract_logs/ethDaiRebalancingManager'; - -import { ProtocolHelper } from '@utils/helpers/protocolHelper'; -import { ERC20Helper } from '@utils/helpers/erc20Helper'; -import { OracleHelper } from 'set-protocol-oracles'; -import { ManagerHelper } from '@utils/helpers/managerHelper'; - -const Core = require('set-protocol-contracts/dist/artifacts/ts/Core').Core; -const RebalancingSetToken = require('set-protocol-contracts/dist/artifacts/ts/RebalancingSetToken').RebalancingSetToken; - -BigNumberSetup.configure(); -ChaiSetup.configure(); -const web3 = getWeb3(); -const ETHDaiRebalancingManager = artifacts.require('ETHDaiRebalancingManager'); -const { expect } = chai; -const blockchain = new Blockchain(web3); -const { SetProtocolTestUtils: SetTestUtils } = setProtocolUtils; -const setTestUtils = new SetTestUtils(web3); - -contract('ETHDaiRebalancingManager', accounts => { - const [ - deployerAccount, - otherAccount, - ] = accounts; - - let rebalancingSetToken: RebalancingSetTokenContract; - - let core: CoreContract; - let transferProxy: TransferProxyContract; - let rebalanceAuctionModule: RebalanceAuctionModuleContract; - let factory: SetTokenFactoryContract; - let rebalancingFactory: RebalancingSetTokenFactoryContract; - let linearAuctionPriceCurve: LinearAuctionPriceCurveContract; - let ethDaiRebalancingManager: ETHDaiRebalancingManagerContract; - let ethMedianizer: MedianContract; - let daiMock: StandardTokenMockContract; - let wrappedETH: WethMockContract; - - const protocolHelper = new ProtocolHelper(deployerAccount); - const erc20Helper = new ERC20Helper(deployerAccount); - const managerHelper = new ManagerHelper(deployerAccount); - const oracleHelper = new OracleHelper(deployerAccount); - - before(async () => { - ABIDecoder.addABI(Core.abi); - ABIDecoder.addABI(RebalancingSetToken.abi); - ABIDecoder.addABI(ETHDaiRebalancingManager.abi); - }); - - after(async () => { - ABIDecoder.removeABI(Core.abi); - ABIDecoder.removeABI(RebalancingSetToken.abi); - ABIDecoder.removeABI(ETHDaiRebalancingManager.abi); - }); - - beforeEach(async () => { - blockchain.saveSnapshotAsync(); - - transferProxy = await protocolHelper.getDeployedTransferProxyAsync(); - core = await protocolHelper.getDeployedCoreAsync(); - rebalanceAuctionModule = await protocolHelper.getDeployedRebalanceAuctionModuleAsync(); - - factory = await protocolHelper.getDeployedSetTokenFactoryAsync(); - rebalancingFactory = await protocolHelper.getDeployedRebalancingSetTokenFactoryAsync(); - linearAuctionPriceCurve = await protocolHelper.getDeployedLinearAuctionPriceCurveAsync(); - - ethMedianizer = await protocolHelper.getDeployedWBTCMedianizerAsync(); - await oracleHelper.addPriceFeedOwnerToMedianizer(ethMedianizer, deployerAccount); - - daiMock = await protocolHelper.getDeployedDAIAsync(); - wrappedETH = await protocolHelper.getDeployedWETHAsync(); - await erc20Helper.approveTransfersAsync( - [daiMock, wrappedETH], - transferProxy.address - ); - }); - - afterEach(async () => { - blockchain.revertAsync(); - }); - - describe('#constructor', async () => { - let subjectCoreAddress: Address; - let subjectEthPriceFeedAddress: Address; - let subjectDaiAddress: Address; - let subjectEthAddress: Address; - let subjectSetTokenFactory: Address; - let subjectAuctionLibrary: Address; - let subjectAuctionTimeToPivot: BigNumber; - let subjectDaiMultiplier: BigNumber; - let subjectEthMultiplier: BigNumber; - let subjectLowerAllocationBound: BigNumber; - let subjectUpperAllocationBound: BigNumber; - - beforeEach(async () => { - subjectCoreAddress = core.address; - subjectEthPriceFeedAddress = ethMedianizer.address; - subjectDaiAddress = daiMock.address; - subjectEthAddress = wrappedETH.address; - subjectSetTokenFactory = factory.address; - subjectAuctionLibrary = linearAuctionPriceCurve.address; - subjectAuctionTimeToPivot = ONE_DAY_IN_SECONDS; - subjectDaiMultiplier = new BigNumber(1); - subjectEthMultiplier = new BigNumber(1); - subjectLowerAllocationBound = new BigNumber(48); - subjectUpperAllocationBound = new BigNumber(52); - }); - - async function subject(): Promise { - return managerHelper.deployETHDaiRebalancingManagerAsync( - subjectCoreAddress, - subjectEthPriceFeedAddress, - subjectDaiAddress, - subjectEthAddress, - subjectSetTokenFactory, - subjectAuctionLibrary, - subjectAuctionTimeToPivot, - [subjectDaiMultiplier, subjectEthMultiplier], - [subjectLowerAllocationBound, subjectUpperAllocationBound] - ); - } - - it('sets dai address', async () => { - const rebalancingManager = await subject(); - - const actualDaiAddress = await rebalancingManager.daiAddress.callAsync(); - - expect(actualDaiAddress).to.be.equal(subjectDaiAddress); - }); - - it('sets weth address', async () => { - const rebalancingManager = await subject(); - - const actualEthAddress = await rebalancingManager.ethAddress.callAsync(); - - expect(actualEthAddress).to.be.equal(subjectEthAddress); - }); - - it('sets set token factory', async () => { - const rebalancingManager = await subject(); - - const actualSetTokenFactory = await rebalancingManager.setTokenFactory.callAsync(); - - expect(actualSetTokenFactory).to.be.equal(subjectSetTokenFactory); - }); - - it('sets auction library', async () => { - const rebalancingManager = await subject(); - - const actualAuctionLibrary = await rebalancingManager.auctionLibrary.callAsync(); - - expect(actualAuctionLibrary).to.be.equal(subjectAuctionLibrary); - }); - - it('sets correct auctionTimeToPivot', async () => { - const rebalancingManager = await subject(); - - const actualAuctionTimeToPivot = await rebalancingManager.auctionTimeToPivot.callAsync(); - - expect(actualAuctionTimeToPivot).to.be.bignumber.eql(subjectAuctionTimeToPivot); - }); - - it('sets correct daiMultiplier', async () => { - const rebalancingManager = await subject(); - - const actualDaiMultiplier = await rebalancingManager.daiMultiplier.callAsync(); - - expect(actualDaiMultiplier).to.be.bignumber.eql(subjectDaiMultiplier); - }); - - it('sets correct ethMultiplier', async () => { - const rebalancingManager = await subject(); - - const actualEthMultiplier = await rebalancingManager.ethMultiplier.callAsync(); - - expect(actualEthMultiplier).to.be.bignumber.eql(subjectEthMultiplier); - }); - - it('sets correct ethPriceFeed', async () => { - const rebalancingManager = await subject(); - - const ethPriceFeed = await rebalancingManager.ethPriceFeed.callAsync(); - - expect(ethPriceFeed).to.be.bignumber.eql(subjectEthPriceFeedAddress); - }); - - it('sets correct maximumLowerThreshold', async () => { - const rebalancingManager = await subject(); - - const maximumLowerThreshold = await rebalancingManager.maximumLowerThreshold.callAsync(); - - expect(maximumLowerThreshold).to.be.bignumber.eql(subjectLowerAllocationBound); - }); - - it('sets correct minimumUpperThreshold', async () => { - const rebalancingManager = await subject(); - - const minimumUpperThreshold = await rebalancingManager.minimumUpperThreshold.callAsync(); - - expect(minimumUpperThreshold).to.be.bignumber.eql(subjectUpperAllocationBound); - }); - - describe('when lower allocation bound is greater than upper', async () => { - beforeEach(async () => { - subjectLowerAllocationBound = new BigNumber(52); - subjectUpperAllocationBound = new BigNumber(48); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); - - describe('#propose', async () => { - let subjectRebalancingSetToken: Address; - let subjectCaller: Address; - let subjectTimeFastForward: BigNumber; - - let proposalPeriod: BigNumber; - let daiMultiplier: BigNumber; - let ethMultiplier: BigNumber; - let lowerAllocationBound: BigNumber; - let upperAllocationBound: BigNumber; - let ethPrice: BigNumber; - let daiUnit: BigNumber; - - const DAI_PRICE: BigNumber = new BigNumber(10 ** 18); - const DAI_DECIMALS: BigNumber = new BigNumber(10 ** 18); - const ETH_DECIMALS: BigNumber = new BigNumber(10 ** 18); - const PRICE_PRECISION: BigNumber = new BigNumber(100); - - let initialAllocationToken: SetTokenContract; - - before(async () => { - daiMultiplier = new BigNumber(1); - ethMultiplier = new BigNumber(1); - - ethPrice = new BigNumber(128 * 10 ** 18); - daiUnit = new BigNumber(115); - }); - - beforeEach(async () => { - lowerAllocationBound = new BigNumber(48); - upperAllocationBound = new BigNumber(52); - ethDaiRebalancingManager = await managerHelper.deployETHDaiRebalancingManagerAsync( - core.address, - ethMedianizer.address, - daiMock.address, - wrappedETH.address, - factory.address, - linearAuctionPriceCurve.address, - ONE_DAY_IN_SECONDS, - [daiMultiplier, ethMultiplier], - [lowerAllocationBound, upperAllocationBound] - ); - - initialAllocationToken = await protocolHelper.createSetTokenAsync( - core, - factory.address, - [daiMock.address, wrappedETH.address], - [daiUnit.mul(daiMultiplier).mul(100), ethMultiplier.mul(100)], - new BigNumber(100), - ); - - proposalPeriod = ONE_DAY_IN_SECONDS; - rebalancingSetToken = await protocolHelper.createDefaultRebalancingSetTokenAsync( - core, - rebalancingFactory.address, - ethDaiRebalancingManager.address, - initialAllocationToken.address, - proposalPeriod - ); - - subjectRebalancingSetToken = rebalancingSetToken.address; - subjectCaller = otherAccount; - subjectTimeFastForward = ONE_DAY_IN_SECONDS.add(1); - - await oracleHelper.updateMedianizerPriceAsync( - ethMedianizer, - ethPrice, - SetTestUtils.generateTimestamp(1000), - ); - - // Issue currentSetToken - await core.issue.sendTransactionAsync( - initialAllocationToken.address, - ether(9), - {from: deployerAccount, gas: DEFAULT_GAS}, - ); - await erc20Helper.approveTransfersAsync([initialAllocationToken], transferProxy.address); - - // Use issued currentSetToken to issue rebalancingSetToken - await core.issue.sendTransactionAsync( - rebalancingSetToken.address, - ether(7), - { from: deployerAccount, gas: DEFAULT_GAS } - ); - }); - - async function subject(): Promise { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - return ethDaiRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - { from: subjectCaller, gas: DEFAULT_GAS} - ); - } - - describe('when proposeNewRebalance is called from the Default state', async () => { - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS.div(ETH_DECIMALS), - PRICE_PRECISION, - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS.div(ETH_DECIMALS), - PRICE_PRECISION, - ); - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - - it('updates new set token to the correct components', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetComponents = await nextSet.getComponents.callAsync(); - - const expectedNextSetComponents = [daiMock.address, wrappedETH.address]; - expect(JSON.stringify(nextSetComponents)).to.be.eql(JSON.stringify(expectedNextSetComponents)); - }); - - it('updates to the new auction library correctly', async () => { - await subject(); - - const newAuctionLibrary = await rebalancingSetToken.auctionLibrary.callAsync(); - expect(newAuctionLibrary).to.equal(linearAuctionPriceCurve.address); - }); - - it('updates the time to pivot correctly', async () => { - await subject(); - - const auctionPriceParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionTimeToPivot = auctionPriceParameters[1]; - expect(newAuctionTimeToPivot).to.be.bignumber.equal(ONE_DAY_IN_SECONDS); - }); - - it('updates the auction start price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedGeneralAuctionParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS, - ETH_DECIMALS, - PRICE_PRECISION, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[2]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionStartPrice']); - }); - - it('updates the auction pivot price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedGeneralAuctionParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS, - ETH_DECIMALS, - PRICE_PRECISION, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[3]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionPivotPrice']); - }); - - it('emits correct LogProposal event', async () => { - const txHash = await subject(); - - const formattedLogs = await setTestUtils.getLogsFromTxHash(txHash); - const expectedLogs = LogManagerProposal( - ethPrice, - ethDaiRebalancingManager.address - ); - - await SetTestUtils.assertLogEquivalence(formattedLogs, expectedLogs); - }); - - describe('when the new allocation is 75/25', async () => { - before(async () => { - daiMultiplier = new BigNumber(3); - ethMultiplier = new BigNumber(1); - }); - - after(async () => { - daiMultiplier = new BigNumber(1); - ethMultiplier = new BigNumber(1); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS.div(ETH_DECIMALS), - PRICE_PRECISION, - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS.div(ETH_DECIMALS), - PRICE_PRECISION, - ); - - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - }); - - describe('but the price of Dai is greater than ETH', async () => { - before(async () => { - ethPrice = new BigNumber(7 * 10 ** 17); - daiUnit = new BigNumber(1); - }); - - after(async () => { - ethPrice = new BigNumber(150 * 10 ** 18); - daiUnit = new BigNumber(115); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS.div(ETH_DECIMALS), - PRICE_PRECISION, - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS.div(ETH_DECIMALS), - PRICE_PRECISION, - ); - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - - it('updates the auction start price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedGeneralAuctionParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS, - ETH_DECIMALS, - PRICE_PRECISION, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[2]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionStartPrice']); - }); - - it('updates the auction pivot price correctly', async () => { - await subject(); - - const auctionPriceParameters = await managerHelper.getExpectedGeneralAuctionParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS, - ETH_DECIMALS, - PRICE_PRECISION, - ONE_DAY_IN_SECONDS, - initialAllocationToken, - ); - - const newAuctionParameters = await rebalancingSetToken.auctionPriceParameters.callAsync(); - const newAuctionPivotPrice = newAuctionParameters[3]; - - expect(newAuctionPivotPrice).to.be.bignumber.equal(auctionPriceParameters['auctionPivotPrice']); - }); - - describe('but the new allocation is 75/25', async () => { - before(async () => { - daiMultiplier = new BigNumber(3); - ethMultiplier = new BigNumber(1); - }); - - after(async () => { - daiMultiplier = new BigNumber(1); - ethMultiplier = new BigNumber(1); - }); - - it('updates new set token to the correct naturalUnit', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetNaturalUnit = await nextSet.naturalUnit.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS.div(ETH_DECIMALS), - PRICE_PRECISION, - ); - expect(nextSetNaturalUnit).to.be.bignumber.equal(expectedNextSetParams['naturalUnit']); - }); - - it('updates new set token to the correct units', async () => { - await subject(); - - const nextSetAddress = await rebalancingSetToken.nextSet.callAsync(); - const nextSet = await protocolHelper.getSetTokenAsync(nextSetAddress); - const nextSetUnits = await nextSet.getUnits.callAsync(); - - const expectedNextSetParams = managerHelper.getExpectedGeneralNextSetParameters( - DAI_PRICE, - ethPrice, - daiMultiplier, - ethMultiplier, - DAI_DECIMALS.div(ETH_DECIMALS), - PRICE_PRECISION, - ); - expect(JSON.stringify(nextSetUnits)).to.be.eql(JSON.stringify(expectedNextSetParams['units'])); - }); - }); - }); - - describe('but the passed rebalancing set address was not created by Core', async () => { - beforeEach(async () => { - const unTrackedSetToken = await protocolHelper.createDefaultRebalancingSetTokenAsync( - core, - rebalancingFactory.address, - ethDaiRebalancingManager.address, - initialAllocationToken.address, - proposalPeriod, - ); - - await core.disableSet.sendTransactionAsync( - unTrackedSetToken.address, - { from: deployerAccount, gas: DEFAULT_GAS }, - ); - - subjectRebalancingSetToken = unTrackedSetToken.address; - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('but the computed token allocation is too close to the bounds', async () => { - before(async () => { - ethPrice = new BigNumber(112 * 10 ** 18); - }); - - after(async () => { - ethPrice = new BigNumber(150 * 10 ** 18); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('but the rebalance interval has not elapsed', async () => { - beforeEach(async () => { - subjectTimeFastForward = ONE_DAY_IN_SECONDS.sub(10); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); - - describe('when proposeNewRebalance is called from Proposal state', async () => { - let timeJump: BigNumber; - - beforeEach(async () => { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await ethDaiRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - timeJump = new BigNumber(1000); - await blockchain.increaseTimeAsync(timeJump); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('when proposeNewRebalance is called from Rebalance state', async () => { - beforeEach(async () => { - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await ethDaiRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - // Transition to rebalance - await blockchain.increaseTimeAsync(ONE_DAY_IN_SECONDS.add(1)); - await rebalancingSetToken.startRebalance.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS } - ); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - - describe('when proposeNewRebalance is called from Drawdown State', async () => { - beforeEach(async () => { - // propose rebalance - await blockchain.increaseTimeAsync(subjectTimeFastForward); - await ethDaiRebalancingManager.propose.sendTransactionAsync( - subjectRebalancingSetToken, - ); - - // Transition to rebalance - await blockchain.increaseTimeAsync(ONE_DAY_IN_SECONDS.add(1)); - - await rebalancingSetToken.startRebalance.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS } - ); - - const defaultTimeToPivot = new BigNumber(100000); - await blockchain.increaseTimeAsync(defaultTimeToPivot.add(1)); - - const biddingParameters = await rebalancingSetToken.biddingParameters.callAsync(); - const minimumBid = biddingParameters[0]; - await rebalanceAuctionModule.bid.sendTransactionAsync( - rebalancingSetToken.address, - minimumBid, - false, - { from: deployerAccount, gas: DEFAULT_GAS} - ); - - await rebalancingSetToken.endFailedAuction.sendTransactionAsync( - { from: otherAccount, gas: DEFAULT_GAS} - ); - }); - - it('should revert', async () => { - await expectRevertError(subject()); - }); - }); - }); -}); diff --git a/test/contracts/managers/lib/managerLibraryMock.spec.ts b/test/contracts/managers/lib/managerLibraryMock.spec.ts deleted file mode 100644 index a4d8b4e..0000000 --- a/test/contracts/managers/lib/managerLibraryMock.spec.ts +++ /dev/null @@ -1,93 +0,0 @@ -require('module-alias/register'); - -import * as _ from 'lodash'; -import * as chai from 'chai'; -import { BigNumber } from 'bignumber.js'; - -import ChaiSetup from '@utils/chaiSetup'; -import { BigNumberSetup } from '@utils/bigNumberSetup'; -import { - ManagerLibraryMockContract -} from '@utils/contracts'; -import { Blockchain } from 'set-protocol-contracts'; -import { getWeb3 } from '@utils/web3Helper'; -import { DEFAULT_AUCTION_PRICE_DIVISOR } from '@utils/constants'; - -import { LibraryMockHelper } from '@utils/helpers/libraryMockHelper'; - -BigNumberSetup.configure(); -ChaiSetup.configure(); -const web3 = getWeb3(); -const blockchain = new Blockchain(web3); -const { expect } = chai; - -contract('ManagerLibraryMock', accounts => { - const [ - contractDeployer, - ] = accounts; - - let managerLibraryMock: ManagerLibraryMockContract; - - const libraryMockHelper = new LibraryMockHelper(contractDeployer); - - beforeEach(async () => { - await blockchain.saveSnapshotAsync(); - - managerLibraryMock = await libraryMockHelper.deployManagerLibraryMockAsync(); - }); - - afterEach(async () => { - await blockchain.revertAsync(); - }); - - describe('#calculateAuctionPriceParameters', async () => { - let subjectCurrentSetDollarAmount: BigNumber; - let subjectNextSetDollarAmount: BigNumber; - let subjectAuctionLibraryPriceDivisor: BigNumber; - let subjectAuctionTimeToPivot: BigNumber; - - const THIRTY_MINUTE_IN_SECONDS = new BigNumber(60 * 30); - - beforeEach(async () => { - subjectCurrentSetDollarAmount = new BigNumber(10 ** 20); - subjectNextSetDollarAmount = new BigNumber(10 ** 20).mul(2); - subjectAuctionLibraryPriceDivisor = DEFAULT_AUCTION_PRICE_DIVISOR; - subjectAuctionTimeToPivot = new BigNumber(60 * 60 * 24); // 1 day - }); - - async function subject(): Promise { - return managerLibraryMock.calculateAuctionPriceParameters.callAsync( - subjectCurrentSetDollarAmount, - subjectNextSetDollarAmount, - subjectAuctionLibraryPriceDivisor, - subjectAuctionTimeToPivot, - ); - } - - it('should return the correct auctionStartPrice', async () => { - const [auctionStartPrice] = await subject(); - - const fairValue = subjectNextSetDollarAmount - .mul(subjectAuctionLibraryPriceDivisor) - .div(subjectCurrentSetDollarAmount); - const thirtyMinutePeriods = subjectAuctionTimeToPivot.div(THIRTY_MINUTE_IN_SECONDS); - const halfPriceRange = thirtyMinutePeriods.mul(fairValue).div(200); - const expectedStartPrice = fairValue.sub(halfPriceRange); - - expect(expectedStartPrice).to.bignumber.equal(auctionStartPrice); - }); - - it('should return the correct auctionPivotPrice', async () => { - const [, auctionPivotPrice] = await subject(); - - const fairValue = subjectNextSetDollarAmount - .mul(subjectAuctionLibraryPriceDivisor) - .div(subjectCurrentSetDollarAmount); - const thirtyMinutePeriods = subjectAuctionTimeToPivot.div(THIRTY_MINUTE_IN_SECONDS); - const halfPriceRange = thirtyMinutePeriods.mul(fairValue).div(200); - const expectedPivotPrice = fairValue.add(halfPriceRange); - - expect(expectedPivotPrice).to.bignumber.equal(auctionPivotPrice); - }); - }); -}); diff --git a/test/scenarios/btc-eth/btcEthMultipleRebalance.spec.ts b/test/scenarios/btc-eth/btcEthMultipleRebalance.spec.ts deleted file mode 100644 index d864b2f..0000000 --- a/test/scenarios/btc-eth/btcEthMultipleRebalance.spec.ts +++ /dev/null @@ -1,113 +0,0 @@ -require('module-alias/register'); - -import * as chai from 'chai'; -import * as _ from 'lodash'; -import * as ABIDecoder from 'abi-decoder'; -import { BigNumber } from 'set-protocol-utils'; - -import ChaiSetup from '@utils/chaiSetup'; -import { BigNumberSetup } from '@utils/bigNumberSetup'; -import { Blockchain } from 'set-protocol-contracts'; -import { getWeb3 } from '@utils/web3Helper'; - -import { getScenarioData } from './scenarioData'; - -import { - DataOutput, - FullRebalanceProgram, -} from './types'; - -import { BTCETHMultipleRebalanceHelper } from './btcEthMultipleRebalanceHelper'; - -const Core = require('set-protocol-contracts/dist/artifacts/ts/Core').Core; -const RebalanceAuctionModule = - require('set-protocol-contracts/dist/artifacts/ts/RebalanceAuctionModule').RebalanceAuctionModule; -const RebalancingSetToken = - require('set-protocol-contracts/dist/artifacts/ts/RebalancingSetToken').RebalancingSetToken; - -BigNumberSetup.configure(); -ChaiSetup.configure(); -const web3 = getWeb3(); -const { expect } = chai; -const blockchain = new Blockchain(web3); - - -contract('Multiple Rebalance BTC-ETH 50/50', accounts => { - - let btcEthRebalanceHelper: BTCETHMultipleRebalanceHelper; - let scenarioData: FullRebalanceProgram; - - before(async () => { - ABIDecoder.addABI(Core.abi); - ABIDecoder.addABI(RebalanceAuctionModule.abi); - ABIDecoder.addABI(RebalancingSetToken.abi); - }); - - after(async () => { - ABIDecoder.removeABI(Core.abi); - ABIDecoder.removeABI(RebalanceAuctionModule.abi); - ABIDecoder.removeABI(RebalancingSetToken.abi); - }); - - beforeEach(async () => { - await blockchain.saveSnapshotAsync(); - - scenarioData = getScenarioData(accounts); - - btcEthRebalanceHelper = new BTCETHMultipleRebalanceHelper(accounts, scenarioData); - }); - - afterEach(async () => { - await blockchain.revertAsync(); - }); - - async function subject(): Promise { - return btcEthRebalanceHelper.runFullRebalanceProgram(); - } - - describe('for multiple rebalance cycles', async () => { - it('for first rebalance actual slippage is within 5% of expected slippage', async () => { - const dataOutput = await subject(); - - const expectedCollateral = dataOutput.collateralizingSets[0].mul( - dataOutput.issuedRebalancingSets[1].div(dataOutput.issuedRebalancingSets[0]) - ).div(dataOutput.rebalanceFairValues[0]).mul(1000).round(0, 4); - - let expectedBidSlippage: BigNumber = new BigNumber(0); - for (let i = 0; i < scenarioData.cycleData[0].biddingSchedule.length; i++) { - const bid = scenarioData.cycleData[0].biddingSchedule[i]; - - expectedBidSlippage = expectedBidSlippage.add(bid.amount.mul(bid.price)); - } - - const actualBidSlippage = new BigNumber(1).sub( - dataOutput.collateralizingSets[1].div(expectedCollateral) - ).toNumber(); - - expect(actualBidSlippage).to.be.greaterThan(expectedBidSlippage.mul(.95).toNumber()); - expect(actualBidSlippage).to.be.lessThan(expectedBidSlippage.mul(1.05).toNumber()); - }); - - it('for second rebalance actual slippage is within 5% of expected slippage', async () => { - const dataOutput = await subject(); - - const expectedCollateral = dataOutput.collateralizingSets[1].mul( - dataOutput.issuedRebalancingSets[2].div(dataOutput.issuedRebalancingSets[1]) - ).div(dataOutput.rebalanceFairValues[1]).mul(1000).round(0, 4); - - let expectedBidSlippage: BigNumber = new BigNumber(0); - for (let i = 0; i < scenarioData.cycleData[1].biddingSchedule.length; i++) { - const bid = scenarioData.cycleData[1].biddingSchedule[i]; - - expectedBidSlippage = expectedBidSlippage.add(bid.amount.mul(bid.price)); - } - - const actualBidSlippage = new BigNumber(1).sub( - dataOutput.collateralizingSets[2].div(expectedCollateral) - ).toNumber(); - - expect(actualBidSlippage).to.be.greaterThan(expectedBidSlippage.mul(.95).toNumber()); - expect(actualBidSlippage).to.be.lessThan(expectedBidSlippage.mul(1.05).toNumber()); - }); - }); -}); diff --git a/test/scenarios/btc-eth/btcEthMultipleRebalanceHelper.ts b/test/scenarios/btc-eth/btcEthMultipleRebalanceHelper.ts deleted file mode 100644 index 3a3531e..0000000 --- a/test/scenarios/btc-eth/btcEthMultipleRebalanceHelper.ts +++ /dev/null @@ -1,708 +0,0 @@ -require('module-alias/register'); - -import * as _ from 'lodash'; -import * as setProtocolUtils from 'set-protocol-utils'; -import { Address, Web3Utils } from 'set-protocol-utils'; -import { BigNumber } from 'set-protocol-utils'; - -import ChaiSetup from '@utils/chaiSetup'; -import { BigNumberSetup } from '@utils/bigNumberSetup'; -import { - CoreContract, - LinearAuctionPriceCurveContract, - RebalanceAuctionModuleContract, - RebalancingSetTokenContract, - RebalancingSetTokenFactoryContract, - SetTokenContract, - SetTokenFactoryContract, - StandardTokenMockContract, - TransferProxyContract, - VaultContract, - WethMockContract, -} from 'set-protocol-contracts'; -import { - MedianContract, -} from 'set-protocol-oracles'; -import { BTCETHRebalancingManagerContract } from '@utils/contracts'; -import { - DEFAULT_GAS, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, -} from '@utils/constants'; -import { getWeb3 } from '@utils/web3Helper'; - -import { - UserAccountData, - TokenBalances, - UserTokenBalances, - IssuanceTxn, - IssuanceSchedule, - TokenPrices, - BidTxn, - SingleRebalanceCycleScenario, - FullRebalanceProgram, - DataOutput, -} from './types'; - -import { ProtocolHelper } from '@utils/helpers/protocolHelper'; -import { ERC20Helper } from '@utils/helpers/erc20Helper'; -import { OracleHelper } from 'set-protocol-oracles'; -import { ManagerHelper } from '@utils/helpers/managerHelper'; - -BigNumberSetup.configure(); -ChaiSetup.configure(); -const web3 = getWeb3(); -const { SetProtocolTestUtils: SetTestUtils, SetProtocolUtils: SetUtils } = setProtocolUtils; -const web3Utils = new Web3Utils(web3); - -export class BTCETHMultipleRebalanceHelper { - private _accounts: UserAccountData; - private _rebalanceProgram: FullRebalanceProgram; - private _dataLogger: DataOutput; - - private _contractOwnerAddress: Address; - private _protocolHelper: ProtocolHelper; - private _erc20Helper: ERC20Helper; - private _oracleHelper: OracleHelper; - private _managerHelper: ManagerHelper; - - private _rebalancingSetToken: RebalancingSetTokenContract; - - private _core: CoreContract; - private _transferProxy: TransferProxyContract; - private _vault: VaultContract; - private _rebalanceAuctionModule: RebalanceAuctionModuleContract; - private _factory: SetTokenFactoryContract; - private _rebalancingFactory: RebalancingSetTokenFactoryContract; - private _linearAuctionPriceCurve: LinearAuctionPriceCurveContract; - private _btcethRebalancingManager: BTCETHRebalancingManagerContract; - private _btcMedianizer: MedianContract; - private _ethMedianizer: MedianContract; - - private _wrappedBTC: StandardTokenMockContract; - private _wrappedETH: WethMockContract; - private _initialBtcEthSet: SetTokenContract; - - constructor(otherAccounts: Address[], rebalanceProgram: FullRebalanceProgram, profileGas: boolean = false) { - this._contractOwnerAddress = otherAccounts[0]; - this._accounts = this._createAccountPersonalitiesAsync(otherAccounts); - this._validateScenarioObject(rebalanceProgram); - this._rebalanceProgram = rebalanceProgram; - this._dataLogger = { - collateralizingSets: [], - issuedRebalancingSets: [], - rebalanceFairValues: [], - rebalancingSetBaseSetDust: [], - rebalancingSetComponentDust: [], - gasProfile: {}, - }; - - this._protocolHelper = new ProtocolHelper(this._contractOwnerAddress); - this._erc20Helper = new ERC20Helper(this._contractOwnerAddress); - this._managerHelper = new ManagerHelper(this._contractOwnerAddress); - this._oracleHelper = new OracleHelper(this._contractOwnerAddress); - } - - public async runFullRebalanceProgram(): Promise { - await this.deployAndAuthorizeCoreContractsAsync(); - await this.createRebalancingSetToken(); - await this.distributeTokensAndMintSets(); - await this.runRebalanceScenario(this._rebalanceProgram.cycleData); - return this._dataLogger; - } - - public async deployAndAuthorizeCoreContractsAsync( - deployerAccount: Address = this._contractOwnerAddress, - ): Promise { - // Deploy core contracts - this._transferProxy = await this._protocolHelper.getDeployedTransferProxyAsync(); - - this._vault = await this._protocolHelper.getDeployedVaultAsync(); - - this._core = await this._protocolHelper.getDeployedCoreAsync(); - - this._rebalanceAuctionModule = await this._protocolHelper.getDeployedRebalanceAuctionModuleAsync(); - - this._factory = await this._protocolHelper.getDeployedSetTokenFactoryAsync(); - - this._rebalancingFactory = await this._protocolHelper.getDeployedRebalancingSetTokenFactoryAsync(); - - this._linearAuctionPriceCurve = await this._protocolHelper.getDeployedLinearAuctionPriceCurveAsync(); - - // Deploy Oracles and set initial prices - this._btcMedianizer = await this._protocolHelper.getDeployedWBTCMedianizerAsync(); - await this._oracleHelper.addPriceFeedOwnerToMedianizer(this._btcMedianizer, deployerAccount); - this._ethMedianizer = await this._protocolHelper.getDeployedWETHMedianizerAsync(); - await this._oracleHelper.addPriceFeedOwnerToMedianizer(this._ethMedianizer, deployerAccount); - - await this._oracleHelper.updateMedianizerPriceAsync( - this._btcMedianizer, - this._rebalanceProgram.initializationParams.initialTokenPrices.WBTCPrice, - SetTestUtils.generateTimestamp(1000), - ); - await this._oracleHelper.updateMedianizerPriceAsync( - this._ethMedianizer, - this._rebalanceProgram.initializationParams.initialTokenPrices.WETHPrice, - SetTestUtils.generateTimestamp(1000), - ); - - // Deploy WBTC, WETH and add tokens to whitelise - this._wrappedBTC = await this._protocolHelper.getDeployedWBTCAsync(); - this._wrappedETH = await this._protocolHelper.getDeployedWETHAsync(); - - // Deploy manager contract - this._btcethRebalancingManager = await this._managerHelper.deployBTCETHRebalancingManagerAsync( - this._core.address, - this._btcMedianizer.address, - this._ethMedianizer.address, - this._wrappedBTC.address, - this._wrappedETH.address, - this._factory.address, - this._linearAuctionPriceCurve.address, - this._rebalanceProgram.initializationParams.auctionTimeToPivot, - [ - this._rebalanceProgram.initializationParams.btcMultiplier, - this._rebalanceProgram.initializationParams.ethMultiplier, - ], - [ - this._rebalanceProgram.initializationParams.lowerAllocationBound, - this._rebalanceProgram.initializationParams.upperAllocationBound, - ] - ); - } - - public async createRebalancingSetToken(): Promise { - this._initialBtcEthSet = await this._protocolHelper.createSetTokenAsync( - this._core, - this._factory.address, - [this._wrappedBTC.address, this._wrappedETH.address], - this._rebalanceProgram.initializationParams.initialSetUnits, - this._rebalanceProgram.initializationParams.initialSetNaturalUnit, - ); - this._dataLogger.gasProfile.createInitialBaseSet = await this._extractGasCostFromLatestBlockAsync(); - this._rebalanceProgram.generalRebalancingData.baseSets.push( - this._initialBtcEthSet.address - ); - - const rebalancingSetCallData = SetUtils.generateRebalancingSetTokenCallData( - this._btcethRebalancingManager.address, - this._rebalanceProgram.initializationParams.proposalPeriod, - this._rebalanceProgram.initializationParams.rebalanceInterval, - ); - - this._rebalancingSetToken = await this._protocolHelper.createRebalancingTokenAsync( - this._core, - this._rebalancingFactory.address, - [this._initialBtcEthSet.address], - this._rebalanceProgram.initializationParams.rebalancingSetUnitShares, - this._rebalanceProgram.initializationParams.rebalancingSetNaturalUnit, - rebalancingSetCallData, - ); - this._dataLogger.gasProfile.createRebalancingSet = await this._extractGasCostFromLatestBlockAsync(); - } - - public async distributeTokensAndMintSets(): Promise { - // Issue Rebalancing Sets using _contractOwnerAddress tokens and distrubuted to owner group - await this._issueAndDistributeRebalancingSetsAsync(); - - // Distribute tokens to bidding accounts - await this._distributeBtcAndEthToBiddersAsync(); - } - - public async runRebalanceScenario( - scenarios: SingleRebalanceCycleScenario[], - ): Promise { - // For each rebalance iteration - for (let i = 0; i < this._rebalanceProgram.rebalanceIterations; i++) { - const scenario = scenarios[i]; - // Issue and Redeem Sets - await this._executeIssuanceScheduleAsync(scenario.issueRedeemSchedule); - - // Run Proposal (change prices) and transtion to rebalance - await this._proposeAndTransitionToRebalanceAsync(scenario.priceUpdate); - // Run bidding program - await this._executeBiddingScheduleAsync(scenario.biddingSchedule, scenario.priceUpdate); - // Finish rebalance cycle and log outputs - await this._settleRebalanceAndLogState(); - } - } - - public async returnAllUserTokenBalancesAsync(): Promise { - let allUserTokenBalances: UserTokenBalances; - - const bidderOne = await this._getTokenBalancesAsync(this._accounts.bidderOne); - const bidderTwo = await this._getTokenBalancesAsync(this._accounts.bidderTwo); - const bidderThree = await this._getTokenBalancesAsync(this._accounts.bidderThree); - const bidderFour = await this._getTokenBalancesAsync(this._accounts.bidderFour); - const bidderFive = await this._getTokenBalancesAsync(this._accounts.bidderFive); - - const tokenOwnerOne = await this._getTokenBalancesAsync(this._accounts.tokenOwnerOne); - const tokenOwnerTwo = await this._getTokenBalancesAsync(this._accounts.tokenOwnerTwo); - const tokenOwnerThree = await this._getTokenBalancesAsync(this._accounts.tokenOwnerThree); - const tokenOwnerFour = await this._getTokenBalancesAsync(this._accounts.tokenOwnerFour); - const tokenOwnerFive = await this._getTokenBalancesAsync(this._accounts.tokenOwnerFive); - - allUserTokenBalances = { - bidderOne, - bidderTwo, - bidderThree, - bidderFour, - bidderFive, - tokenOwnerOne, - tokenOwnerTwo, - tokenOwnerThree, - tokenOwnerFour, - tokenOwnerFive, - }; - return allUserTokenBalances; - } - - /* ============ Private ============ */ - - private _validateScenarioObject( - rebalanceProgram: FullRebalanceProgram, - ): void { - if (rebalanceProgram.rebalanceIterations != rebalanceProgram.cycleData.length) { - throw new Error('Provided rebalance iterations does not match cycle data'); - } - - let lastBidPrice: BigNumber; - for (let i = 0; i < rebalanceProgram.rebalanceIterations; i++) { - lastBidPrice = new BigNumber(-1); - for (let j = 0; j < rebalanceProgram.cycleData[i].biddingSchedule.length; j++) { - const bid = rebalanceProgram.cycleData[i].biddingSchedule[j]; - if (lastBidPrice.greaterThan(bid.price)) { - throw new Error('Bids must be placed in ascending price order'); - } - lastBidPrice = bid.price; - } - } - } - - private _createAccountPersonalitiesAsync( - accounts: Address[], - ): UserAccountData { - const personalities = { - bidderOne: accounts[1], - bidderTwo: accounts[2], - bidderThree: accounts[3], - bidderFour: accounts[4], - bidderFive: accounts[5], - tokenOwnerOne: accounts[6], - tokenOwnerTwo: accounts[7], - tokenOwnerThree: accounts[8], - tokenOwnerFour: accounts[9], - tokenOwnerFive: accounts[10], - bidders: accounts.slice(1, 6), - tokenOwners: accounts.slice(6, 11), - }; - - return personalities; - } - - private async _issueAndDistributeRebalancingSetsAsync(): Promise { - // Approve transfers for WBTC and WETH - await this._erc20Helper.approveTransfersAsync( - [this._wrappedBTC], - this._transferProxy.address - ); - - await this._wrappedETH.approve.sendTransactionAsync( - this._transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ); - - // Issue Rebalancing Set to the the deployer - const txHashIssueBase = await this._core.issue.sendTransactionAsync( - this._initialBtcEthSet.address, - this._rebalanceProgram.initializationParams.initialSetIssueQuantity, - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ); - this._dataLogger.gasProfile.issueInitialBaseSet = await this._extractGasCostAsync( - txHashIssueBase - ); - - await this._initialBtcEthSet.approve.sendTransactionAsync( - this._transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ); - - // Issue Rebalancing Set to the the deployer - const txHashIssueRebalancing = await this._core.issue.sendTransactionAsync( - this._rebalancingSetToken.address, - this._rebalanceProgram.initializationParams.rebalancingSetIssueQuantity, - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ); - this._dataLogger.gasProfile.issueRebalancingSet = await this._extractGasCostAsync( - txHashIssueRebalancing - ); - - // Transfer RebalancingSetToken amounts to bidders - const transferRebalancingSetPromises = _.map( - this._accounts.tokenOwners, - address => this._rebalancingSetToken.transfer.sendTransactionAsync( - address, - this._rebalanceProgram.initializationParams.rebalancingSetIssueQuantity.div(5), - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ) - ); - await Promise.all(transferRebalancingSetPromises); - - this._dataLogger.collateralizingSets.push( - await this._vault.getOwnerBalance.callAsync( - this._initialBtcEthSet.address, - this._rebalancingSetToken.address, - ) - ); - - this._dataLogger.issuedRebalancingSets.push( - await this._rebalancingSetToken.totalSupply.callAsync() - ); - } - - private async _distributeBtcAndEthToBiddersAsync(): Promise { - // Transfer WBTC amounts to bidders - const transferWBTCPromises = _.map( - this._accounts.bidders, - address => this._wrappedBTC.transfer.sendTransactionAsync( - address, - new BigNumber(10 ** 19), - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ) - ); - await Promise.all(transferWBTCPromises); - - // Transfer WETH amounts to bidders - const transferWETHPromises = _.map( - this._accounts.bidders, - address => this._wrappedETH.transfer.sendTransactionAsync( - address, - new BigNumber(10 ** 19), - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ) - ); - await Promise.all(transferWETHPromises); - - // Approve WBTC amounts for bidders to transferProxy - const approveWBTCPromises = _.map( - this._accounts.bidders, - address => this._wrappedBTC.approve.sendTransactionAsync( - this._transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: address, gas: DEFAULT_GAS }, - ) - ); - await Promise.all(approveWBTCPromises); - - // Approve WETH amounts for bidders to transferProxy - const approveWETHPromises = _.map( - this._accounts.bidders, - address => this._wrappedETH.approve.sendTransactionAsync( - this._transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: address, gas: DEFAULT_GAS }, - ) - ); - await Promise.all(approveWETHPromises); - } - - private async _executeIssuanceScheduleAsync( - scehdule: IssuanceSchedule, - ): Promise { - // Execute issuances - const issuancePromises = _.map( - scehdule.issuances, - txn => this._issueRebalancingSetsAsync( - txn, - ) - ); - await Promise.all(issuancePromises); - - // Execute redemptions - const redemptionPromises = _.map( - scehdule.redemptions, - txn => this._redeemRebalancingSetsAsync( - txn, - ) - ); - await Promise.all(redemptionPromises); - } - - private async _proposeAndTransitionToRebalanceAsync( - newPrices: TokenPrices, - ): Promise { - - await this._oracleHelper.updateMedianizerPriceAsync( - this._btcMedianizer, - newPrices.WBTCPrice, - SetTestUtils.generateTimestamp(1000), - ); - - - await this._oracleHelper.updateMedianizerPriceAsync( - this._ethMedianizer, - newPrices.WETHPrice, - SetTestUtils.generateTimestamp(1000), - ); - - // Fast forward the rebalance interval - await web3Utils.increaseTime( - this._rebalanceProgram.initializationParams.rebalanceInterval.plus(1).toNumber() - ); - - - // Call propose from Rebalance Manager and log propose data - const txHashPropose = await this._btcethRebalancingManager.propose.sendTransactionAsync( - this._rebalancingSetToken.address, - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ); - await this._logPostProposeDataAsync(txHashPropose); - - await web3Utils.increaseTime( - this._rebalanceProgram.initializationParams.proposalPeriod.mul(2).toNumber() - ); - - - const txHashStartRebalance = await this._rebalancingSetToken.startRebalance.sendTransactionAsync( - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ); - await this._logPostStartRebalanceDataAsync(txHashStartRebalance); - - } - - private async _executeBiddingScheduleAsync( - schedule: BidTxn[], - tokenPrices: TokenPrices, - ): Promise { - let cumulativeTime: number = 0; - - for (let i = 0; i < schedule.length; i++) { - const bid = schedule[i]; - - const bidPrice = await this._calculateImpliedBidPriceAsync(bid.price, tokenPrices); - const bidTime = await this._calculateImpliedBidTimeAsync(bidPrice); - const timeJump = bidTime - cumulativeTime; - - const bidAmount = this._calculateImpliedBidAmount(bid.amount); - await web3Utils.increaseTime(timeJump); - - await this._rebalanceAuctionModule.bid.sendTransactionAsync( - this._rebalancingSetToken.address, - bidAmount, - false, - { from: bid.sender, gas: DEFAULT_GAS } - ); - cumulativeTime += timeJump; - } - - await this._executeBidCleanUpAsync(schedule[schedule.length - 1].sender); - } - - private async _settleRebalanceAndLogState(): Promise { - const txHashSettle = await this._rebalancingSetToken.settleRebalance.sendTransactionAsync( - { from: this._contractOwnerAddress, gas: DEFAULT_GAS }, - ); - this._dataLogger.gasProfile.settleRebalance = await this._extractGasCostAsync( - txHashSettle - ); - - - this._dataLogger.collateralizingSets.push( - await this._vault.getOwnerBalance.callAsync( - this._getRecentBaseSet(), - this._rebalancingSetToken.address, - ) - ); - - this._dataLogger.issuedRebalancingSets.push( - await this._rebalancingSetToken.totalSupply.callAsync() - ); - - this._dataLogger.rebalancingSetBaseSetDust.push( - await this._vault.getOwnerBalance.callAsync( - this._rebalanceProgram.generalRebalancingData.baseSets.slice(-2)[0], - this._rebalancingSetToken.address - ) - ); - - this._dataLogger.rebalancingSetComponentDust.push( - await this._getTokenBalancesAsync( - this._rebalancingSetToken.address - ) - ); - } - - private async _issueRebalancingSetsAsync( - issuance: IssuanceTxn, - ): Promise { - const currentSetInstance = await this._protocolHelper.getSetTokenAsync( - this._getRecentBaseSet() - ); - const currentSetNaturalUnit = await currentSetInstance.naturalUnit.callAsync(); - - const rebalancingSetUnitShares = await this._rebalancingSetToken.unitShares.callAsync(); - const rebalancingSetNaturalUnit = await this._rebalancingSetToken.naturalUnit.callAsync(); - const currentSetRequiredAmountUnrounded = issuance.amount - .mul(rebalancingSetUnitShares) - .div(rebalancingSetNaturalUnit) - .round(0, 3); - const currentSetRequiredAmount = currentSetRequiredAmountUnrounded.sub( - currentSetRequiredAmountUnrounded.modulo(currentSetNaturalUnit) - ).add(currentSetNaturalUnit); - - await this._core.issue.sendTransactionAsync( - currentSetInstance.address, - currentSetRequiredAmount, - { from: issuance.sender, gas: DEFAULT_GAS }, - ); - await currentSetInstance.approve.sendTransactionAsync( - this._transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: issuance.sender, gas: DEFAULT_GAS }, - ); - await this._core.issue.sendTransactionAsync( - this._rebalancingSetToken.address, - issuance.amount, - { from: issuance.sender, gas: DEFAULT_GAS }, - ); - } - - private async _redeemRebalancingSetsAsync( - redemption: IssuanceTxn, - ): Promise { - const txHashRedeem = await this._core.redeem.sendTransactionAsync( - this._rebalancingSetToken.address, - redemption.amount, - { from: redemption.sender, gas: DEFAULT_GAS }, - ); - - this._dataLogger.gasProfile.redeemRebalancingSet = await this._extractGasCostAsync( - txHashRedeem - ); - } - - private async _calculateImpliedBidPriceAsync( - percentFromFairValue: BigNumber, - tokenPrices: TokenPrices, - ): Promise { - const auctionPriceParameters = await this._rebalancingSetToken.getAuctionPriceParameters.callAsync(); - const auctionStartPrice = auctionPriceParameters[2]; - const auctionPivotPrice = auctionPriceParameters[3]; - - const fairValue = (auctionStartPrice.add(auctionPivotPrice)).div(2).round(0, 3); - return fairValue.mul(percentFromFairValue.add(1)).round(0, 4); - } - - private async _calculateImpliedBidTimeAsync( - bidPrice: BigNumber, - ): Promise { - const auctionPriceParameters = await this._rebalancingSetToken.getAuctionPriceParameters.callAsync(); - const auctionTimeToPivot = this._rebalanceProgram.initializationParams.auctionTimeToPivot; - const auctionStartPrice = auctionPriceParameters[2]; - const auctionPivotPrice = auctionPriceParameters[3]; - const linearPriceDifference = auctionPivotPrice.sub(auctionStartPrice); - - const bidTime = (bidPrice.sub(auctionStartPrice)).mul(auctionTimeToPivot) - .div(linearPriceDifference).round(0, 3); - - return bidTime.toNumber(); - } - - private _calculateImpliedBidAmount( - bidAmount: BigNumber, - ): BigNumber { - const initialRemainingSets = this._rebalanceProgram.generalRebalancingData.initialRemainingSets; - const unroundedBidAmount = initialRemainingSets.mul(bidAmount); - - return unroundedBidAmount.sub( - unroundedBidAmount.modulo(this._rebalanceProgram.generalRebalancingData.minimumBid) - ); - } - - private async _executeBidCleanUpAsync( - lastBidder: Address, - ): Promise { - const biddingParameters = await this._rebalancingSetToken.getBiddingParameters.callAsync(); - const bidAmount = biddingParameters[1].sub( - biddingParameters[1].modulo(this._rebalanceProgram.generalRebalancingData.minimumBid) - ); - - if (bidAmount.greaterThan(0)) { - const txHashBid = await this._rebalanceAuctionModule.bid.sendTransactionAsync( - this._rebalancingSetToken.address, - bidAmount, - false, - { from: lastBidder, gas: DEFAULT_GAS } - ); - this._dataLogger.gasProfile.bid = await this._extractGasCostAsync( - txHashBid - ); - } - } - - private async _getTokenBalancesAsync( - userAddress: Address, - ): Promise { - let userBalances: TokenBalances; - - const WBTCWallet = await this._wrappedBTC.balanceOf.callAsync(userAddress); - const WBTCVault = await this._vault.getOwnerBalance.callAsync(this._wrappedBTC.address, userAddress); - const WETHWallet = await this._wrappedETH.balanceOf.callAsync(userAddress); - const WETHVault = await this._vault.getOwnerBalance.callAsync(this._wrappedETH.address, userAddress); - const RebalancingSet = await this._rebalancingSetToken.balanceOf.callAsync(userAddress); - - userBalances = { - WBTC: WBTCWallet.add(WBTCVault), - WETH: WETHWallet.add(WETHVault), - RebalancingSet, - }; - return userBalances; - } - - private async _extractGasCostAsync( - txHash: string, - ): Promise { - const issueReceipt = await web3.eth.getTransactionReceipt(txHash); - return issueReceipt.gasUsed; - } - - private async _extractGasCostFromLatestBlockAsync(): Promise { - const block = await web3.eth.getBlock('latest'); - - const txHash = block.transactions[0]; - return this._extractGasCostAsync(txHash); - } - - private async _logPostProposeDataAsync(txHash: string): Promise { - this._dataLogger.gasProfile.proposeRebalance = await this._extractGasCostAsync( - txHash - ); - this._rebalanceProgram.generalRebalancingData.baseSets.push( - await this._rebalancingSetToken.nextSet.callAsync() - ); - - const auctionPriceParameters = await this._rebalancingSetToken.getAuctionPriceParameters.callAsync(); - const auctionStartPrice = auctionPriceParameters[2]; - const auctionPivotPrice = auctionPriceParameters[3]; - this._dataLogger.rebalanceFairValues.push( - (auctionStartPrice.add(auctionPivotPrice)).div(2).round(0, 3) - ); - } - - private async _logPostStartRebalanceDataAsync(txHash: string): Promise { - this._dataLogger.gasProfile.startRebalance = await this._extractGasCostAsync( - txHash - ); - - const biddingParameters = await this._rebalancingSetToken.getBiddingParameters.callAsync(); - this._rebalanceProgram.generalRebalancingData.minimumBid = biddingParameters[0]; - this._rebalanceProgram.generalRebalancingData.initialRemainingSets = biddingParameters[1]; - } - - private _getRecentBaseSet(): Address { - return this._rebalanceProgram.generalRebalancingData.baseSets.slice(-1)[0]; - } - - -} \ No newline at end of file diff --git a/test/scenarios/btc-eth/btcEthRebalancing.spec.ts b/test/scenarios/btc-eth/btcEthRebalancing.spec.ts deleted file mode 100644 index b7af372..0000000 --- a/test/scenarios/btc-eth/btcEthRebalancing.spec.ts +++ /dev/null @@ -1,484 +0,0 @@ -require('module-alias/register'); - -import * as _ from 'lodash'; -import * as ABIDecoder from 'abi-decoder'; -import * as chai from 'chai'; -import * as setProtocolUtils from 'set-protocol-utils'; -import { BigNumber } from 'set-protocol-utils'; -import { SetProtocolTestUtils, Web3Utils } from 'set-protocol-utils'; - -import ChaiSetup from '@utils/chaiSetup'; -import { BigNumberSetup } from '@utils/bigNumberSetup'; -import { - CoreContract, - LinearAuctionPriceCurveContract, - RebalanceAuctionModuleContract, - RebalancingSetTokenContract, - RebalancingSetTokenFactoryContract, - SetTokenContract, - SetTokenFactoryContract, - StandardTokenMockContract, - TransferProxyContract, - VaultContract, - WethMockContract, -} from 'set-protocol-contracts'; -import { Core } from 'set-protocol-contracts/dist/artifacts/ts/Core'; -import { RebalanceAuctionModule } from 'set-protocol-contracts/dist/artifacts/ts/RebalanceAuctionModule'; -import { RebalancingSetToken } from 'set-protocol-contracts/dist/artifacts/ts/RebalancingSetToken'; - -import { - MedianContract, -} from 'set-protocol-oracles'; -import { BTCETHRebalancingManagerContract } from '@utils/contracts'; -import { - DEFAULT_GAS, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, -} from '@utils/constants'; -import { Blockchain } from 'set-protocol-contracts'; -import { getWeb3 } from '@utils/web3Helper'; - -import { ProtocolHelper } from '@utils/helpers/protocolHelper'; -import { ERC20Helper } from '@utils/helpers/erc20Helper'; -import { OracleHelper } from 'set-protocol-oracles'; -import { ManagerHelper } from '@utils/helpers/managerHelper'; - -BigNumberSetup.configure(); -ChaiSetup.configure(); -const web3 = getWeb3(); -const { expect } = chai; -const blockchain = new Blockchain(web3); -const { SetProtocolUtils: SetUtils } = setProtocolUtils; -const web3Utils = new Web3Utils(web3); - - -contract('Rebalancing BTC-ETH 50/50', accounts => { - const [ - deployerAccount, - bidderOneAccount, - bidderTwoAccount, - ] = accounts; - - let rebalancingSetToken: RebalancingSetTokenContract; - - let core: CoreContract; - let transferProxy: TransferProxyContract; - let vault: VaultContract; - let rebalanceAuctionModule: RebalanceAuctionModuleContract; - let factory: SetTokenFactoryContract; - let rebalancingFactory: RebalancingSetTokenFactoryContract; - let linearAuctionPriceCurve: LinearAuctionPriceCurveContract; - let btcethRebalancingManager: BTCETHRebalancingManagerContract; - let btcMedianizer: MedianContract; - let ethMedianizer: MedianContract; - - let wrappedBTC: StandardTokenMockContract; - let wrappedETH: WethMockContract; - let baseBtcEthSet: SetTokenContract; - - const protocolHelper = new ProtocolHelper(deployerAccount); - const erc20Helper = new ERC20Helper(deployerAccount); - const managerHelper = new ManagerHelper(deployerAccount); - const oracleHelper = new OracleHelper(deployerAccount); - - // Initial MKR Price Feed Values - const BTC_PRICE_INITIAL = new BigNumber(3.711).mul(10 ** 21); - const ETH_PRICE_INITIAL = new BigNumber(1.28).mul(10 ** 20); - - const BTC_PRICE_PROPOSAL = BTC_PRICE_INITIAL.mul(1.1); - - // Base Component Constants - const WBTC_DECIMALS = 8; - const WETH_DECIMALS = 18; - const DECIMAL_DIFFERENCE = WETH_DECIMALS - WBTC_DECIMALS; - const ETH_DECIMAL_EXPONENTIATION = new BigNumber(10 ** DECIMAL_DIFFERENCE); - - // Base Set Details - const BTC_ETH_NATURAL_UNIT = new BigNumber(10 ** 10); - const INITIAL_BTC_UNIT = new BigNumber(1); - const INITIAL_ETH_UNIT = BTC_PRICE_INITIAL.div(ETH_PRICE_INITIAL) - .mul(ETH_DECIMAL_EXPONENTIATION) - .mul(INITIAL_BTC_UNIT); - - // Rebalancing Set Details - const REBALANCING_SET_UNIT_SHARES = new BigNumber(1.35).mul(10 ** 6); - const REBALANCING_SET_NATURAL_UNIT = new BigNumber(10 ** 10); - - // Issue Quantity - const BTC_ETH_ISSUE_QUANTITY = new BigNumber(10 ** 18); - const REQUIRED_WETH = BTC_ETH_ISSUE_QUANTITY.div(BTC_ETH_NATURAL_UNIT).mul(INITIAL_ETH_UNIT); - const UNROUNDED_REBALANCING_SET_ISSUE_QUANTITY = BTC_ETH_ISSUE_QUANTITY.mul(REBALANCING_SET_NATURAL_UNIT) - .div(REBALANCING_SET_UNIT_SHARES); - - // Round the number to a certain precision w/o rounding up - const REBALANCING_SET_ISSUE_QUANTITY = UNROUNDED_REBALANCING_SET_ISSUE_QUANTITY - .minus(UNROUNDED_REBALANCING_SET_ISSUE_QUANTITY.modulo(REBALANCING_SET_NATURAL_UNIT)); - - - // Pre-Rebalance Value - const INITIAL_QUANTITY_BASE_SET = REBALANCING_SET_ISSUE_QUANTITY.mul(REBALANCING_SET_UNIT_SHARES) - .div(REBALANCING_SET_NATURAL_UNIT); - const INITIAL_BTC_VALUE = INITIAL_QUANTITY_BASE_SET.mul(INITIAL_BTC_UNIT) - .div(BTC_ETH_NATURAL_UNIT) - .mul(BTC_PRICE_PROPOSAL) - .div(10 ** WBTC_DECIMALS); - const INITIAL_ETH_VALUE = INITIAL_QUANTITY_BASE_SET.mul(INITIAL_ETH_UNIT) - .div(BTC_ETH_NATURAL_UNIT) - .mul(ETH_PRICE_INITIAL) - .div(10 ** WETH_DECIMALS); - const PRE_REBALANCE_VALUE = INITIAL_BTC_VALUE.plus(INITIAL_ETH_VALUE); - - // Rebalancing Details - const SECONDS_PER_DAY = new BigNumber(86400); - const REBALANCE_INTERVAL = new BigNumber(28).mul(SECONDS_PER_DAY); - const PROPOSAL_PERIOD = new BigNumber(1).mul(SECONDS_PER_DAY); - - // Auction Constants - const PRICE_DIVISOR = new BigNumber(1000); - const TIME_TO_PIVOT = SECONDS_PER_DAY; - - // Bid Assumptions - const MINIMUM_BID = PRICE_DIVISOR.mul(REBALANCING_SET_NATURAL_UNIT); - const SECONDS_TO_FAIR_VALUE = TIME_TO_PIVOT.div(2); - const BID_ONE_TIME_AFTER_FAIR_VALUE = new BigNumber(900); - const BID_TWO_TIME_AFTER_FAIR_VALUE = new BigNumber(3600); - const BID_ONE_MAX_INFLOW_ETH = new BigNumber(8).mul(10 ** 17); - const BID_TWO_MAX_INFLOW_ETH = new BigNumber(5).mul(10 ** 17); - const UNROUNDED_BID_ONE_QUANTITY = BTC_ETH_ISSUE_QUANTITY.div(2); - const UNROUNDED_BID_TWO_QUANTITY = BTC_ETH_ISSUE_QUANTITY.div(2).minus(MINIMUM_BID); - const BID_ONE_QUANTITY = UNROUNDED_BID_ONE_QUANTITY.minus(UNROUNDED_BID_ONE_QUANTITY.modulo(MINIMUM_BID)); - const BID_TWO_QUANTITY = UNROUNDED_BID_TWO_QUANTITY.minus(UNROUNDED_BID_TWO_QUANTITY.modulo(MINIMUM_BID)); - const MAX_SLIPPAGE = new BigNumber(0.015); // 1 Percent Slippage - - before(async () => { - ABIDecoder.addABI(Core.abi); - ABIDecoder.addABI(RebalanceAuctionModule.abi); - ABIDecoder.addABI(RebalancingSetToken.abi); - }); - - after(async () => { - ABIDecoder.removeABI(Core.abi); - ABIDecoder.removeABI(RebalanceAuctionModule.abi); - ABIDecoder.removeABI(RebalancingSetToken.abi); - }); - - beforeEach(async () => { - await blockchain.saveSnapshotAsync(); - - vault = await protocolHelper.getDeployedVaultAsync(); - transferProxy = await protocolHelper.getDeployedTransferProxyAsync(); - core = await protocolHelper.getDeployedCoreAsync(); - rebalanceAuctionModule = await protocolHelper.getDeployedRebalanceAuctionModuleAsync(); - - factory = await protocolHelper.getDeployedSetTokenFactoryAsync(); - rebalancingFactory = await protocolHelper.getDeployedRebalancingSetTokenFactoryAsync(); - - linearAuctionPriceCurve = await protocolHelper.getDeployedLinearAuctionPriceCurveAsync(); - - btcMedianizer = await protocolHelper.getDeployedWBTCMedianizerAsync(); - await oracleHelper.addPriceFeedOwnerToMedianizer(btcMedianizer, deployerAccount); - ethMedianizer = await protocolHelper.getDeployedWETHMedianizerAsync(); - await oracleHelper.addPriceFeedOwnerToMedianizer(ethMedianizer, deployerAccount); - - wrappedBTC = await protocolHelper.getDeployedWBTCAsync(); - wrappedETH = await protocolHelper.getDeployedWETHAsync(); - - const btcMultiplier = new BigNumber(1); - const ethMultiplier = new BigNumber(1); - btcethRebalancingManager = await managerHelper.deployBTCETHRebalancingManagerAsync( - core.address, - btcMedianizer.address, - ethMedianizer.address, - wrappedBTC.address, - wrappedETH.address, - factory.address, - linearAuctionPriceCurve.address, - TIME_TO_PIVOT, - [btcMultiplier, ethMultiplier], - [new BigNumber(48), new BigNumber(52)], - ); - - baseBtcEthSet = await protocolHelper.createSetTokenAsync( - core, - factory.address, - [wrappedBTC.address, wrappedETH.address], - [INITIAL_BTC_UNIT, INITIAL_ETH_UNIT], - BTC_ETH_NATURAL_UNIT, - ); - - const rebalancingSetCallData = SetUtils.generateRebalancingSetTokenCallData( - btcethRebalancingManager.address, - PROPOSAL_PERIOD, - REBALANCE_INTERVAL, - ); - - rebalancingSetToken = await protocolHelper.createRebalancingTokenAsync( - core, - rebalancingFactory.address, - [baseBtcEthSet.address], - [REBALANCING_SET_UNIT_SHARES], - REBALANCING_SET_NATURAL_UNIT, - rebalancingSetCallData, - ); - - await oracleHelper.updateMedianizerPriceAsync( - btcMedianizer, - BTC_PRICE_INITIAL, - SetProtocolTestUtils.generateTimestamp(1000), - ); - - await oracleHelper.updateMedianizerPriceAsync( - ethMedianizer, - ETH_PRICE_INITIAL, - SetProtocolTestUtils.generateTimestamp(1000), - ); - - await erc20Helper.approveTransfersAsync( - [wrappedBTC], - transferProxy.address - ); - - await wrappedETH.approve.sendTransactionAsync( - transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: deployerAccount, gas: DEFAULT_GAS } - ); - - // Mint WETH - await wrappedETH.deposit.sendTransactionAsync( - { from: deployerAccount, value: REQUIRED_WETH.toString() } - ); - - // Issue Rebalancing Set to the the deployer - await core.issue.sendTransactionAsync( - baseBtcEthSet.address, - BTC_ETH_ISSUE_QUANTITY, - { from: deployerAccount, gas: DEFAULT_GAS } - ); - - await baseBtcEthSet.approve.sendTransactionAsync( - transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: deployerAccount, gas: DEFAULT_GAS } - ); - - // Issue Rebalancing Set to the the deployer - await core.issue.sendTransactionAsync( - rebalancingSetToken.address, - REBALANCING_SET_ISSUE_QUANTITY, - { from: deployerAccount, gas: DEFAULT_GAS } - ); - - await oracleHelper.updateMedianizerPriceAsync( - btcMedianizer, - BTC_PRICE_PROPOSAL, - SetProtocolTestUtils.generateTimestamp(1000), - ); - - await oracleHelper.updateMedianizerPriceAsync( - ethMedianizer, - ETH_PRICE_INITIAL, - SetProtocolTestUtils.generateTimestamp(1000), - ); - - // Fast forward the rebalance interval - await web3Utils.increaseTime(REBALANCE_INTERVAL.plus(1).toNumber()); - - // Call propose from Rebalance Manager - await btcethRebalancingManager.propose.sendTransactionAsync( - rebalancingSetToken.address, - { from: deployerAccount, gas: DEFAULT_GAS } - ); - - await web3Utils.increaseTime(PROPOSAL_PERIOD.plus(1).toNumber()); - - await rebalancingSetToken.startRebalance.sendTransactionAsync( - { from: deployerAccount, gas: DEFAULT_GAS } - ); - - // Move time to X after Fair Value - await web3Utils.increaseTime(SECONDS_TO_FAIR_VALUE.plus(BID_ONE_TIME_AFTER_FAIR_VALUE).plus(1).toNumber()); - - // Perform Bid 1 - await wrappedETH.approve.sendTransactionAsync( - transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: bidderOneAccount, gas: DEFAULT_GAS } - ); - - // Mint WETH - await wrappedETH.deposit.sendTransactionAsync( - { from: bidderOneAccount, value: BID_ONE_MAX_INFLOW_ETH.toString() } - ); - - await rebalanceAuctionModule.bid.sendTransactionAsync( - rebalancingSetToken.address, - BID_ONE_QUANTITY, - false, - { from: bidderOneAccount, gas: DEFAULT_GAS } - ); - - // Move time to X after Fair Value - await web3Utils.increaseTime(BID_TWO_TIME_AFTER_FAIR_VALUE.minus(BID_ONE_TIME_AFTER_FAIR_VALUE).toNumber()); - - // Perform Bid 2 - await wrappedETH.approve.sendTransactionAsync( - transferProxy.address, - UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { from: bidderTwoAccount, gas: DEFAULT_GAS } - ); - - // Mint WETH - await wrappedETH.deposit.sendTransactionAsync( - { from: bidderTwoAccount, value: BID_TWO_MAX_INFLOW_ETH.toString() } - ); - - await rebalanceAuctionModule.bid.sendTransactionAsync( - rebalancingSetToken.address, - BID_TWO_QUANTITY, - false, - { from: bidderTwoAccount, gas: DEFAULT_GAS } - ); - }); - - afterEach(async () => { - await blockchain.revertAsync(); - }); - - describe('settles the rebalance after 2 bids', async () => { - async function subject(): Promise { - return rebalancingSetToken.settleRebalance.sendTransactionAsync(); - } - - it('should shouldnt exceed 1% slippage', async () => { - await subject(); - - const newBaseSetAddress = await rebalancingSetToken.currentSet.callAsync(); - const newBaseSetInstance = await protocolHelper.getSetTokenAsync(newBaseSetAddress); - - const [bitcoinUnit, etherUnit] = await newBaseSetInstance.getUnits.callAsync(); - - const newBaseSetNaturalUnit = await newBaseSetInstance.naturalUnit.callAsync(); - const currentSetRBSetBalance = await vault.getOwnerBalance.callAsync( - newBaseSetAddress, - rebalancingSetToken.address - ); - - const ownedBTCBalance = currentSetRBSetBalance.mul(bitcoinUnit).div(newBaseSetNaturalUnit); - const ownedETHBalance = currentSetRBSetBalance.mul(etherUnit).div(newBaseSetNaturalUnit); - - const btcValue = ownedBTCBalance.mul(BTC_PRICE_PROPOSAL).div(10 ** WBTC_DECIMALS); - const ethValue = ownedETHBalance.mul(ETH_PRICE_INITIAL).div(10 ** WETH_DECIMALS); - const totalValue = btcValue.plus(ethValue); - - const percentOfPreRebalanceValue = totalValue.div(PRE_REBALANCE_VALUE); - const slippage = new BigNumber(1).minus(percentOfPreRebalanceValue); - - expect(slippage).to.bignumber.be.lessThan(MAX_SLIPPAGE); - }); - - it('should be in the right rebalance state', async () => { - await subject(); - - const rebalanceState = await rebalancingSetToken.rebalanceState.callAsync(); - - expect(rebalanceState).to.bignumber.equal(0); - }); - - it('should have the correct next Set BTC units', async () => { - const expectedBTCUnit = new BigNumber(1); - - await subject(); - - const newBaseSetAddress = await rebalancingSetToken.currentSet.callAsync(); - const newBaseSetInstance = await protocolHelper.getSetTokenAsync(newBaseSetAddress); - - const [bitcoinUnit] = await newBaseSetInstance.getUnits.callAsync(); - expect(bitcoinUnit).to.bignumber.equal(expectedBTCUnit); - }); - - it('should have the correct next Set WETH units', async () => { - const expecetdEtherUnit = new BigNumber(318914062500); - await subject(); - - const newBaseSetAddress = await rebalancingSetToken.currentSet.callAsync(); - const newBaseSetInstance = await protocolHelper.getSetTokenAsync(newBaseSetAddress); - - const [, etherUnit] = await newBaseSetInstance.getUnits.callAsync(); - expect(etherUnit).to.bignumber.equal(expecetdEtherUnit); - }); - - it('should increase bidder ones BTC Balance by a minimum amount', async () => { - const MINIMUM_BTC_OUTFLOW = new BigNumber(0.0247).mul(10 ** WBTC_DECIMALS); - - // Instead of checking balance, we have to check the vault - const preBidBitcoinBalance = await wrappedBTC.balanceOf.callAsync(bidderOneAccount); - - await subject(); - - const btcVaultBalance = await vault.getOwnerBalance.callAsync(wrappedBTC.address, bidderOneAccount); - - await core.withdraw.sendTransactionAsync( - wrappedBTC.address, - btcVaultBalance, - { from: bidderOneAccount, gas: DEFAULT_GAS } - ); - - const postBidBitcoinBalance = await wrappedBTC.balanceOf.callAsync(bidderOneAccount); - - const bitcoinAcquired = postBidBitcoinBalance.minus(preBidBitcoinBalance); - - expect(bitcoinAcquired).to.bignumber.be.greaterThan(MINIMUM_BTC_OUTFLOW); - }); - - it('should decrease bidder ones WETH Balance by a maximum amount', async () => { - const MAXIMUM_ETH_INFLOW = new BigNumber(0.7).mul(10 ** WETH_DECIMALS); - - const preBidWethBalance = await wrappedETH.balanceOf.callAsync(bidderOneAccount); - - await subject(); - - const postBidWethBalance = await wrappedETH.balanceOf.callAsync(bidderOneAccount); - - const wethSpent = preBidWethBalance.minus(postBidWethBalance); - - expect(wethSpent).to.bignumber.be.lessThan(MAXIMUM_ETH_INFLOW); - }); - - it('should increase bidder twos BTC Balance by a minimum amount', async () => { - const MINIMUM_BTC_OUTFLOW = new BigNumber(0.03).mul(10 ** WBTC_DECIMALS); - - // Instead of checking balance, we have to check the vault - const preBidBitcoinBalance = await wrappedBTC.balanceOf.callAsync(bidderTwoAccount); - - await subject(); - - const btcVaultBalance = await vault.getOwnerBalance.callAsync(wrappedBTC.address, bidderTwoAccount); - - await core.withdraw.sendTransactionAsync( - wrappedBTC.address, - btcVaultBalance, - { from: bidderTwoAccount, gas: DEFAULT_GAS } - ); - - const postBidBitcoinBalance = await wrappedBTC.balanceOf.callAsync(bidderTwoAccount); - - const bitcoinAcquired = postBidBitcoinBalance.minus(preBidBitcoinBalance); - - expect(bitcoinAcquired).to.bignumber.be.greaterThan(MINIMUM_BTC_OUTFLOW); - }); - - it('should decrease bidder two WETH Balance by a maximum amount', async () => { - const MAXIMUM_ETH_INFLOW = new BigNumber(0.5).mul(10 ** WETH_DECIMALS); - - const preBidWethBalance = await wrappedETH.balanceOf.callAsync(bidderTwoAccount); - - await subject(); - - const postBidWethBalance = await wrappedETH.balanceOf.callAsync(bidderTwoAccount); - - const wethSpent = preBidWethBalance.minus(postBidWethBalance); - - expect(wethSpent).to.bignumber.be.lessThan(MAXIMUM_ETH_INFLOW); - }); - }); -}); diff --git a/test/scenarios/btc-eth/scenarioData.ts b/test/scenarios/btc-eth/scenarioData.ts deleted file mode 100644 index b234d81..0000000 --- a/test/scenarios/btc-eth/scenarioData.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { BigNumber } from 'set-protocol-utils'; - -import CONSTANTS from '../constants'; - -import { - BidTxn, - GeneralRebalancingData, - InitializationParameters, - IssuanceTxn, - IssuanceSchedule, - FullRebalanceProgram, - SingleRebalanceCycleScenario, - TokenPrices -} from './types'; - -export function getScenarioData(accounts): FullRebalanceProgram { - const initializationParams: InitializationParameters = getInitializationData(); - - const generalRebalancingData: GeneralRebalancingData = { - baseSets: [], - minimumBid: new BigNumber(0), - initialRemainingSets: new BigNumber(0), - }; - const cycleData = getCycleData(accounts); - const rebalanceIterations = 2; - - return { - rebalanceIterations, - initializationParams, - generalRebalancingData, - cycleData, - }; -} - -function getCycleData(accounts): SingleRebalanceCycleScenario[] { - const BTC_PRICE_PROPOSAL = CONSTANTS.WBTC.INITIAL_FEED_PRICE.mul(1.1); - - // Bid Assumptions - const BID_ONE_PRICE = new BigNumber(0.004776); - const BID_TWO_PRICE = new BigNumber(0.019102); - const BID_ONE_QUANTITY = new BigNumber(0.5); - const BID_TWO_QUANTITY = new BigNumber(0.5); - - // Rebalancing Cycle 1 - const issueRedeemScheduleOne: IssuanceSchedule = { - issuances: [], - redemptions: [], - }; - const priceUpdateOne: TokenPrices = { - WBTCPrice: BTC_PRICE_PROPOSAL, - WETHPrice: CONSTANTS.WETH.INITIAL_FEED_PRICE, - }; - const bidTxnOne: BidTxn = { - sender: accounts[1], - amount: BID_ONE_QUANTITY, - price: BID_ONE_PRICE, - }; - const bidTxnTwo: BidTxn = { - sender: accounts[2], - amount: BID_TWO_QUANTITY, - price: BID_TWO_PRICE, - }; - const biddingScheduleOne: BidTxn[] = [bidTxnOne, bidTxnTwo]; - const cycleScenarioOne: SingleRebalanceCycleScenario = { - issueRedeemSchedule: issueRedeemScheduleOne, - priceUpdate: priceUpdateOne, - biddingSchedule: biddingScheduleOne, - }; - - // Rebalancing Cycle 2 - const issueTxnOne: IssuanceTxn = { - sender: accounts[5], - amount: new BigNumber(10 ** 21), - }; - const redeemTxnOne: IssuanceTxn = { - sender: accounts[6], - amount: new BigNumber(5 * 10 ** 20), - }; - const issueRedeemScheduleTwo: IssuanceSchedule = { - issuances: [issueTxnOne], - redemptions: [redeemTxnOne], - }; - const priceUpdateTwo: TokenPrices = { - WBTCPrice: new BigNumber(3.983).mul(10 ** 22), - WETHPrice: new BigNumber(1.15).mul(10 ** 21), - }; - const cycleTwoBidTxnOne: BidTxn = { - sender: accounts[3], - amount: new BigNumber(0.2), - price: new BigNumber(-0.005), - }; - const cycleTwoBidTxnTwo: BidTxn = { - sender: accounts[4], - amount: new BigNumber(0.6), - price: new BigNumber(0.01), - }; - const cycleTwoBidTxnThree: BidTxn = { - sender: accounts[2], - amount: new BigNumber(0.2), - price: new BigNumber(0.015), - }; - const biddingScheduleTwo: BidTxn[] = [cycleTwoBidTxnOne, cycleTwoBidTxnTwo, cycleTwoBidTxnThree]; - const cycleScenarioTwo: SingleRebalanceCycleScenario = { - issueRedeemSchedule: issueRedeemScheduleTwo, - priceUpdate: priceUpdateTwo, - biddingSchedule: biddingScheduleTwo, - }; - - return [cycleScenarioOne, cycleScenarioTwo]; -} - -function getInitializationData(): InitializationParameters { - // Rebalancing Set Details - const REBALANCING_SET_UNIT_SHARES = new BigNumber(1.35).mul(10 ** 6); - const REBALANCING_SET_NATURAL_UNIT = new BigNumber(10 ** 10); - - // RB Manager Properties - const btcMultiplier = new BigNumber(1); - const ethMultiplier = new BigNumber(1); - const lowerAllocationBound = new BigNumber(48); - const upperAllocationBound = new BigNumber(48); - - // Rebalancing Details - const REBALANCE_INTERVAL = new BigNumber(28).mul(CONSTANTS.SECONDS_PER_DAY); - const PROPOSAL_PERIOD = new BigNumber(1).mul(CONSTANTS.SECONDS_PER_DAY); - const TIME_TO_PIVOT = CONSTANTS.SECONDS_PER_DAY; - const PRICE_DIVISOR = new BigNumber(1000); - - // Issue Quantity - const BTC_ETH_ISSUE_QUANTITY = new BigNumber(10 ** 18); - const UNROUNDED_REBALANCING_SET_ISSUE_QUANTITY = BTC_ETH_ISSUE_QUANTITY - .mul(REBALANCING_SET_NATURAL_UNIT) - .div(REBALANCING_SET_UNIT_SHARES); - - // Round the number to a certain precision w/o rounding up - const REBALANCING_SET_ISSUE_QUANTITY = UNROUNDED_REBALANCING_SET_ISSUE_QUANTITY - .minus(UNROUNDED_REBALANCING_SET_ISSUE_QUANTITY - .modulo(REBALANCING_SET_NATURAL_UNIT)); - - // Base Component Constants - const DECIMAL_DIFFERENCE = CONSTANTS.WETH.DECIMALS - CONSTANTS.WBTC.DECIMALS; - const ETH_DECIMAL_EXPONENTIATION = new BigNumber(10 ** DECIMAL_DIFFERENCE); - - // Base Set Details - const BTC_ETH_NATURAL_UNIT = new BigNumber(10 ** 10); - const INITIAL_BTC_UNIT = new BigNumber(1); - const INITIAL_ETH_UNIT = CONSTANTS.WBTC.INITIAL_FEED_PRICE - .div(CONSTANTS.WETH.INITIAL_FEED_PRICE) - .mul(ETH_DECIMAL_EXPONENTIATION) - .mul(CONSTANTS.WBTC.DEFAULT_UNIT); - - // Create Full Rebalance Object - const initialTokenPrices: TokenPrices = { - WBTCPrice: CONSTANTS.WBTC.INITIAL_FEED_PRICE, - WETHPrice: CONSTANTS.WETH.INITIAL_FEED_PRICE, - }; - return { - btcMultiplier, - ethMultiplier, - lowerAllocationBound, - upperAllocationBound, - initialTokenPrices, - initialSetIssueQuantity: BTC_ETH_ISSUE_QUANTITY, - initialSetUnits: [INITIAL_BTC_UNIT, INITIAL_ETH_UNIT], - initialSetNaturalUnit: BTC_ETH_NATURAL_UNIT, - rebalancingSetIssueQuantity: REBALANCING_SET_ISSUE_QUANTITY, - rebalancingSetUnitShares: [REBALANCING_SET_UNIT_SHARES], - rebalancingSetNaturalUnit: REBALANCING_SET_NATURAL_UNIT, - proposalPeriod: PROPOSAL_PERIOD, - rebalanceInterval: REBALANCE_INTERVAL, - auctionTimeToPivot: TIME_TO_PIVOT, - priceDivisor: PRICE_DIVISOR, - }; -} - diff --git a/test/scenarios/btc-eth/types.ts b/test/scenarios/btc-eth/types.ts deleted file mode 100644 index c432dbd..0000000 --- a/test/scenarios/btc-eth/types.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { Address } from 'set-protocol-utils'; -import { BigNumber } from 'set-protocol-utils'; - -export interface IssuanceSchedule { - issuances: IssuanceTxn[]; - redemptions: IssuanceTxn[]; -} - -export interface UserAccountData { - bidderOne: Address; - bidderTwo: Address; - bidderThree: Address; - bidderFour: Address; - bidderFive: Address; - tokenOwnerOne: Address; - tokenOwnerTwo: Address; - tokenOwnerThree: Address; - tokenOwnerFour: Address; - tokenOwnerFive: Address; - bidders: Address[]; - tokenOwners: Address[]; -} - -export interface TokenBalances { - WBTC: BigNumber; - WETH: BigNumber; - RebalancingSet: BigNumber; -} - -export interface UserTokenBalances { - bidderOne: TokenBalances; - bidderTwo: TokenBalances; - bidderThree: TokenBalances; - bidderFour: TokenBalances; - bidderFive: TokenBalances; - tokenOwnerOne: TokenBalances; - tokenOwnerTwo: TokenBalances; - tokenOwnerThree: TokenBalances; - tokenOwnerFour: TokenBalances; - tokenOwnerFive: TokenBalances; -} - -export interface GasProfiler { - coreMock?: BigNumber; - transferProxy?: BigNumber; - vault?: BigNumber; - rebalanceAuctionModule?: BigNumber; - factory?: BigNumber; - rebalancingComponentWhiteList?: BigNumber; - rebalancingFactory?: BigNumber; - linearAuctionPriceCurve?: BigNumber; - btcethRebalancingManager?: BigNumber; - addTokenToWhiteList?: BigNumber; - createInitialBaseSet?: BigNumber; - createRebalancingSet?: BigNumber; - issueInitialBaseSet?: BigNumber; - issueRebalancingSet?: BigNumber; - redeemRebalancingSet?: BigNumber; - proposeRebalance?: BigNumber; - startRebalance?: BigNumber; - bid?: BigNumber; - settleRebalance?: BigNumber; -} - -export interface TokenPrices { - WBTCPrice: BigNumber; - WETHPrice: BigNumber; -} - -export interface BidTxn { - sender: Address; - amount: BigNumber; - price: BigNumber; -} - -export interface IssuanceTxn { - sender: Address; - amount: BigNumber; -} - -export interface InitializationParameters { - btcMultiplier: BigNumber; - ethMultiplier: BigNumber; - lowerAllocationBound: BigNumber; - upperAllocationBound: BigNumber; - initialTokenPrices: TokenPrices; - initialSetIssueQuantity: BigNumber; - initialSetUnits: BigNumber[]; - initialSetNaturalUnit: BigNumber; - rebalancingSetIssueQuantity: BigNumber; - rebalancingSetUnitShares: BigNumber[]; - rebalancingSetNaturalUnit: BigNumber; - proposalPeriod: BigNumber; - rebalanceInterval: BigNumber; - auctionTimeToPivot: BigNumber; - priceDivisor: BigNumber; -} - -export interface GeneralRebalancingData { - baseSets: Address[]; - minimumBid: BigNumber; - initialRemainingSets: BigNumber; -} - -export interface SingleRebalanceCycleScenario { - issueRedeemSchedule: IssuanceSchedule; - priceUpdate: TokenPrices; - biddingSchedule: BidTxn[]; -} - -export interface FullRebalanceProgram { - rebalanceIterations: number; - initializationParams: InitializationParameters; - generalRebalancingData: GeneralRebalancingData; - cycleData: SingleRebalanceCycleScenario[]; -} - -export interface DataOutput { - collateralizingSets?: BigNumber[]; - issuedRebalancingSets?: BigNumber[]; - rebalanceFairValues?: BigNumber[]; - rebalancingSetComponentDust?: TokenBalances[]; - rebalancingSetBaseSetDust?: BigNumber[]; - gasProfile: GasProfiler; -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 4bcb12f..8a548e8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,8 @@ "node_modules/@types" ], "esModuleInterop": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "skipLibCheck": true }, "include": [ "types/**/*.ts", diff --git a/utils/compoundSnapshotAddresses.ts b/utils/compoundSnapshotAddresses.ts deleted file mode 100644 index 3f7cc99..0000000 --- a/utils/compoundSnapshotAddresses.ts +++ /dev/null @@ -1,19 +0,0 @@ - -export const PERMISSIONED_ACCOUNTS = { - admin: '0x5409ED021D9299bf6814279A6A1411A7e866A631', -}; - -export const CONTRACTS = { - PriceOracle: '0x8E1fF02637Cb5E39f2fA36c14706aa348B065B09', - Comptroller: '0x2727E688B8fD40b198cd5Fe6E408e00494a06F07', - InterestRateModel: '0x22ebc052F43A88Efa06379426120718170F2204e', -}; - - -export const BYTECODE = { - // Compiled with Solidity v0.5.8 - // https://github.com/compound-finance/compound-protocol - // Based on Commit Hash: 681833a557a282fba5441b7d49edb05153bb28ec - // tslint:disable-next-line - CErc20: '0x60806040523480156200001157600080fd5b50604051620052cd380380620052cd83398101806040526101008110156200003857600080fd5b8151602083015160408401516060850151608086018051949693959294919392830192916401000000008111156200006f57600080fd5b820160208101848111156200008357600080fd5b81516401000000008111828201871017156200009e57600080fd5b50509291906020018051640100000000811115620000bb57600080fd5b82016020810184811115620000cf57600080fd5b8151640100000000811182820187101715620000ea57600080fd5b5050602082015160409092015160016000556007879055909350909150868686868686868462000166576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806200529d6030913960400191505060405180910390fd5b60038054610100600160a81b03191633610100021790556000620001918862000397602090811b901c565b905080156200020157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f53657474696e6720636f6d7074726f6c6c6572206661696c6564000000000000604482015290519081900360640190fd5b620002116200052f60201b60201c565b600955670de0b6b3a7640000600a55620002328762000534602090811b901c565b905080156200028d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806200527b6022913960400191505060405180910390fd5b8451620002a29060019060208801906200075b565b508351620002b89060029060208701906200075b565b50506003805460ff191660ff9390931692909217610100600160a81b0319166101006001600160a01b039283160217909155601180546001600160a01b0319168f83161790819055604080517f18160ddd00000000000000000000000000000000000000000000000000000000815290519190921696506318160ddd9550600480830195506020945090925090829003018186803b1580156200035a57600080fd5b505afa1580156200036f573d6000803e3d6000fd5b505050506040513d60208110156200038657600080fd5b50620007fd98505050505050505050565b60035460009061010090046001600160a01b03163314620003ce57620003c66001603f620006eb60201b60201c565b90506200052a565b600554604080517e7e3dd200000000000000000000000000000000000000000000000000000000815290516001600160a01b0392831692851691627e3dd2916004808301926020929190829003018186803b1580156200042d57600080fd5b505afa15801562000442573d6000803e3d6000fd5b505050506040513d60208110156200045957600080fd5b5051620004c757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d9281900390910190a160005b9150505b919050565b435b90565b600354600090819061010090046001600160a01b031633146200056e576200056560016042620006eb60201b60201c565b9150506200052a565b6200057e6200052f60201b60201c565b600954146200059b5762000565600a6041620006eb60201b60201c565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b158015620005ed57600080fd5b505afa15801562000602573d6000803e3d6000fd5b505050506040513d60208110156200061957600080fd5b50516200068757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a1600062000526565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360108111156200071b57fe5b83604d8111156200072857fe5b604080519283526020830191909152600082820152519081900360600190a18260108111156200075457fe5b9392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200079e57805160ff1916838001178555620007ce565b82800160010185558215620007ce579182015b82811115620007ce578251825591602001919060010190620007b1565b50620007dc929150620007e0565b5090565b6200053191905b80821115620007dc5760008155600101620007e7565b614a6e806200080d6000396000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c80638f840ddd1161015c578063c37f68e2116100ce578063f3fdb15a11610087578063f3fdb15a1461071e578063f5e3c46214610726578063f851a4401461075c578063f8f9da2814610764578063fca7820b1461076c578063fe9c44ae146107895761028a565b8063c37f68e21461063c578063c5ebeaec14610688578063db006a75146106a5578063dd62ed3e146106c2578063e9c714f2146106f0578063f2b3abbd146106f85761028a565b8063a9059cbb11610120578063a9059cbb1461059c578063aa5af0fd146105c8578063ae9d70b0146105d0578063b2a02ff1146105d8578063b71d1a0c1461060e578063bd6d894d146106345761028a565b80638f840ddd1461054157806395d89b411461054957806395dd919314610551578063a0712d6814610577578063a6afed95146105945761028a565b80633af9e66911610200578063675d972c116101b9578063675d972c146104de5780636c540baf146104e65780636f307dc3146104ee57806370a08231146104f657806373acee981461051c578063852a12e3146105245761028a565b80633af9e6691461045d5780633b1d21a2146104835780634576b5db1461048b57806347bd3718146104b15780635fe3b567146104b9578063601a0bf1146104c15761028a565b806318160ddd1161025257806318160ddd146103a9578063182df0f5146103b157806323b872dd146103b95780632608f818146103ef578063267822471461041b578063313ce5671461043f5761028a565b806306fdde031461028f578063095ea7b31461030c5780630e7527021461034c578063173b99041461037b57806317bfdfbc14610383575b600080fd5b610297610791565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102d15781810151838201526020016102b9565b50505050905090810190601f1680156102fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103386004803603604081101561032257600080fd5b506001600160a01b03813516906020013561081e565b604080519115158252519081900360200190f35b6103696004803603602081101561036257600080fd5b503561088b565b60408051918252519081900360200190f35b61036961089e565b6103696004803603602081101561039957600080fd5b50356001600160a01b03166108a4565b610369610967565b61036961096d565b610338600480360360608110156103cf57600080fd5b506001600160a01b038135811691602081013590911690604001356109d3565b6103696004803603604081101561040557600080fd5b506001600160a01b038135169060200135610a3f565b610423610a52565b604080516001600160a01b039092168252519081900360200190f35b610447610a61565b6040805160ff9092168252519081900360200190f35b6103696004803603602081101561047357600080fd5b50356001600160a01b0316610a6a565b610369610ad8565b610369600480360360208110156104a157600080fd5b50356001600160a01b0316610ae7565b610369610c41565b610423610c47565b610369600480360360208110156104d757600080fd5b5035610c56565b610369610ce4565b610369610cea565b610423610cf0565b6103696004803603602081101561050c57600080fd5b50356001600160a01b0316610cff565b610369610d1a565b6103696004803603602081101561053a57600080fd5b5035610dd4565b610369610ddf565b610297610de5565b6103696004803603602081101561056757600080fd5b50356001600160a01b0316610e3d565b6103696004803603602081101561058d57600080fd5b5035610e9d565b610369610ea8565b610338600480360360408110156105b257600080fd5b506001600160a01b0381351690602001356112a3565b61036961130e565b610369611314565b610369600480360360608110156105ee57600080fd5b506001600160a01b038135811691602081013590911690604001356115ee565b6103696004803603602081101561062457600080fd5b50356001600160a01b03166118ab565b610369611937565b6106626004803603602081101561065257600080fd5b50356001600160a01b03166119f2565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6103696004803603602081101561069e57600080fd5b5035611a87565b610369600480360360208110156106bb57600080fd5b5035611a92565b610369600480360360408110156106d857600080fd5b506001600160a01b0381358116916020013516611a9d565b610369611ac8565b6103696004803603602081101561070e57600080fd5b50356001600160a01b0316611bcb565b610423611c05565b6103696004803603606081101561073c57600080fd5b506001600160a01b03813581169160208101359160409091013516611c14565b610423611c21565b610369611c35565b6103696004803603602081101561078257600080fd5b5035611d14565b610338611d4e565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156108165780601f106107eb57610100808354040283529160200191610816565b820191906000526020600020905b8154815290600101906020018083116107f957829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855290835281842086905581518681529151939493909284927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a360019150505b92915050565b600061089682611d53565b90505b919050565b60085481565b60008054600101808255816108b7610ea8565b1461090c5760408051600160e51b62461bcd02815260206004820152601660248201527f61636372756520696e746572657374206661696c656400000000000000000000604482015290519081900360640190fd5b61091583610e3d565b91505b60005481146109615760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b50919050565b600d5481565b600080600061097a611d8f565b9092509050600082600381111561098d57fe5b146109cc57604051600160e51b62461bcd0281526004018080602001828103825260358152602001806149b66035913960400191505060405180910390fd5b9150505b90565b60008054600101808255816109ea33878787611e3d565b1491505b6000548114610a375760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b509392505050565b6000610a4b8383612151565b9392505050565b6004546001600160a01b031681565b60035460ff1681565b6000610a7461470f565b6040518060200160405280610a87611937565b90526001600160a01b0384166000908152600e6020526040812054919250908190610ab39084906121e1565b90925090506000826003811115610ac657fe5b14610ad057600080fd5b949350505050565b6000610ae2612235565b905090565b60035460009061010090046001600160a01b03163314610b1457610b0d6001603f6122b8565b9050610899565b60055460408051600160e11b623f1ee902815290516001600160a01b0392831692851691627e3dd2916004808301926020929190829003018186803b158015610b5c57600080fd5b505afa158015610b70573d6000803e3d6000fd5b505050506040513d6020811015610b8657600080fd5b5051610bdc5760408051600160e51b62461bcd02815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d9281900390910190a160009392505050565b600b5481565b6005546001600160a01b031681565b6000805460010180825581610c69610ea8565b90508015610c8f57610c87816010811115610c8057fe5b60306122b8565b925050610918565b610c988461231e565b92505060005481146109615760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b60075481565b60095481565b6011546001600160a01b031681565b6001600160a01b03166000908152600e602052604090205490565b6000805460010180825581610d2d610ea8565b14610d825760408051600160e51b62461bcd02815260206004820152601660248201527f61636372756520696e746572657374206661696c656400000000000000000000604482015290519081900360640190fd5b600b5491506000548114610dd05760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b5090565b6000610896826124b1565b600c5481565b6002805460408051602060018416156101000260001901909316849004601f810184900484028201840190925281815292918301828280156108165780601f106107eb57610100808354040283529160200191610816565b6000806000610e4b846124ee565b90925090506000826003811115610e5e57fe5b14610a4b57604051600160e51b62461bcd02815260040180806020018281038252603781526020018061488a6037913960400191505060405180910390fd5b6000610896826125a2565b6000610eb2614722565b6006546001600160a01b03166315f24053610ecb612235565b600b54600c546040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050604080518083038186803b158015610f1257600080fd5b505afa158015610f26573d6000803e3d6000fd5b505050506040513d6040811015610f3c57600080fd5b508051602091820151604084018190529183015265048c273950001015610fad5760408051600160e51b62461bcd02815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c79206869676800000000604482015290519081900360640190fd5b602081015115610fd057610fc86005600283602001516125dd565b9150506109d0565b610fd8612643565b60608201819052600954610fec9190612647565b608083018190528282600381111561100057fe5b600381111561100b57fe5b905250600090508151600381111561101f57fe5b1461102657fe5b61104660405180602001604052808360400151815250826080015161266a565b60a083018190528282600381111561105a57fe5b600381111561106557fe5b905250600090508151600381111561107957fe5b1461109a57610fc8600960068360000151600381111561109557fe5b6125dd565b6110aa8160a00151600b546121e1565b60c08301819052828260038111156110be57fe5b60038111156110c957fe5b90525060009050815160038111156110dd57fe5b146110f957610fc8600960018360000151600381111561109557fe5b6111098160c00151600b546126d2565b60e083018190528282600381111561111d57fe5b600381111561112857fe5b905250600090508151600381111561113c57fe5b1461115857610fc8600960048360000151600381111561109557fe5b61117960405180602001604052806008548152508260c00151600c546126f8565b61010083018190528282600381111561118e57fe5b600381111561119957fe5b90525060009050815160038111156111ad57fe5b146111c957610fc8600960058360000151600381111561109557fe5b6111dc8160a00151600a54600a546126f8565b6101208301819052828260038111156111f157fe5b60038111156111fc57fe5b905250600090508151600381111561121057fe5b1461122c57610fc8600960038360000151600381111561109557fe5b606080820151600955610120820151600a81905560e0830151600b819055610100840151600c5560c08401516040805191825260208201939093528083019190915290517f875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9929181900390910190a1600091505090565b60008054600101808255816112ba33338787611e3d565b1491505b60005481146113075760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b5092915050565b600a5481565b60008061131f61096d565b60065490915060009081906001600160a01b03166315f24053611340612235565b600b54600c546040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050604080518083038186803b15801561138757600080fd5b505afa15801561139b573d6000803e3d6000fd5b505050506040513d60408110156113b157600080fd5b508051602090910151909250905081156113ff57604051600160e51b62461bcd0281526004018080602001828103825260318152602001806149296031913960400191505060405180910390fd5b600061140961470f565b611423604051806020016040528087815250600d5461266a565b9092509050600082600381111561143657fe5b1461147557604051600160e51b62461bcd0281526004018080602001828103825260318152602001806148c16031913960400191505060405180910390fd5b600061147f61470f565b61148b600b5484612754565b9092509050600082600381111561149e57fe5b146114dd57604051600160e51b62461bcd0281526004018080602001828103825260318152602001806148056031913960400191505060405180910390fd5b60006114e761470f565b6115176040518060200160405280670de0b6b3a764000081525060405180602001604052806008548152506127b3565b9092509050600082600381111561152a57fe5b1461156957604051600160e51b62461bcd02815260040180806020018281038252603c81526020018061497a603c913960400191505060405180910390fd5b600061157361470f565b61158c60405180602001604052808b81525084876127ed565b9092509050600082600381111561159f57fe5b146115de57604051600160e51b62461bcd0281526004018080602001828103825260318152602001806148596031913960400191505060405180910390fd5b519a505050505050505050505090565b6000805460010180825560055460408051600160e01b63d02f73510281523060048201523360248201526001600160a01b03888116604483015287811660648301526084820187905291518593929092169163d02f73519160a48082019260209290919082900301818787803b15801561166757600080fd5b505af115801561167b573d6000803e3d6000fd5b505050506040513d602081101561169157600080fd5b5051905080156116b0576116a86003601b836125dd565b9250506109ee565b856001600160a01b0316856001600160a01b031614156116d6576116a86006601c6122b8565b6001600160a01b0385166000908152600e6020526040812054819081906116fd9088612647565b9093509150600083600381111561171057fe5b14611733576117286009601a85600381111561109557fe5b9550505050506109ee565b6001600160a01b0389166000908152600e602052604090205461175690886126d2565b9093509050600083600381111561176957fe5b14611781576117286009601985600381111561109557fe5b6001600160a01b038089166000818152600e60209081526040808320879055938d168083529184902085905583518b81529351919360008051602061495a833981519152929081900390910190a360055460408051600160e01b636d35bf910281523060048201523360248201526001600160a01b038c811660448301528b81166064830152608482018b905291519190921691636d35bf919160a480830192600092919082900301818387803b15801561183b57600080fd5b505af115801561184f573d6000803e3d6000fd5b506000925061185c915050565b9550505050506000548114610a375760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b60035460009061010090046001600160a01b031633146118d157610b0d600160456122b8565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a16000610a4b565b600080546001018082558161194a610ea8565b1461199f5760408051600160e51b62461bcd02815260206004820152601660248201527f61636372756520696e746572657374206661696c656400000000000000000000604482015290519081900360640190fd5b6119a761096d565b91506000548114610dd05760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b6001600160a01b0381166000908152600e6020526040812054819081908190818080611a1d896124ee565b935090506000816003811115611a2f57fe5b14611a4d5760095b975060009650869550859450611a809350505050565b611a55611d8f565b925090506000816003811115611a6757fe5b14611a73576009611a37565b5060009650919450925090505b9193509193565b600061089682612837565b600061089682612872565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6004546000906001600160a01b031633141580611ae3575033155b15611afb57611af4600160006122b8565b90506109d0565b60038054600480546001600160a01b03818116610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401528351909391927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600454604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160009250505090565b600080611bd6610ea8565b90508015611bfc57611bf4816010811115611bed57fe5b60406122b8565b915050610899565b610a4b836128a8565b6006546001600160a01b031681565b6000610ad0848484612a20565b60035461010090046001600160a01b031681565b600654600090819081906001600160a01b03166315f24053611c55612235565b600b54600c546040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050604080518083038186803b158015611c9c57600080fd5b505afa158015611cb0573d6000803e3d6000fd5b505050506040513d6040811015611cc657600080fd5b508051602090910151909250905081156109cc57604051600160e51b62461bcd0281526004018080602001828103825260378152602001806148f26037913960400191505060405180910390fd5b6000805460010180825581611d27610ea8565b90508015611d4557610c87816010811115611d3e57fe5b60466122b8565b610c9884612b2e565b600181565b6000805460010180825581611d66610ea8565b90508015611d8457610c87816010811115611d7d57fe5b60366122b8565b610c98333386612bd6565b600080600d5460001415611daa575050600754600090611e39565b6000611db4612235565b90506000611dc061470f565b6000611dd184600b54600c54613032565b935090506000816003811115611de357fe5b14611df757945060009350611e3992505050565b611e0383600d54613070565b925090506000816003811115611e1557fe5b14611e2957945060009350611e3992505050565b5051600094509250611e39915050565b9091565b60055460408051600160e31b6317b9b84b0281523060048201526001600160a01b03868116602483015285811660448301526064820185905291516000938493169163bdcdc25891608480830192602092919082900301818787803b158015611ea557600080fd5b505af1158015611eb9573d6000803e3d6000fd5b505050506040513d6020811015611ecf57600080fd5b505190508015611eee57611ee66003604a836125dd565b915050610ad0565b836001600160a01b0316856001600160a01b03161415611f1457611ee66002604b6122b8565b60006001600160a01b038781169087161415611f335750600019611f5b565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b600080600080611f6b8589612647565b90945092506000846003811115611f7e57fe5b14611f9c57611f8f6009604b6122b8565b9650505050505050610ad0565b6001600160a01b038a166000908152600e6020526040902054611fbf9089612647565b90945091506000846003811115611fd257fe5b14611fe357611f8f6009604c6122b8565b6001600160a01b0389166000908152600e602052604090205461200690896126d2565b9094509050600084600381111561201957fe5b1461202a57611f8f6009604d6122b8565b6001600160a01b03808b166000908152600e6020526040808220859055918b168152208190556000198514612082576001600160a01b03808b166000908152600f60209081526040808320938f168352929052208390555b886001600160a01b03168a6001600160a01b031660008051602061495a8339815191528a6040518082815260200191505060405180910390a360055460408051600160e11b63352b4a3f0281523060048201526001600160a01b038d811660248301528c81166044830152606482018c905291519190921691636a56947e91608480830192600092919082900301818387803b15801561212157600080fd5b505af1158015612135573d6000803e3d6000fd5b5060009250612142915050565b9b9a5050505050505050505050565b6000805460010180825581612164610ea8565b9050801561218a5761218281601081111561217b57fe5b60356122b8565b9250506112be565b612195338686612bd6565b92505060005481146113075760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b60008060006121ee61470f565b6121f8868661266a565b9092509050600082600381111561220b57fe5b1461221c575091506000905061222e565b600061222782613120565b9350935050505b9250929050565b60115460408051600160e01b6370a0823102815230600482015290516000926001600160a01b03169182916370a0823191602480820192602092909190829003018186803b15801561228657600080fd5b505afa15801561229a573d6000803e3d6000fd5b505050506040513d60208110156122b057600080fd5b505191505090565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360108111156122e757fe5b83604d8111156122f357fe5b604080519283526020830191909152600082820152519081900360600190a1826010811115610a4b57fe5b6003546000908190819061010090046001600160a01b0316331461235157612348600160316122b8565b92505050610899565b612359612643565b6009541461236d57612348600a60336122b8565b83612376612235565b101561238857612348600e60326122b8565b600c5484111561239e57612348600260346122b8565b50600c54838103908111156123e757604051600160e51b62461bcd028152600401808060200182810382526024815260200180614a1f6024913960400191505060405180910390fd5b600c8190556003546124079061010090046001600160a01b03168561312f565b9150600082601081111561241757fe5b1461245657604051600160e51b62461bcd0281526004018080602001828103825260238152602001806148366023913960400191505060405180910390fd5b600354604080516101009092046001600160a01b0316825260208201869052818101839052517f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e916060908290030190a16000949350505050565b60008054600101808255816124c4610ea8565b905080156124e257610c878160108111156124db57fe5b60276122b8565b610c98336000866131ee565b6001600160a01b03811660009081526010602052604081208054829182918291829161252557506000945084935061259d92505050565b6125358160000154600a54613703565b9094509250600084600381111561254857fe5b1461255d57509193506000925061259d915050565b61256b838260010154613742565b9094509150600084600381111561257e57fe5b1461259357509193506000925061259d915050565b5060009450925050505b915091565b60008054600101808255816125b5610ea8565b905080156125d357610c878160108111156125cc57fe5b601e6122b8565b610c98338561376d565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601081111561260c57fe5b84604d81111561261857fe5b604080519283526020830191909152818101859052519081900360600190a1836010811115610ad057fe5b4390565b60008083831161265e57506000905081830361222e565b5060039050600061222e565b600061267461470f565b600080612685866000015186613703565b9092509050600082600381111561269857fe5b146126b75750604080516020810190915260008152909250905061222e565b60408051602081019091529081526000969095509350505050565b6000808383018481106126ea5760009250905061222e565b50600291506000905061222e565b600080600061270561470f565b61270f878761266a565b9092509050600082600381111561272257fe5b14612733575091506000905061274c565b61274561273f82613120565b866126d2565b9350935050505b935093915050565b600061275e61470f565b600080612773670de0b6b3a764000087613703565b9092509050600082600381111561278657fe5b146127a55750604080516020810190915260008152909250905061222e565b612227818660000151613070565b60006127bd61470f565b6000806127d286600001518660000151612647565b60408051602081019091529081529097909650945050505050565b60006127f761470f565b600061280161470f565b61280b8787613bbb565b9092509050600082600381111561281e57fe5b1461282d57909250905061274c565b6127458186613bbb565b600080546001018082558161284a610ea8565b9050801561286857610c8781601081111561286157fe5b60086122b8565b610c983385613ca4565b6000805460010180825581612885610ea8565b9050801561289c57610c878160108111156124db57fe5b610c98338560006131ee565b600354600090819061010090046001600160a01b031633146128d057611bf4600160426122b8565b6128d8612643565b600954146128ec57611bf4600a60416122b8565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561293d57600080fd5b505afa158015612951573d6000803e3d6000fd5b505050506040513d602081101561296757600080fd5b50516129bd5760408051600160e51b62461bcd02815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a16000610a4b565b6000805460010180825581612a33610ea8565b90508015612a51576116a8816010811115612a4a57fe5b600f6122b8565b836001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612a8c57600080fd5b505af1158015612aa0573d6000803e3d6000fd5b505050506040513d6020811015612ab657600080fd5b505190508015612ad6576116a8816010811115612acf57fe5b60106122b8565b612ae233878787614013565b9250506000548114610a375760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b60035460009061010090046001600160a01b03163314612b5457610b0d600160476122b8565b612b5c612643565b60095414612b7057610b0d600a60486122b8565b670de0b6b3a7640000821115612b8c57610b0d600260496122b8565b6008805490839055604080518281526020810185905281517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460929181900390910190a16000610a4b565b60055460408051600160e11b63120045310281523060048201526001600160a01b0386811660248301528581166044830152606482018590529151600093849316916324008a6291608480830192602092919082900301818787803b158015612c3e57600080fd5b505af1158015612c52573d6000803e3d6000fd5b505050506040513d6020811015612c6857600080fd5b505190508015612c8757612c7f60036038836125dd565b915050610a4b565b612c8f612643565b60095414612ca357612c7f600a60396122b8565b612cab61477c565b6001600160a01b0385166000908152601060205260409020600101546060820152612cd5856124ee565b6080830181905260208301826003811115612cec57fe5b6003811115612cf757fe5b9052506000905081602001516003811115612d0e57fe5b14612d3357612d2a600960378360200151600381111561109557fe5b92505050610a4b565b600019841415612d4c5760808101516040820152612d54565b604081018490525b612d62868260400151614507565b81906010811115612d6f57fe5b90816010811115612d7c57fe5b905250600081516010811115612d8e57fe5b14612da0578051612d2a90603c6122b8565b612db281608001518260400151612647565b60a0830181905260208301826003811115612dc957fe5b6003811115612dd457fe5b9052506000905081602001516003811115612deb57fe5b14612e0757612d2a6009603a8360200151600381111561109557fe5b612e17600b548260400151612647565b60c0830181905260208301826003811115612e2e57fe5b6003811115612e3957fe5b9052506000905081602001516003811115612e5057fe5b14612e6c57612d2a6009603b8360200151600381111561109557fe5b612e7a86826040015161463e565b81906010811115612e8757fe5b90816010811115612e9457fe5b905250600081516010811115612ea657fe5b14612efb5760408051600160e51b62461bcd02815260206004820152601f60248201527f726570617920626f72726f77207472616e7366657220696e206661696c656400604482015290519081900360640190fd5b60a080820180516001600160a01b03808916600081815260106020908152604091829020948555600a5460019095019490945560c0870151600b8190558188015195518251948e16855294840192909252828101949094526060820192909252608081019190915290517f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1929181900390910190a160055460408083015160608401518251600160e01b631ededc910281523060048201526001600160a01b038b811660248301528a81166044830152606482019390935260848101919091529151921691631ededc919160a48082019260009290919082900301818387803b15801561300757600080fd5b505af115801561301b573d6000803e3d6000fd5b5060009250613028915050565b9695505050505050565b60008060008061304287876126d2565b9092509050600082600381111561305557fe5b14613066575091506000905061274c565b6127458186612647565b600061307a61470f565b60008061308f86670de0b6b3a7640000613703565b909250905060008260038111156130a257fe5b146130c15750604080516020810190915260008152909250905061222e565b6000806130ce8388613742565b909250905060008260038111156130e157fe5b146131035750604080516020810190915260008152909450925061222e915050565b604080516020810190915290815260009890975095505050505050565b51670de0b6b3a7640000900490565b60115460408051600160e01b63a9059cbb0281526001600160a01b03858116600483015260248201859052915160009392909216918391839163a9059cbb91604480820192869290919082900301818387803b15801561318e57600080fd5b505af11580156131a2573d6000803e3d6000fd5b505050503d600081146131bc57602081146131c657600080fd5b60001991506131d2565b60206000803e60005191505b50806131e357601092505050610885565b506000949350505050565b60008215806131fb575081155b61323957604051600160e51b62461bcd0281526004018080602001828103825260348152602001806149eb6034913960400191505060405180910390fd5b61324161477c565b613249611d8f565b604083018190526020830182600381111561326057fe5b600381111561326b57fe5b905250600090508160200151600381111561328257fe5b1461329e57612c7f6009602b8360200151600381111561109557fe5b831561331f5760608101849052604080516020810182529082015181526132c590856121e1565b60808301819052602083018260038111156132dc57fe5b60038111156132e757fe5b90525060009050816020015160038111156132fe57fe5b1461331a57612c7f600960298360200151600381111561109557fe5b613398565b61333b83604051806020016040528084604001518152506146f8565b606083018190526020830182600381111561335257fe5b600381111561335d57fe5b905250600090508160200151600381111561337457fe5b1461339057612c7f6009602a8360200151600381111561109557fe5b608081018390525b600554606082015160408051600160e01b63eabe7d910281523060048201526001600160a01b03898116602483015260448201939093529051600093929092169163eabe7d919160648082019260209290919082900301818787803b15801561340057600080fd5b505af1158015613414573d6000803e3d6000fd5b505050506040513d602081101561342a57600080fd5b50519050801561344157612d2a60036028836125dd565b613449612643565b6009541461345d57612d2a600a602c6122b8565b61346d600d548360600151612647565b60a084018190526020840182600381111561348457fe5b600381111561348f57fe5b90525060009050826020015160038111156134a657fe5b146134c257612d2a6009602e8460200151600381111561109557fe5b6001600160a01b0386166000908152600e602052604090205460608301516134ea9190612647565b60c084018190526020840182600381111561350157fe5b600381111561350c57fe5b905250600090508260200151600381111561352357fe5b1461353f57612d2a6009602d8460200151600381111561109557fe5b816080015161354c612235565b101561355e57612d2a600e602f6122b8565b61356c86836080015161312f565b8290601081111561357957fe5b9081601081111561358657fe5b90525060008251601081111561359857fe5b146135ed5760408051600160e51b62461bcd02815260206004820152601a60248201527f72656465656d207472616e73666572206f7574206661696c6564000000000000604482015290519081900360640190fd5b60a0820151600d5560c08201516001600160a01b0387166000818152600e602090815260409182902093909355606085015181519081529051309360008051602061495a833981519152928290030190a36080820151606080840151604080516001600160a01b038b168152602081019490945283810191909152517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9299281900390910190a16005546080830151606084015160408051600160e01b6351dff9890281523060048201526001600160a01b038b81166024830152604482019490945260648101929092525191909216916351dff98991608480830192600092919082900301818387803b15801561300757600080fd5b600080836137165750600090508061222e565b8383028385828161372357fe5b04146137375750600291506000905061222e565b60009250905061222e565b60008082613756575060019050600061222e565b600083858161376157fe5b04915091509250929050565b60055460408051600160e01b634ef4c3e10281523060048201526001600160a01b03858116602483015260448201859052915160009384931691634ef4c3e191606480830192602092919082900301818787803b1580156137cd57600080fd5b505af11580156137e1573d6000803e3d6000fd5b505050506040513d60208110156137f757600080fd5b5051905080156138165761380e6003601f836125dd565b915050610885565b61381e612643565b600954146138325761380e600a60226122b8565b61383a6147ba565b6138448585614507565b8190601081111561385157fe5b9081601081111561385e57fe5b90525060008151601081111561387057fe5b1461388b5780516138829060266122b8565b92505050610885565b613893611d8f565b60408301819052602083018260038111156138aa57fe5b60038111156138b557fe5b90525060009050816020015160038111156138cc57fe5b146138e857613882600960218360200151600381111561109557fe5b61390484604051806020016040528084604001518152506146f8565b606083018190526020830182600381111561391b57fe5b600381111561392657fe5b905250600090508160200151600381111561393d57fe5b1461395957613882600960208360200151600381111561109557fe5b613969600d5482606001516126d2565b608083018190526020830182600381111561398057fe5b600381111561398b57fe5b90525060009050816020015160038111156139a257fe5b146139be57613882600960248360200151600381111561109557fe5b6001600160a01b0385166000908152600e602052604090205460608201516139e691906126d2565b60a08301819052602083018260038111156139fd57fe5b6003811115613a0857fe5b9052506000905081602001516003811115613a1f57fe5b14613a3b57613882600960238360200151600381111561109557fe5b613a45858561463e565b81906010811115613a5257fe5b90816010811115613a5f57fe5b905250600081516010811115613a7157fe5b14613a835780516138829060256122b8565b6080810151600d5560a08101516001600160a01b0386166000818152600e602090815260409182902093909355606080850151825193845293830188905282820193909352517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f929181900390910190a1606081015160408051918252516001600160a01b03871691309160008051602061495a8339815191529181900360200190a3600554606082015160408051600160e01b6341c728b90281523060048201526001600160a01b038981166024830152604482018990526064820193909352905191909216916341c728b991608480830192600092919082900301818387803b158015613b9157600080fd5b505af1158015613ba5573d6000803e3d6000fd5b5060009250613bb2915050565b95945050505050565b6000613bc561470f565b600080613bda86600001518660000151613703565b90925090506000826003811115613bed57fe5b14613c0c5750604080516020810190915260008152909250905061222e565b600080613c216706f05b59d3b20000846126d2565b90925090506000826003811115613c3457fe5b14613c565750604080516020810190915260008152909450925061222e915050565b600080613c6b83670de0b6b3a7640000613742565b90925090506000826003811115613c7e57fe5b14613c8557fe5b604080516020810190915290815260009a909950975050505050505050565b60055460408051600160e21b63368f51530281523060048201526001600160a01b0385811660248301526044820185905291516000938493169163da3d454c91606480830192602092919082900301818787803b158015613d0457600080fd5b505af1158015613d18573d6000803e3d6000fd5b505050506040513d6020811015613d2e57600080fd5b505190508015613d455761380e6003600e836125dd565b613d4d612643565b60095414613d605761380e600a806122b8565b82613d69612235565b1015613d7b5761380e600e60096122b8565b613d836147d4565b613d8c856124ee565b6040830181905260208301826003811115613da357fe5b6003811115613dae57fe5b9052506000905081602001516003811115613dc557fe5b14613de157613882600960078360200151600381111561109557fe5b613def8160400151856126d2565b6060830181905260208301826003811115613e0657fe5b6003811115613e1157fe5b9052506000905081602001516003811115613e2857fe5b14613e44576138826009600c8360200151600381111561109557fe5b613e50600b54856126d2565b6080830181905260208301826003811115613e6757fe5b6003811115613e7257fe5b9052506000905081602001516003811115613e8957fe5b14613ea5576138826009600b8360200151600381111561109557fe5b613eaf858561312f565b81906010811115613ebc57fe5b90816010811115613ec957fe5b905250600081516010811115613edb57fe5b14613f305760408051600160e51b62461bcd02815260206004820152601a60248201527f626f72726f77207472616e73666572206f7574206661696c6564000000000000604482015290519081900360640190fd5b606080820180516001600160a01b038816600081815260106020908152604091829020938455600a54600190940193909355608080870151600b819055945182519384529383018a9052828201939093529381019290925291517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80929181900390910190a160055460408051600160e01b635c7786050281523060048201526001600160a01b0388811660248301526044820188905291519190921691635c77860591606480830192600092919082900301818387803b158015613b9157600080fd5b60055460408051600160e11b632fe3f38f0281523060048201526001600160a01b0384811660248301528781166044830152868116606483015260848201869052915160009384931691635fc7e71e9160a480830192602092919082900301818787803b15801561408357600080fd5b505af1158015614097573d6000803e3d6000fd5b505050506040513d60208110156140ad57600080fd5b5051905080156140c457611ee660036012836125dd565b6140cc612643565b600954146140e057611ee6600a60166122b8565b6140e8612643565b836001600160a01b0316636c540baf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561412157600080fd5b505afa158015614135573d6000803e3d6000fd5b505050506040513d602081101561414b57600080fd5b50511461415e57611ee6600a60116122b8565b856001600160a01b0316856001600160a01b0316141561418457611ee6600660176122b8565b8361419557611ee6600760156122b8565b6000198414156141ab57611ee6600760146122b8565b60055460408051600160e01b63c488847b0281523060048201526001600160a01b038681166024830152604482018890528251600094859492169263c488847b926064808301939192829003018186803b15801561420857600080fd5b505afa15801561421c573d6000803e3d6000fd5b505050506040513d604081101561423257600080fd5b5080516020909101519092509050811561425d5761425360046013846125dd565b9350505050610ad0565b846001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156142b357600080fd5b505afa1580156142c7573d6000803e3d6000fd5b505050506040513d60208110156142dd57600080fd5b50518111156142f257614253600d601d6122b8565b60006142ff898989612bd6565b905080156143285761431d81601081111561431657fe5b60186122b8565b945050505050610ad0565b60408051600160e01b63b2a02ff10281526001600160a01b038b811660048301528a8116602483015260448201859052915160009289169163b2a02ff191606480830192602092919082900301818787803b15801561438657600080fd5b505af115801561439a573d6000803e3d6000fd5b505050506040513d60208110156143b057600080fd5b50519050801561440a5760408051600160e51b62461bcd02815260206004820152601460248201527f746f6b656e207365697a757265206661696c6564000000000000000000000000604482015290519081900360640190fd5b604080516001600160a01b03808d168252808c1660208301528183018b9052891660608201526080810185905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a160055460408051600160e01b6347ef3b3b0281523060048201526001600160a01b038a811660248301528d811660448301528c81166064830152608482018c905260a48201879052915191909216916347ef3b3b9160c480830192600092919082900301818387803b1580156144d857600080fd5b505af11580156144ec573d6000803e3d6000fd5b50600092506144f9915050565b9a9950505050505050505050565b60115460408051600160e11b636eb1769f0281526001600160a01b038581166004830152306024830152915160009392909216918491839163dd62ed3e91604480820192602092909190829003018186803b15801561456557600080fd5b505afa158015614579573d6000803e3d6000fd5b505050506040513d602081101561458f57600080fd5b505110156145a157600c915050610885565b82816001600160a01b03166370a08231866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156145f857600080fd5b505afa15801561460c573d6000803e3d6000fd5b505050506040513d602081101561462257600080fd5b5051101561463457600d915050610885565b5060009392505050565b60115460408051600160e01b6323b872dd0281526001600160a01b0385811660048301523060248301526044820185905291516000939290921691839183916323b872dd91606480820192869290919082900301818387803b1580156146a357600080fd5b505af11580156146b7573d6000803e3d6000fd5b505050503d600081146146d157602081146146db57600080fd5b60001991506146e7565b60206000803e60005191505b50806131e357600f92505050610885565b600080600061470561470f565b6121f88686612754565b6040518060200160405280600081525090565b60408051610140810190915280600081526020016000815260200160008152602001600081526020016000815260200161475a61470f565b8152602001600081526020016000815260200160008152602001600081525090565b6040805160e0810190915280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805160c081019091528060008152602001600061475a565b6040805160a08101909152806000815260200160008152602001600081526020016000815260200160008152509056fe737570706c7952617465506572426c6f636b3a2063616c63756c6174696e6720626f72726f7773506572206661696c6564726564756365207265736572766573207472616e73666572206f7574206661696c6564737570706c7952617465506572426c6f636b3a2063616c63756c6174696e6720737570706c7952617465206661696c6564626f72726f7742616c616e636553746f7265643a20626f72726f7742616c616e636553746f726564496e7465726e616c206661696c6564737570706c7952617465506572426c6f636b3a2063616c63756c6174696e6720756e6465726c79696e67206661696c6564626f72726f7752617465506572426c6f636b3a20696e746572657374526174654d6f64656c2e626f72726f7752617465206661696c6564737570706c7952617465506572426c6f636b3a2063616c63756c6174696e6720626f72726f7752617465206661696c6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef737570706c7952617465506572426c6f636b3a2063616c63756c6174696e67206f6e654d696e757352657365727665466163746f72206661696c656465786368616e67655261746553746f7265643a2065786368616e67655261746553746f726564496e7465726e616c206661696c65646f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416d6f756e74496e206d757374206265207a65726f72656475636520726573657276657320756e657870656374656420756e646572666c6f77a165627a7a7230582094c0d9578f6ecda1bf3c1e5dadc45059d6219b5c62e61a7e7e56a8d43ab32d9c002953657474696e6720696e7465726573742072617465206d6f64656c206661696c6564496e697469616c2065786368616e67652072617465206d7573742062652067726561746572207468616e207a65726f2e', -}; diff --git a/utils/contract_logs/btcDaiRebalancingManager.ts b/utils/contract_logs/btcDaiRebalancingManager.ts deleted file mode 100644 index ba9418c..0000000 --- a/utils/contract_logs/btcDaiRebalancingManager.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Address, Log } from 'set-protocol-utils'; -import { BigNumber } from 'bignumber.js'; - -export function LogManagerProposal( - btcPrice: BigNumber, - contractAddress: Address, -): Log[] { - return [{ - event: 'LogManagerProposal', - address: contractAddress, - args: { - btcPrice, - }, - }]; -} \ No newline at end of file diff --git a/utils/contract_logs/btcEthRebalancingManager.ts b/utils/contract_logs/btcEthRebalancingManager.ts deleted file mode 100644 index 9f63a3d..0000000 --- a/utils/contract_logs/btcEthRebalancingManager.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Address, Log } from 'set-protocol-utils'; -import { BigNumber } from 'bignumber.js'; - -export function LogManagerProposal( - btcPrice: BigNumber, - ethPrice: BigNumber, - contractAddress: Address, -): Log[] { - return [{ - event: 'LogManagerProposal', - address: contractAddress, - args: { - btcPrice, - ethPrice, - }, - }]; -} diff --git a/utils/contract_logs/emaOracle.ts b/utils/contract_logs/emaOracle.ts deleted file mode 100644 index 5d76614..0000000 --- a/utils/contract_logs/emaOracle.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Address, Log } from 'set-protocol-utils'; -import { BigNumber } from 'bignumber.js'; - - export function FeedAdded( - newFeedAddress: Address, - emaDays: BigNumber, - contractAddress: Address -): Log[] { - return [{ - event: 'FeedAdded', - address: contractAddress, - args: { - newFeedAddress, - emaDays, - }, - }]; -} - -export function FeedRemoved( - removedFeedAddress: Address, - emaDays: BigNumber, - contractAddress: Address -): Log[] { - return [{ - event: 'FeedRemoved', - address: contractAddress, - args: { - removedFeedAddress, - emaDays, - }, - }]; -} \ No newline at end of file diff --git a/utils/contract_logs/ethDaiRebalancingManager.ts b/utils/contract_logs/ethDaiRebalancingManager.ts deleted file mode 100644 index 71a0a42..0000000 --- a/utils/contract_logs/ethDaiRebalancingManager.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Address, Log } from 'set-protocol-utils'; -import { BigNumber } from 'bignumber.js'; - -export function LogManagerProposal( - ethPrice: BigNumber, - contractAddress: Address, -): Log[] { - return [{ - event: 'LogManagerProposal', - address: contractAddress, - args: { - ethPrice, - }, - }]; -} \ No newline at end of file diff --git a/utils/contract_logs/linearizedPriceDataSource.ts b/utils/contract_logs/linearizedPriceDataSource.ts deleted file mode 100644 index 8b7ef29..0000000 --- a/utils/contract_logs/linearizedPriceDataSource.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Address, Log } from 'set-protocol-utils'; - - export function LogOracleUpdated( - newOracleAddress: Address, - contractAddress: Address -): Log[] { - return [{ - event: 'LogOracleUpdated', - address: contractAddress, - args: { - newOracleAddress, - }, - }]; -} \ No newline at end of file diff --git a/utils/contract_logs/oracle.ts b/utils/contract_logs/oracle.ts deleted file mode 100644 index 6875d4e..0000000 --- a/utils/contract_logs/oracle.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Address, Log } from 'set-protocol-utils'; - -export interface FeedCreatedArgs { - sender: Address; - feed: Address; -} - -export function FeedCreated( - _factory: Address, - sender: Address, - feed: Address, -): Log { - return { - event: 'Created', - address: _factory, - args: { - sender, - feed, - }, - }; -} \ No newline at end of file diff --git a/utils/contracts.ts b/utils/contracts.ts index a5c22a3..35b78a2 100644 --- a/utils/contracts.ts +++ b/utils/contracts.ts @@ -4,14 +4,10 @@ export { AssetPairManagerV2Contract } from '../types/generated/asset_pair_manage export { BaseContract } from '../types/base_contract'; export { BinaryAllocatorContract } from '../types/generated/binary_allocator'; export { BinaryAllocatorMockContract } from '../types/generated/binary_allocator_mock'; -export { BTCDaiRebalancingManagerContract } from '../types/generated/b_t_c_dai_rebalancing_manager'; -export { BTCETHRebalancingManagerContract } from '../types/generated/b_t_c_e_t_h_rebalancing_manager'; -export { ETHDaiRebalancingManagerContract } from '../types/generated/e_t_h_dai_rebalancing_manager'; export { FlexibleTimingManagerLibraryMockContract } from '../types/generated/flexible_timing_manager_library_mock'; export { InverseMACOStrategyManagerContract } from '../types/generated/inverse_m_a_c_o_strategy_manager'; export { MACOStrategyManagerContract } from '../types/generated/m_a_c_o_strategy_manager'; export { MACOStrategyManagerV2Contract } from '../types/generated/m_a_c_o_strategy_manager_v2'; -export { ManagerLibraryMockContract } from '../types/generated/manager_library_mock'; export { MovingAverageCrossoverTriggerContract } from '../types/generated/moving_average_crossover_trigger'; export { TriggerMockContract } from '../types/generated/trigger_mock'; export { RSITrendingTriggerContract } from '../types/generated/r_s_i_trending_trigger'; diff --git a/utils/external/abis/compound/CErc20ABI.ts b/utils/external/abis/compound/CErc20ABI.ts deleted file mode 100644 index 14256b8..0000000 --- a/utils/external/abis/compound/CErc20ABI.ts +++ /dev/null @@ -1,1177 +0,0 @@ -export const CErc20ABI = [ - { - 'constant': true, - 'inputs': [], - 'name': 'name', - 'outputs': [ - { - 'name': '', - 'type': 'string', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'spender', - 'type': 'address', - }, - { - 'name': 'amount', - 'type': 'uint256', - }, - ], - 'name': 'approve', - 'outputs': [ - { - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'reserveFactorMantissa', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'account', - 'type': 'address', - }, - ], - 'name': 'borrowBalanceCurrent', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'totalSupply', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'exchangeRateStored', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'src', - 'type': 'address', - }, - { - 'name': 'dst', - 'type': 'address', - }, - { - 'name': 'amount', - 'type': 'uint256', - }, - ], - 'name': 'transferFrom', - 'outputs': [ - { - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'pendingAdmin', - 'outputs': [ - { - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'decimals', - 'outputs': [ - { - 'name': '', - 'type': 'uint8', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'owner', - 'type': 'address', - }, - ], - 'name': 'balanceOfUnderlying', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'getCash', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'newComptroller', - 'type': 'address', - }, - ], - 'name': '_setComptroller', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'totalBorrows', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'comptroller', - 'outputs': [ - { - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'reduceAmount', - 'type': 'uint256', - }, - ], - 'name': '_reduceReserves', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'initialExchangeRateMantissa', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'accrualBlockNumber', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'underlying', - 'outputs': [ - { - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [ - { - 'name': 'owner', - 'type': 'address', - }, - ], - 'name': 'balanceOf', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [], - 'name': 'totalBorrowsCurrent', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'totalReserves', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'symbol', - 'outputs': [ - { - 'name': '', - 'type': 'string', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [ - { - 'name': 'account', - 'type': 'address', - }, - ], - 'name': 'borrowBalanceStored', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [], - 'name': 'accrueInterest', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'dst', - 'type': 'address', - }, - { - 'name': 'amount', - 'type': 'uint256', - }, - ], - 'name': 'transfer', - 'outputs': [ - { - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'borrowIndex', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'supplyRatePerBlock', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'liquidator', - 'type': 'address', - }, - { - 'name': 'borrower', - 'type': 'address', - }, - { - 'name': 'seizeTokens', - 'type': 'uint256', - }, - ], - 'name': 'seize', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'newPendingAdmin', - 'type': 'address', - }, - ], - 'name': '_setPendingAdmin', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [], - 'name': 'exchangeRateCurrent', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [ - { - 'name': 'account', - 'type': 'address', - }, - ], - 'name': 'getAccountSnapshot', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - { - 'name': '', - 'type': 'uint256', - }, - { - 'name': '', - 'type': 'uint256', - }, - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [ - { - 'name': 'owner', - 'type': 'address', - }, - { - 'name': 'spender', - 'type': 'address', - }, - ], - 'name': 'allowance', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [], - 'name': '_acceptAdmin', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'newInterestRateModel', - 'type': 'address', - }, - ], - 'name': '_setInterestRateModel', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'interestRateModel', - 'outputs': [ - { - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'admin', - 'outputs': [ - { - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'borrowRatePerBlock', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'newReserveFactorMantissa', - 'type': 'uint256', - }, - ], - 'name': '_setReserveFactor', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'isCToken', - 'outputs': [ - { - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - }, - { - 'inputs': [ - { - 'name': 'underlying_', - 'type': 'address', - }, - { - 'name': 'comptroller_', - 'type': 'address', - }, - { - 'name': 'interestRateModel_', - 'type': 'address', - }, - { - 'name': 'initialExchangeRateMantissa_', - 'type': 'uint256', - }, - { - 'name': 'name_', - 'type': 'string', - }, - { - 'name': 'symbol_', - 'type': 'string', - }, - { - 'name': 'decimals_', - 'type': 'uint8', - }, - { - 'name': 'admin_', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'constructor', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'interestAccumulated', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'borrowIndex', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'totalBorrows', - 'type': 'uint256', - }, - ], - 'name': 'AccrueInterest', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'minter', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'mintAmount', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'mintTokens', - 'type': 'uint256', - }, - ], - 'name': 'Mint', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'redeemer', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'redeemAmount', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'redeemTokens', - 'type': 'uint256', - }, - ], - 'name': 'Redeem', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'borrower', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'borrowAmount', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'accountBorrows', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'totalBorrows', - 'type': 'uint256', - }, - ], - 'name': 'Borrow', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'payer', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'borrower', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'repayAmount', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'accountBorrows', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'totalBorrows', - 'type': 'uint256', - }, - ], - 'name': 'RepayBorrow', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'liquidator', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'borrower', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'repayAmount', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'cTokenCollateral', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'seizeTokens', - 'type': 'uint256', - }, - ], - 'name': 'LiquidateBorrow', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'oldPendingAdmin', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'newPendingAdmin', - 'type': 'address', - }, - ], - 'name': 'NewPendingAdmin', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'oldAdmin', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'newAdmin', - 'type': 'address', - }, - ], - 'name': 'NewAdmin', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'oldComptroller', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'newComptroller', - 'type': 'address', - }, - ], - 'name': 'NewComptroller', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'oldInterestRateModel', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'newInterestRateModel', - 'type': 'address', - }, - ], - 'name': 'NewMarketInterestRateModel', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'oldReserveFactorMantissa', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'newReserveFactorMantissa', - 'type': 'uint256', - }, - ], - 'name': 'NewReserveFactor', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'admin', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'reduceAmount', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'newTotalReserves', - 'type': 'uint256', - }, - ], - 'name': 'ReservesReduced', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'name': 'error', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'info', - 'type': 'uint256', - }, - { - 'indexed': false, - 'name': 'detail', - 'type': 'uint256', - }, - ], - 'name': 'Failure', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': true, - 'name': 'from', - 'type': 'address', - }, - { - 'indexed': true, - 'name': 'to', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'amount', - 'type': 'uint256', - }, - ], - 'name': 'Transfer', - 'type': 'event', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': true, - 'name': 'owner', - 'type': 'address', - }, - { - 'indexed': true, - 'name': 'spender', - 'type': 'address', - }, - { - 'indexed': false, - 'name': 'amount', - 'type': 'uint256', - }, - ], - 'name': 'Approval', - 'type': 'event', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'mintAmount', - 'type': 'uint256', - }, - ], - 'name': 'mint', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'redeemTokens', - 'type': 'uint256', - }, - ], - 'name': 'redeem', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'redeemAmount', - 'type': 'uint256', - }, - ], - 'name': 'redeemUnderlying', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'borrowAmount', - 'type': 'uint256', - }, - ], - 'name': 'borrow', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'repayAmount', - 'type': 'uint256', - }, - ], - 'name': 'repayBorrow', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'borrower', - 'type': 'address', - }, - { - 'name': 'repayAmount', - 'type': 'uint256', - }, - ], - 'name': 'repayBorrowBehalf', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, - { - 'constant': false, - 'inputs': [ - { - 'name': 'borrower', - 'type': 'address', - }, - { - 'name': 'repayAmount', - 'type': 'uint256', - }, - { - 'name': 'cTokenCollateral', - 'type': 'address', - }, - ], - 'name': 'liquidateBorrow', - 'outputs': [ - { - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - }, -]; \ No newline at end of file diff --git a/utils/external/abis/compound/ComptrollerABI.ts b/utils/external/abis/compound/ComptrollerABI.ts deleted file mode 100644 index dcee2a7..0000000 --- a/utils/external/abis/compound/ComptrollerABI.ts +++ /dev/null @@ -1,1563 +0,0 @@ -export const ComptrollerABI = [ - { - 'inputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'constructor', - 'signature': 'constructor', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'string', - 'name': 'action', - 'type': 'string', - }, - { - 'indexed': false, - 'internalType': 'bool', - 'name': 'pauseState', - 'type': 'bool', - }, - ], - 'name': 'ActionPaused', - 'type': 'event', - 'signature': '0xef159d9a32b2472e32b098f954f3ce62d232939f1c207070b584df1814de2de0', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'error', - 'type': 'uint256', - }, - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'info', - 'type': 'uint256', - }, - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'detail', - 'type': 'uint256', - }, - ], - 'name': 'Failure', - 'type': 'event', - 'signature': '0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - { - 'indexed': false, - 'internalType': 'address', - 'name': 'account', - 'type': 'address', - }, - ], - 'name': 'MarketEntered', - 'type': 'event', - 'signature': '0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - { - 'indexed': false, - 'internalType': 'address', - 'name': 'account', - 'type': 'address', - }, - ], - 'name': 'MarketExited', - 'type': 'event', - 'signature': '0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - ], - 'name': 'MarketListed', - 'type': 'event', - 'signature': '0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'oldCloseFactorMantissa', - 'type': 'uint256', - }, - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'newCloseFactorMantissa', - 'type': 'uint256', - }, - ], - 'name': 'NewCloseFactor', - 'type': 'event', - 'signature': '0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'oldCollateralFactorMantissa', - 'type': 'uint256', - }, - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'newCollateralFactorMantissa', - 'type': 'uint256', - }, - ], - 'name': 'NewCollateralFactor', - 'type': 'event', - 'signature': '0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'oldLiquidationIncentiveMantissa', - 'type': 'uint256', - }, - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'newLiquidationIncentiveMantissa', - 'type': 'uint256', - }, - ], - 'name': 'NewLiquidationIncentive', - 'type': 'event', - 'signature': '0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'oldMaxAssets', - 'type': 'uint256', - }, - { - 'indexed': false, - 'internalType': 'uint256', - 'name': 'newMaxAssets', - 'type': 'uint256', - }, - ], - 'name': 'NewMaxAssets', - 'type': 'event', - 'signature': '0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'address', - 'name': 'oldPauseGuardian', - 'type': 'address', - }, - { - 'indexed': false, - 'internalType': 'address', - 'name': 'newPauseGuardian', - 'type': 'address', - }, - ], - 'name': 'NewPauseGuardian', - 'type': 'event', - 'signature': '0x0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e', - }, - { - 'anonymous': false, - 'inputs': [ - { - 'indexed': false, - 'internalType': 'contract PriceOracle', - 'name': 'oldPriceOracle', - 'type': 'address', - }, - { - 'indexed': false, - 'internalType': 'contract PriceOracle', - 'name': 'newPriceOracle', - 'type': 'address', - }, - ], - 'name': 'NewPriceOracle', - 'type': 'event', - 'signature': '0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'contract Unitroller', - 'name': 'unitroller', - 'type': 'address', - }, - ], - 'name': '_become', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x1d504dc6', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'bool', - 'name': 'state', - 'type': 'bool', - }, - ], - 'name': '_setBorrowPaused', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x56133fc8', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'uint256', - 'name': 'newCloseFactorMantissa', - 'type': 'uint256', - }, - ], - 'name': '_setCloseFactor', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x317b0b77', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'newCollateralFactorMantissa', - 'type': 'uint256', - }, - ], - 'name': '_setCollateralFactor', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xe4028eee', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'uint256', - 'name': 'newLiquidationIncentiveMantissa', - 'type': 'uint256', - }, - ], - 'name': '_setLiquidationIncentive', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x4fd42e17', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'uint256', - 'name': 'newMaxAssets', - 'type': 'uint256', - }, - ], - 'name': '_setMaxAssets', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xd9226ced', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'bool', - 'name': 'state', - 'type': 'bool', - }, - ], - 'name': '_setMintPaused', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x9845f280', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'newPauseGuardian', - 'type': 'address', - }, - ], - 'name': '_setPauseGuardian', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x5f5af1aa', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'contract PriceOracle', - 'name': 'newOracle', - 'type': 'address', - }, - ], - 'name': '_setPriceOracle', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x55ee1fe1', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'bool', - 'name': 'state', - 'type': 'bool', - }, - ], - 'name': '_setSeizePaused', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x2d70db78', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'bool', - 'name': 'state', - 'type': 'bool', - }, - ], - 'name': '_setTransferPaused', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x8ebf6364', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - ], - 'name': '_supportMarket', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xa76b3fda', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'address', - 'name': '', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'name': 'accountAssets', - 'outputs': [ - { - 'internalType': 'contract CToken', - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xdce15449', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'admin', - 'outputs': [ - { - 'internalType': 'address', - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xf851a440', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'blockNumber', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x57e871e7', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'borrower', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'borrowAmount', - 'type': 'uint256', - }, - ], - 'name': 'borrowAllowed', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xda3d454c', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'borrowGuardianPaused', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x9530f644', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'borrower', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'borrowAmount', - 'type': 'uint256', - }, - ], - 'name': 'borrowVerify', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x5c778605', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'account', - 'type': 'address', - }, - { - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - ], - 'name': 'checkMembership', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x929fe9a1', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'closeFactorMantissa', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xe8755446', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'comptrollerImplementation', - 'outputs': [ - { - 'internalType': 'address', - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xbb82aa5e', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address[]', - 'name': 'cTokens', - 'type': 'address[]', - }, - ], - 'name': 'enterMarkets', - 'outputs': [ - { - 'internalType': 'uint256[]', - 'name': '', - 'type': 'uint256[]', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xc2998238', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cTokenAddress', - 'type': 'address', - }, - ], - 'name': 'exitMarket', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xede4edd0', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'uint256', - 'name': 'blocks', - 'type': 'uint256', - }, - ], - 'name': 'fastForward', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xfccbe7f6', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'account', - 'type': 'address', - }, - ], - 'name': 'getAccountLiquidity', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x5ec88c79', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'account', - 'type': 'address', - }, - ], - 'name': 'getAssetsIn', - 'outputs': [ - { - 'internalType': 'contract CToken[]', - 'name': '', - 'type': 'address[]', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xabfceffc', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'account', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'cTokenModify', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'redeemTokens', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': 'borrowAmount', - 'type': 'uint256', - }, - ], - 'name': 'getHypotheticalAccountLiquidity', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x4e79238f', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'isComptroller', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x007e3dd2', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cTokenBorrowed', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'cTokenCollateral', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'liquidator', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'borrower', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'repayAmount', - 'type': 'uint256', - }, - ], - 'name': 'liquidateBorrowAllowed', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x5fc7e71e', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cTokenBorrowed', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'cTokenCollateral', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'liquidator', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'borrower', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'repayAmount', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': 'seizeTokens', - 'type': 'uint256', - }, - ], - 'name': 'liquidateBorrowVerify', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x47ef3b3b', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cTokenBorrowed', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'cTokenCollateral', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'repayAmount', - 'type': 'uint256', - }, - ], - 'name': 'liquidateCalculateSeizeTokens', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xc488847b', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'liquidationIncentiveMantissa', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x4ada90af', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'address', - 'name': '', - 'type': 'address', - }, - ], - 'name': 'markets', - 'outputs': [ - { - 'internalType': 'bool', - 'name': 'isListed', - 'type': 'bool', - }, - { - 'internalType': 'uint256', - 'name': 'collateralFactorMantissa', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x8e8f294b', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'maxAssets', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x94b2294b', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - ], - 'name': 'membershipLength', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x4bca0d8c', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'minter', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'mintAmount', - 'type': 'uint256', - }, - ], - 'name': 'mintAllowed', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x4ef4c3e1', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'mintGuardianPaused', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x5dce0515', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'minter', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'mintAmount', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': 'mintTokens', - 'type': 'uint256', - }, - ], - 'name': 'mintVerify', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x41c728b9', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'oracle', - 'outputs': [ - { - 'internalType': 'contract PriceOracle', - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x7dc0d1d0', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'pauseGuardian', - 'outputs': [ - { - 'internalType': 'address', - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x24a3d622', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'pendingAdmin', - 'outputs': [ - { - 'internalType': 'address', - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x26782247', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'pendingComptrollerImplementation', - 'outputs': [ - { - 'internalType': 'address', - 'name': '', - 'type': 'address', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xdcfbc0c7', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'redeemer', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'redeemTokens', - 'type': 'uint256', - }, - ], - 'name': 'redeemAllowed', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xeabe7d91', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'redeemer', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'redeemAmount', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': 'redeemTokens', - 'type': 'uint256', - }, - ], - 'name': 'redeemVerify', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x51dff989', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'payer', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'borrower', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'repayAmount', - 'type': 'uint256', - }, - ], - 'name': 'repayBorrowAllowed', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x24008a62', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'payer', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'borrower', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'repayAmount', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': 'borrowerIndex', - 'type': 'uint256', - }, - ], - 'name': 'repayBorrowVerify', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x1ededc91', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cTokenCollateral', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'cTokenBorrowed', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'liquidator', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'borrower', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'seizeTokens', - 'type': 'uint256', - }, - ], - 'name': 'seizeAllowed', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xd02f7351', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'seizeGuardianPaused', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xac0b0bb7', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cTokenCollateral', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'cTokenBorrowed', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'liquidator', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'borrower', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'seizeTokens', - 'type': 'uint256', - }, - ], - 'name': 'seizeVerify', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x6d35bf91', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'uint256', - 'name': 'number', - 'type': 'uint256', - }, - ], - 'name': 'setBlockNumber', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xa8c3c850', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'src', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'dst', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'transferTokens', - 'type': 'uint256', - }, - ], - 'name': 'transferAllowed', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xbdcdc258', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'transferGuardianPaused', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x87f76303', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'src', - 'type': 'address', - }, - { - 'internalType': 'address', - 'name': 'dst', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'transferTokens', - 'type': 'uint256', - }, - ], - 'name': 'transferVerify', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x6a56947e', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - ], - 'name': 'unlist', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xbde3672d', - }, -]; \ No newline at end of file diff --git a/utils/external/abis/compound/InterestRateModelABI.ts b/utils/external/abis/compound/InterestRateModelABI.ts deleted file mode 100644 index 43a935a..0000000 --- a/utils/external/abis/compound/InterestRateModelABI.ts +++ /dev/null @@ -1,148 +0,0 @@ -export const InterestRateModelABI = [ - { - 'inputs': [ - { - 'internalType': 'uint256', - 'name': 'borrowRate_', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'constructor', - 'signature': 'constructor', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'borrowRate', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xc914b437', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'failBorrowRate', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xc4fd6b2d', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'uint256', - 'name': '_cash', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': '_borrows', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': '_reserves', - 'type': 'uint256', - }, - ], - 'name': 'getBorrowRate', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x15f24053', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'isInterestRateModel', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x2191f92a', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'opaqueBorrowFailureCode', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x7ddeded1', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'uint256', - 'name': 'borrowRate_', - 'type': 'uint256', - }, - ], - 'name': 'setBorrowRate', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0xdd3eaf04', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'bool', - 'name': 'failBorrowRate_', - 'type': 'bool', - }, - ], - 'name': 'setFailBorrowRate', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x1f64eb4e', - }, -]; \ No newline at end of file diff --git a/utils/external/abis/compound/PriceOracleABI.ts b/utils/external/abis/compound/PriceOracleABI.ts deleted file mode 100644 index ca2c7f3..0000000 --- a/utils/external/abis/compound/PriceOracleABI.ts +++ /dev/null @@ -1,104 +0,0 @@ -export const PriceOracleABI = [ - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'asset', - 'type': 'address', - }, - ], - 'name': 'assetPrices', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x5e9a523c', - }, - { - 'constant': true, - 'inputs': [ - { - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - ], - 'name': 'getUnderlyingPrice', - 'outputs': [ - { - 'internalType': 'uint256', - 'name': '', - 'type': 'uint256', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0xfc57d4df', - }, - { - 'constant': true, - 'inputs': [], - 'name': 'isPriceOracle', - 'outputs': [ - { - 'internalType': 'bool', - 'name': '', - 'type': 'bool', - }, - ], - 'payable': false, - 'stateMutability': 'view', - 'type': 'function', - 'signature': '0x66331bba', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'address', - 'name': 'a', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'price', - 'type': 'uint256', - }, - ], - 'name': 'setDirectPrice', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x09a8acb0', - }, - { - 'constant': false, - 'inputs': [ - { - 'internalType': 'contract CToken', - 'name': 'cToken', - 'type': 'address', - }, - { - 'internalType': 'uint256', - 'name': 'underlyingPriceMantissa', - 'type': 'uint256', - }, - ], - 'name': 'setUnderlyingPrice', - 'outputs': [], - 'payable': false, - 'stateMutability': 'nonpayable', - 'type': 'function', - 'signature': '0x127ffda0', - }, -]; \ No newline at end of file diff --git a/utils/helpers/libraryMockHelper.ts b/utils/helpers/libraryMockHelper.ts index 748d335..37e9c7e 100644 --- a/utils/helpers/libraryMockHelper.ts +++ b/utils/helpers/libraryMockHelper.ts @@ -2,7 +2,6 @@ import { Address } from 'set-protocol-utils'; import { AllocatorMathLibraryMockContract, FlexibleTimingManagerLibraryMockContract, - ManagerLibraryMockContract, UintArrayUtilsLibraryMockContract, } from '../contracts'; import { @@ -13,7 +12,6 @@ import { const AllocatorMathLibraryMock = importArtifactsFromSource('AllocatorMathLibraryMock'); const FlexibleTimingManagerLibraryMock = importArtifactsFromSource('FlexibleTimingManagerLibraryMock'); -const ManagerLibraryMock = importArtifactsFromSource('ManagerLibraryMock'); const UintArrayUtilsLibrary = importArtifactsFromSource('UintArrayUtilsLibrary'); const UintArrayUtilsLibraryMock = importArtifactsFromSource('UintArrayUtilsLibraryMock'); @@ -26,17 +24,6 @@ export class LibraryMockHelper { /* ============ Deployment ============ */ - public async deployManagerLibraryMockAsync( - from: Address = this._contractOwnerAddress - ): Promise { - const managerLibraryMockContract = await ManagerLibraryMock.new(txnFrom(from)); - - return new ManagerLibraryMockContract( - getContractInstance(managerLibraryMockContract), - txnFrom(from), - ); - } - public async deployFlexibleTimingManagerLibraryMockAsync( from: Address = this._contractOwnerAddress ): Promise { diff --git a/utils/helpers/managerHelper.ts b/utils/helpers/managerHelper.ts index 6a2375c..7b1683e 100644 --- a/utils/helpers/managerHelper.ts +++ b/utils/helpers/managerHelper.ts @@ -16,9 +16,6 @@ import { AssetPairManagerV2Contract, BinaryAllocatorContract, BinaryAllocatorMockContract, - BTCETHRebalancingManagerContract, - BTCDaiRebalancingManagerContract, - ETHDaiRebalancingManagerContract, InverseMACOStrategyManagerContract, MACOStrategyManagerContract, MACOStrategyManagerV2Contract, @@ -53,9 +50,6 @@ const AssetPairManager = importArtifactsFromSource('AssetPairManager'); const AssetPairManagerV2 = importArtifactsFromSource('AssetPairManagerV2'); const BinaryAllocator = importArtifactsFromSource('BinaryAllocator'); const BinaryAllocatorMock = importArtifactsFromSource('BinaryAllocatorMock'); -const BTCETHRebalancingManager = importArtifactsFromSource('BTCETHRebalancingManager'); -const BTCDaiRebalancingManager = importArtifactsFromSource('BTCDaiRebalancingManager'); -const ETHDaiRebalancingManager = importArtifactsFromSource('ETHDaiRebalancingManager'); const InverseMACOStrategyManager = importArtifactsFromSource('InverseMACOStrategyManager'); const MACOStrategyManager = importArtifactsFromSource('MACOStrategyManager'); const MACOStrategyManagerV2 = importArtifactsFromSource('MACOStrategyManagerV2'); @@ -71,11 +65,7 @@ const SocialAllocator = importArtifactsFromSource('SocialAllocator'); const { SetProtocolUtils: SetUtils, SetProtocolTestUtils: SetTestUtils } = setProtocolUtils; const setTestUtils = new SetTestUtils(web3); -const { - SET_FULL_TOKEN_UNITS, - WBTC_FULL_TOKEN_UNITS, - WETH_FULL_TOKEN_UNITS, -} = SetUtils.CONSTANTS; +const { SET_FULL_TOKEN_UNITS } = SetUtils.CONSTANTS; export class ManagerHelper { private _tokenOwnerAddress: Address; @@ -88,101 +78,6 @@ export class ManagerHelper { /* ============ Rebalancing Token Manager Deployment ============ */ - public async deployBTCETHRebalancingManagerAsync( - coreAddress: Address, - btcPriceFeedAddress: Address, - ethPriceFeedAddress: Address, - btcAddress: Address, - ethAddress: Address, - setTokenFactoryAddress: Address, - auctionLibrary: Address, - auctionTimeToPivot: BigNumber = new BigNumber(100000), - multiplers: BigNumber[], - allocationBounds: BigNumber[], - from: Address = this._tokenOwnerAddress - ): Promise { - const truffleRebalacingTokenManager = await BTCETHRebalancingManager.new( - coreAddress, - btcPriceFeedAddress, - ethPriceFeedAddress, - btcAddress, - ethAddress, - setTokenFactoryAddress, - auctionLibrary, - auctionTimeToPivot, - multiplers, - allocationBounds, - { from }, - ); - - return new BTCETHRebalancingManagerContract( - getContractInstance(truffleRebalacingTokenManager), - { from, gas: DEFAULT_GAS }, - ); - } - - public async deployBTCDaiRebalancingManagerAsync( - coreAddress: Address, - btcPriceFeedAddress: Address, - daiAddress: Address, - btcAddress: Address, - setTokenFactoryAddress: Address, - auctionLibrary: Address, - auctionTimeToPivot: BigNumber = new BigNumber(100000), - multiplers: BigNumber[], - allocationBounds: BigNumber[], - from: Address = this._tokenOwnerAddress - ): Promise { - const truffleRebalacingTokenManager = await BTCDaiRebalancingManager.new( - coreAddress, - btcPriceFeedAddress, - daiAddress, - btcAddress, - setTokenFactoryAddress, - auctionLibrary, - auctionTimeToPivot, - multiplers, - allocationBounds, - { from }, - ); - - return new BTCDaiRebalancingManagerContract( - getContractInstance(truffleRebalacingTokenManager), - { from, gas: DEFAULT_GAS }, - ); - } - - public async deployETHDaiRebalancingManagerAsync( - coreAddress: Address, - ethPriceFeedAddress: Address, - daiAddress: Address, - ethAddress: Address, - setTokenFactoryAddress: Address, - auctionLibrary: Address, - auctionTimeToPivot: BigNumber = new BigNumber(100000), - multiplers: BigNumber[], - allocationBounds: BigNumber[], - from: Address = this._tokenOwnerAddress - ): Promise { - const truffleRebalacingTokenManager = await ETHDaiRebalancingManager.new( - coreAddress, - ethPriceFeedAddress, - daiAddress, - ethAddress, - setTokenFactoryAddress, - auctionLibrary, - auctionTimeToPivot, - multiplers, - allocationBounds, - { from }, - ); - - return new ETHDaiRebalancingManagerContract( - getContractInstance(truffleRebalacingTokenManager), - { from, gas: DEFAULT_GAS }, - ); - } - public async deployMACOStrategyManagerAsync( coreAddress: Address, movingAveragePriceFeedAddress: Address, @@ -619,31 +514,6 @@ export class ManagerHelper { } } - public getExpectedBtcEthNextSetParameters( - btcPrice: BigNumber, - ethPrice: BigNumber, - btcMultiplier: BigNumber, - ethMultiplier: BigNumber, - ): any { - let units: BigNumber[]; - let naturalUnit: BigNumber; - if (btcPrice.greaterThanOrEqualTo(ethPrice)) { - const ethUnits = btcPrice.mul(new BigNumber(10 ** 10)).div(ethPrice).round(0, 3); - units = [new BigNumber(1).mul(btcMultiplier), ethUnits.mul(ethMultiplier)]; - naturalUnit = new BigNumber(10 ** 10); - } else { - const btcUnits = ethPrice.mul(new BigNumber(100)).mul(btcMultiplier).div(btcPrice).round(0, 3); - const ethUnits = new BigNumber(100).mul(new BigNumber(10 ** 10)).mul(ethMultiplier); - units = [btcUnits, ethUnits]; - naturalUnit = new BigNumber(10 ** 12); - } - - return { - units, - naturalUnit, - }; - } - public getExpectedGeneralNextSetParameters( tokenOnePrice: BigNumber, tokenTwoPrice: BigNumber, @@ -915,61 +785,6 @@ export class ManagerHelper { }; } - public async getExpectedBtcEthAuctionParameters( - btcPrice: BigNumber, - ethPrice: BigNumber, - btcMultiplier: BigNumber, - ethMultiplier: BigNumber, - auctionTimeToPivot: BigNumber, - currentSetToken: SetTokenContract, - ): Promise { - const THIRTY_MINUTES_IN_SECONDS = new BigNumber(30 * 60); - const BTC_DECIMALS = WBTC_FULL_TOKEN_UNITS; - const ETH_DECIMALS = WETH_FULL_TOKEN_UNITS; - - const nextSetParams = this.getExpectedBtcEthNextSetParameters( - btcPrice, - ethPrice, - btcMultiplier, - ethMultiplier, - ); - - const currentSetNaturalUnit = await currentSetToken.naturalUnit.callAsync(); - const currentSetUnits = await currentSetToken.getUnits.callAsync(); - - const currentSetDollarAmount = this.computeTokenValue( - currentSetUnits, - currentSetNaturalUnit, - btcPrice, - ethPrice, - BTC_DECIMALS, - ETH_DECIMALS, - ); - - const nextSetDollarAmount = this.computeTokenValue( - nextSetParams['units'], - nextSetParams['naturalUnit'], - btcPrice, - ethPrice, - BTC_DECIMALS, - ETH_DECIMALS, - ); - - const fairValue = nextSetDollarAmount.div(currentSetDollarAmount).mul(1000).round(0, 3); - const onePercentSlippage = fairValue.div(100).round(0, 3); - - const thirtyMinutePeriods = auctionTimeToPivot.div(THIRTY_MINUTES_IN_SECONDS).round(0, 3); - const halfPriceRange = thirtyMinutePeriods.mul(onePercentSlippage).div(2).round(0, 3); - - const auctionStartPrice = fairValue.sub(halfPriceRange); - const auctionPivotPrice = fairValue.add(halfPriceRange); - - return { - auctionStartPrice, - auctionPivotPrice, - }; - } - public async calculateSetTokenValue( setToken: SetTokenContract, componentPrices: BigNumber[],