Contract Overview
Balance:
0 AVAX
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x614b2fc866a6d7f439091f03e2304c7e503f7e61ab864dd12e49f58ff26d9bf4 | Set Addresses | 6600314 | 585 days 20 hrs ago | 0x9e97ae5d91da840eed47a5b07fdabbc2bfad8ada | IN | 0xa0c61494842176ce0cdb828542b4c3a842cc29af | 0 AVAX | 0.00967755 | |
0x6d78f522a81f2864681385f0ac15523e9ac5532612f92d3be5fc48d0f7692cc7 | Set Addresses | 6067306 | 598 days 1 hr ago | 0x9e97ae5d91da840eed47a5b07fdabbc2bfad8ada | IN | 0xa0c61494842176ce0cdb828542b4c3a842cc29af | 0 AVAX | 0.0028593 | |
0x23e47f4a8bc471d7c3c21e67bf30a262333844a183849733e00b93e14fa5e44f | 0x60806040 | 6066563 | 598 days 1 hr ago | 0x9e97ae5d91da840eed47a5b07fdabbc2bfad8ada | IN | Contract Creation | 0 AVAX | 0.18164259 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Similar Match Source Code This contract matches the deployed ByteCode of the Source Code for Contract 0xa7C7633027B6ec8f8E69Bfa94044ec6F709112c3 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
TroveManagerLiquidations
Compiler Version
v0.6.11+commit.5ef660b1
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./Interfaces/IWAsset.sol"; import "./Dependencies/TroveManagerBase.sol"; /** * TroveManagerLiquidations is derived from TroveManager and has all the functions * related to Liquidations. */ contract TroveManagerLiquidations is TroveManagerBase { address yetiFinanceTreasury; struct LiquidationValues { uint256 entireTroveDebt; newColls entireTroveColl; newColls collGasCompensation; uint256 YUSDGasCompensation; uint256 debtToOffset; newColls collToSendToSP; uint256 debtToRedistribute; newColls collToRedistribute; newColls collSurplus; } struct LiquidationTotals { uint256 totalVCInSequence; uint256 totalDebtInSequence; newColls totalCollGasCompensation; uint256 totalYUSDGasCompensation; uint256 totalDebtToOffset; newColls totalCollToSendToSP; uint256 totalDebtToRedistribute; newColls totalCollToRedistribute; newColls totalCollSurplus; } struct LocalVariables_LiquidationSequence { uint256 remainingYUSDInStabPool; uint256 i; uint256 ICR; address user; bool backToNormalMode; uint256 entireSystemDebt; uint256 entireSystemColl; } struct LocalVariables_OuterLiquidationFunction { uint256 YUSDInStabPool; bool recoveryModeAtStart; uint256 liquidatedDebt; } struct LocalVariables_InnerSingleLiquidateFunction { newColls collToLiquidate; uint256 pendingDebtReward; newColls pendingCollReward; } struct LocalVariables_ORVals { uint256 debtToOffset; newColls collToSendToSP; uint256 debtToRedistribute; newColls collToRedistribute; newColls collSurplus; } event TroveLiquidated( address indexed _borrower, uint256 _debt, TroveManagerOperation _operation ); event Liquidation( uint256 liquidatedAmount, uint256 totalYUSDGasCompensation, address[] totalCollTokens, uint256[] totalCollAmounts, address[] totalCollGasCompTokens, uint256[] totalCollGasCompAmounts ); function setAddresses( address _borrowerOperationsAddress, address _activePoolAddress, address _defaultPoolAddress, address _stabilityPoolAddress, address _gasPoolAddress, address _collSurplusPoolAddress, address _yusdTokenAddress, address _sortedTrovesAddress, address _yetiTokenAddress, address _sYETIAddress, address _whitelistAddress, address _troveManagerAddress, address _yetiFinanceTreasury ) external onlyOwner { checkContract(_borrowerOperationsAddress); checkContract(_activePoolAddress); checkContract(_defaultPoolAddress); checkContract(_stabilityPoolAddress); checkContract(_gasPoolAddress); checkContract(_collSurplusPoolAddress); checkContract(_yusdTokenAddress); checkContract(_sortedTrovesAddress); checkContract(_yetiTokenAddress); checkContract(_sYETIAddress); checkContract(_whitelistAddress); checkContract(_troveManagerAddress); checkContract(_yetiFinanceTreasury); borrowerOperationsAddress = _borrowerOperationsAddress; activePool = IActivePool(_activePoolAddress); defaultPool = IDefaultPool(_defaultPoolAddress); stabilityPoolContract = IStabilityPool(_stabilityPoolAddress); whitelist = IWhitelist(_whitelistAddress); gasPoolAddress = _gasPoolAddress; collSurplusPool = ICollSurplusPool(_collSurplusPoolAddress); yusdTokenContract = IYUSDToken(_yusdTokenAddress); sortedTroves = ISortedTroves(_sortedTrovesAddress); yetiTokenContract = IYETIToken(_yetiTokenAddress); sYETIContract = ISYETI(_sYETIAddress); troveManager = ITroveManager(_troveManagerAddress); troveManagerAddress = _troveManagerAddress; yetiFinanceTreasury = _yetiFinanceTreasury; emit BorrowerOperationsAddressChanged(_borrowerOperationsAddress); emit ActivePoolAddressChanged(_activePoolAddress); emit DefaultPoolAddressChanged(_defaultPoolAddress); emit StabilityPoolAddressChanged(_stabilityPoolAddress); emit GasPoolAddressChanged(_gasPoolAddress); emit CollSurplusPoolAddressChanged(_collSurplusPoolAddress); emit YUSDTokenAddressChanged(_yusdTokenAddress); emit SortedTrovesAddressChanged(_sortedTrovesAddress); emit YETITokenAddressChanged(_yetiTokenAddress); emit SYETIAddressChanged(_sYETIAddress); _renounceOwnership(); } /** * Function for liquidating a list of troves in a single transaction. Will perform as many as it can * and looks at if it is eligible for liquidation based on the current ICR value. */ function batchLiquidateTroves(address[] memory _troveArray, address _liquidator) public { _requireCallerisTroveManager(); require(_troveArray.length != 0, "TroveManager: Calldata address array must not be empty"); IActivePool activePoolCached = activePool; IDefaultPool defaultPoolCached = defaultPool; IStabilityPool stabilityPoolCached = stabilityPoolContract; LocalVariables_OuterLiquidationFunction memory vars; LiquidationTotals memory totals; vars.YUSDInStabPool = stabilityPoolCached.getTotalYUSDDeposits(); vars.recoveryModeAtStart = _checkRecoveryMode(); // Perform the appropriate liquidation sequence - tally values and obtain their totals. if (vars.recoveryModeAtStart) { totals = _getTotalFromBatchLiquidate_RecoveryMode( activePoolCached, defaultPoolCached, vars.YUSDInStabPool, _troveArray ); } else { // if !vars.recoveryModeAtStart totals = _getTotalsFromBatchLiquidate_NormalMode( activePoolCached, defaultPoolCached, vars.YUSDInStabPool, _troveArray ); } require(totals.totalDebtInSequence > 0, "TroveManager: nothing to liquidate"); // Move liquidated Collateral and YUSD to the appropriate pools stabilityPoolCached.offset( totals.totalDebtToOffset, totals.totalCollToSendToSP.tokens, totals.totalCollToSendToSP.amounts ); troveManager.redistributeDebtAndColl( activePoolCached, defaultPoolCached, totals.totalDebtToRedistribute, totals.totalCollToRedistribute.tokens, totals.totalCollToRedistribute.amounts ); if (_CollsIsNonZero(totals.totalCollSurplus)) { activePoolCached.sendCollaterals( address(collSurplusPool), totals.totalCollSurplus.tokens, totals.totalCollSurplus.amounts ); } // Update system snapshots troveManager.updateSystemSnapshots_excludeCollRemainder( activePoolCached, totals.totalCollGasCompensation.tokens, totals.totalCollGasCompensation.amounts ); vars.liquidatedDebt = totals.totalDebtInSequence; // merge the colls into one to emit correct event. newColls memory sumCollsResult = _sumColls( totals.totalCollToSendToSP, totals.totalCollToRedistribute ); sumCollsResult = _sumColls(sumCollsResult, totals.totalCollSurplus); emit Liquidation( vars.liquidatedDebt, totals.totalYUSDGasCompensation, sumCollsResult.tokens, sumCollsResult.amounts, totals.totalCollGasCompensation.tokens, totals.totalCollGasCompensation.amounts ); // Send gas compensation to caller _sendGasCompensation( activePoolCached, _liquidator, totals.totalYUSDGasCompensation, totals.totalCollGasCompensation.tokens, totals.totalCollGasCompensation.amounts ); } /* * This function is used when the batch liquidation sequence starts during Recovery Mode. However, it * handle the case where the system *leaves* Recovery Mode, part way through the liquidation sequence */ function _getTotalFromBatchLiquidate_RecoveryMode( IActivePool _activePool, IDefaultPool _defaultPool, uint256 _YUSDInStabPool, address[] memory _troveArray ) internal returns (LiquidationTotals memory totals) { LocalVariables_LiquidationSequence memory vars; LiquidationValues memory singleLiquidation; vars.remainingYUSDInStabPool = _YUSDInStabPool; vars.backToNormalMode = false; vars.entireSystemDebt = getEntireSystemDebt(); // get total VC vars.entireSystemColl = getEntireSystemColl(); for (vars.i = 0; vars.i < _troveArray.length; vars.i++) { vars.user = _troveArray[vars.i]; // Skip non-active troves Status userStatus = Status(troveManager.getTroveStatus(vars.user)); if (userStatus != Status.active) { continue; } vars.ICR = troveManager.getCurrentICR(vars.user); if (!vars.backToNormalMode) { // Skip this trove if ICR is greater than MCR and Stability Pool is empty if (vars.ICR >= MCR && vars.remainingYUSDInStabPool == 0) { continue; } uint256 TCR = LiquityMath._computeCR(vars.entireSystemColl, vars.entireSystemDebt); singleLiquidation = _liquidateRecoveryMode( _activePool, _defaultPool, vars.user, vars.ICR, vars.remainingYUSDInStabPool, TCR ); // Update aggregate trackers vars.remainingYUSDInStabPool = vars.remainingYUSDInStabPool.sub( singleLiquidation.debtToOffset ); vars.entireSystemDebt = vars.entireSystemDebt.sub(singleLiquidation.debtToOffset); uint256 collToSendToSpVc = _getVCColls(singleLiquidation.collToSendToSP); uint256 collGasCompensationTotal = _getVCColls( singleLiquidation.collGasCompensation ); uint256 collSurplusTotal = _getVCColls(singleLiquidation.collSurplus); vars.entireSystemColl = vars .entireSystemColl .sub(collToSendToSpVc) .sub(collGasCompensationTotal) .sub(collSurplusTotal); // Add liquidation values to their respective running totals totals = _addLiquidationValuesToTotals(totals, singleLiquidation); vars.backToNormalMode = !_checkPotentialRecoveryMode( vars.entireSystemColl, vars.entireSystemDebt ); } else if (vars.backToNormalMode && vars.ICR < MCR) { singleLiquidation = _liquidateNormalMode( _activePool, _defaultPool, vars.user, vars.remainingYUSDInStabPool ); vars.remainingYUSDInStabPool = vars.remainingYUSDInStabPool.sub( singleLiquidation.debtToOffset ); // Add liquidation values to their respective running totals totals = _addLiquidationValuesToTotals(totals, singleLiquidation); } else continue; // In Normal Mode skip troves with ICR >= MCR } } function _getTotalsFromBatchLiquidate_NormalMode( IActivePool _activePool, IDefaultPool _defaultPool, uint256 _YUSDInStabPool, address[] memory _troveArray ) internal returns (LiquidationTotals memory totals) { LocalVariables_LiquidationSequence memory vars; LiquidationValues memory singleLiquidation; vars.remainingYUSDInStabPool = _YUSDInStabPool; for (vars.i = 0; vars.i < _troveArray.length; vars.i++) { vars.user = _troveArray[vars.i]; vars.ICR = troveManager.getCurrentICR(vars.user); if (vars.ICR < MCR) { singleLiquidation = _liquidateNormalMode( _activePool, _defaultPool, vars.user, vars.remainingYUSDInStabPool ); vars.remainingYUSDInStabPool = vars.remainingYUSDInStabPool.sub( singleLiquidation.debtToOffset ); // Add liquidation values to their respective running totals totals = _addLiquidationValuesToTotals(totals, singleLiquidation); } } } // Liquidate one trove, in Normal Mode. function _liquidateNormalMode( IActivePool _activePool, IDefaultPool _defaultPool, address _borrower, uint256 _YUSDInStabPool ) internal returns (LiquidationValues memory singleLiquidation) { LocalVariables_InnerSingleLiquidateFunction memory vars; ( singleLiquidation.entireTroveDebt, singleLiquidation.entireTroveColl.tokens, singleLiquidation.entireTroveColl.amounts, vars.pendingDebtReward, vars.pendingCollReward.tokens, vars.pendingCollReward.amounts ) = troveManager.getEntireDebtAndColls(_borrower); troveManager.movePendingTroveRewardsToActivePool( _activePool, _defaultPool, vars.pendingDebtReward, vars.pendingCollReward.tokens, vars.pendingCollReward.amounts, _borrower ); troveManager.removeStakeTLR(_borrower); singleLiquidation.collGasCompensation = _getCollGasCompensation( singleLiquidation.entireTroveColl ); // WAssets sent as liquidation reward will be unstaked and no longer accrue rewards _updateWAssetsRewardOwner(singleLiquidation.collGasCompensation, _borrower, address(0)); singleLiquidation.YUSDGasCompensation = YUSD_GAS_COMPENSATION; vars.collToLiquidate.tokens = singleLiquidation.entireTroveColl.tokens; vars.collToLiquidate.amounts = new uint256[](vars.collToLiquidate.tokens.length); for (uint256 i = 0; i < vars.collToLiquidate.tokens.length; i++) { vars.collToLiquidate.amounts[i] = singleLiquidation.entireTroveColl.amounts[i].sub( singleLiquidation.collGasCompensation.amounts[i] ); } LocalVariables_ORVals memory or_vals = _getOffsetAndRedistributionVals( singleLiquidation.entireTroveDebt, vars.collToLiquidate, _YUSDInStabPool ); newColls memory collsToUpdate = _sumColls(or_vals.collToSendToSP, or_vals.collToRedistribute); // rewards for WAssets sent to SP and collToRedistribute will // accrue to Yeti Finance Treasury until the assets are claimed _updateWAssetsRewardOwner(collsToUpdate, _borrower, yetiFinanceTreasury); singleLiquidation = _updateSingleLiquidation(or_vals, singleLiquidation); troveManager.closeTroveLiquidation(_borrower); if (_CollsIsNonZero(singleLiquidation.collSurplus)) { troveManager.collSurplusUpdate( _borrower, singleLiquidation.collSurplus.tokens, singleLiquidation.collSurplus.amounts ); } emit TroveLiquidated( _borrower, singleLiquidation.entireTroveDebt, TroveManagerOperation.liquidateInNormalMode ); newColls memory borrowerColls; emit TroveUpdated( _borrower, 0, borrowerColls.tokens, borrowerColls.amounts, TroveManagerOperation.liquidateInNormalMode ); return singleLiquidation; } // Liquidate one trove, in Recovery Mode. function _liquidateRecoveryMode( IActivePool _activePool, IDefaultPool _defaultPool, address _borrower, uint256 _ICR, uint256 _YUSDInStabPool, uint256 _TCR ) internal returns (LiquidationValues memory singleLiquidation) { LocalVariables_InnerSingleLiquidateFunction memory vars; if (troveManager.getTroveOwnersCount() <= 1) { return singleLiquidation; } // don't liquidate if last trove ( singleLiquidation.entireTroveDebt, singleLiquidation.entireTroveColl.tokens, singleLiquidation.entireTroveColl.amounts, vars.pendingDebtReward, vars.pendingCollReward.tokens, vars.pendingCollReward.amounts ) = troveManager.getEntireDebtAndColls(_borrower); singleLiquidation.collGasCompensation = _getCollGasCompensation( singleLiquidation.entireTroveColl ); // WAssets sent as liquidation reward will be unstaked and no longer accrue rewards _updateWAssetsRewardOwner(singleLiquidation.collGasCompensation, _borrower, address(0)); singleLiquidation.YUSDGasCompensation = YUSD_GAS_COMPENSATION; vars.collToLiquidate.tokens = singleLiquidation.entireTroveColl.tokens; vars.collToLiquidate.amounts = new uint256[](vars.collToLiquidate.tokens.length); for (uint256 i = 0; i < vars.collToLiquidate.tokens.length; i++) { vars.collToLiquidate.amounts[i] = singleLiquidation.entireTroveColl.amounts[i].sub( singleLiquidation.collGasCompensation.amounts[i] ); } // If ICR <= 100%, purely redistribute the Trove across all active Troves if (_ICR <= _100pct) { troveManager.movePendingTroveRewardsToActivePool( _activePool, _defaultPool, vars.pendingDebtReward, vars.pendingCollReward.tokens, vars.pendingCollReward.amounts, _borrower ); // troveManager.movePendingTroveRewardsToActivePool(_activePool, _defaultPool, vars.pendingDebtReward, singleLiquidation.entireTroveColl.tokens, singleLiquidation.entireTroveColl.amounts); troveManager.removeStakeTLR(_borrower); singleLiquidation.debtToOffset = 0; newColls memory emptyColls; singleLiquidation.collToSendToSP = emptyColls; singleLiquidation.debtToRedistribute = singleLiquidation.entireTroveDebt; singleLiquidation.collToRedistribute = vars.collToLiquidate; // WAsset rewards for collToRedistribute will accrue to // Yeti Finance Treasury until the WAssets are claimed by troves _updateWAssetsRewardOwner(singleLiquidation.collToRedistribute, _borrower, yetiFinanceTreasury); troveManager.closeTroveLiquidation(_borrower); emit TroveLiquidated( _borrower, singleLiquidation.entireTroveDebt, TroveManagerOperation.liquidateInRecoveryMode ); newColls memory borrowerColls;// = troveManager.getTroveColls(_borrower); emit TroveUpdated( _borrower, 0, borrowerColls.tokens, borrowerColls.amounts, TroveManagerOperation.liquidateInRecoveryMode ); // If 100% < ICR < MCR, offset as much as possible, and redistribute the remainder // ICR > 100% is implied by prevoius state. } else if (_ICR < MCR) { troveManager.movePendingTroveRewardsToActivePool( _activePool, _defaultPool, vars.pendingDebtReward, vars.pendingCollReward.tokens, vars.pendingCollReward.amounts, _borrower ); troveManager.removeStakeTLR(_borrower); LocalVariables_ORVals memory or_vals = _getOffsetAndRedistributionVals( singleLiquidation.entireTroveDebt, vars.collToLiquidate, _YUSDInStabPool ); newColls memory collsToUpdate = _sumColls(or_vals.collToSendToSP, or_vals.collToRedistribute); // rewards for WAssets sent to SP and collToRedistribute will // accrue to Yeti Finance Treasury until the assets are claimed _updateWAssetsRewardOwner(collsToUpdate, _borrower, yetiFinanceTreasury); singleLiquidation = _updateSingleLiquidation(or_vals, singleLiquidation); troveManager.closeTroveLiquidation(_borrower); emit TroveLiquidated( _borrower, singleLiquidation.entireTroveDebt, TroveManagerOperation.liquidateInRecoveryMode ); newColls memory borrowerColls;// = troveManager.getTroveColls(_borrower); emit TroveUpdated( _borrower, 0, borrowerColls.tokens, borrowerColls.amounts, TroveManagerOperation.liquidateInRecoveryMode ); /* * If 110% <= ICR < current TCR (accounting for the preceding liquidations in the current sequence) * and there is YUSD in the Stability Pool, only offset, with no redistribution, * but at a capped rate of 1.1 and only if the whole debt can be liquidated. * The remainder due to the capped rate will be claimable as collateral surplus. * ICR >= 110% is implied from last else if statement. */ } else if ( (_ICR < _TCR) && (singleLiquidation.entireTroveDebt <= _YUSDInStabPool) ) { troveManager.movePendingTroveRewardsToActivePool( _activePool, _defaultPool, vars.pendingDebtReward, vars.pendingCollReward.tokens, vars.pendingCollReward.amounts, _borrower ); assert(_YUSDInStabPool != 0); troveManager.removeStakeTLR(_borrower); singleLiquidation = _getCappedOffsetVals( singleLiquidation.entireTroveDebt, singleLiquidation.entireTroveColl.tokens, singleLiquidation.entireTroveColl.amounts, MCR ); newColls memory collsToUpdate = _sumColls( singleLiquidation.collToSendToSP, singleLiquidation.collToRedistribute ); // rewards for WAssets sent to SP and collToRedistribute will // accrue to Yeti Finance Treasury until the assets are claimed _updateWAssetsRewardOwner(collsToUpdate, _borrower, yetiFinanceTreasury); troveManager.closeTroveLiquidation(_borrower); emit TroveLiquidated( _borrower, singleLiquidation.entireTroveDebt, TroveManagerOperation.liquidateInRecoveryMode ); newColls memory borrowerColls; emit TroveUpdated( _borrower, 0, borrowerColls.tokens, borrowerColls.amounts, TroveManagerOperation.liquidateInRecoveryMode ); } else { // if (_ICR >= MCR && ( _ICR >= _TCR || singleLiquidation.entireTroveDebt > _YUSDInStabPool)) LiquidationValues memory zeroVals; return zeroVals; } if (_CollsIsNonZero(singleLiquidation.collSurplus)) { troveManager.collSurplusUpdate( _borrower, singleLiquidation.collSurplus.tokens, singleLiquidation.collSurplus.amounts ); } return singleLiquidation; } function _updateSingleLiquidation( LocalVariables_ORVals memory or_vals, LiquidationValues memory singleLiquidation ) internal pure returns (LiquidationValues memory) { singleLiquidation.debtToOffset = or_vals.debtToOffset; singleLiquidation.collToSendToSP = or_vals.collToSendToSP; singleLiquidation.debtToRedistribute = or_vals.debtToRedistribute; singleLiquidation.collToRedistribute = or_vals.collToRedistribute; singleLiquidation.collSurplus = or_vals.collSurplus; return singleLiquidation; } /* In a full liquidation, returns the values for a trove's coll and debt to be offset, and coll and debt to be * redistributed to active troves. _colls parameters is the _colls to be liquidated (total trove colls minus collateral for gas compensation) * collsToRedistribute.tokens and collsToRedistribute.amounts should be the same length * and should be the same length as _colls.tokens and _colls.amounts. * If there is any colls redistributed to stability pool, collsToSendToSP.tokens and collsToSendToSP.amounts * will be length equal to _colls.tokens and _colls.amounts. However, if no colls are redistributed to stability pool (which is the case when _YUSDInStabPool == 0), * then collsToSendToSP.tokens and collsToSendToSP.amounts will be empty. */ function _getOffsetAndRedistributionVals( uint256 _entireTroveDebt, newColls memory _collsToLiquidate, uint256 _YUSDInStabPool ) internal view returns (LocalVariables_ORVals memory or_vals) { or_vals.collToRedistribute.tokens = _collsToLiquidate.tokens; or_vals.collToRedistribute.amounts = new uint256[](_collsToLiquidate.tokens.length); if (_YUSDInStabPool > 0) { /* * Offset as much debt & collateral as possible against the Stability Pool, and redistribute the remainder * between all active troves. * * If the trove's debt is larger than the deposited YUSD in the Stability Pool: * * - Offset an amount of the trove's debt equal to the YUSD in the Stability Pool * - Remainder of trove's debt will be redistributed * - Trove collateral can be partitioned into two parts: * - (1) Offsetting Collateral = (debtToOffset / troveDebt) * Collateral * - (2) Redistributed Collateral = Total Collateral - Offsetting Collateral * - The max offsetting collateral that can be sent to the stability pool is an amount of collateral such that * - the stability pool receives 110% of value of the debtToOffset. Any extra Offsetting Collateral is * - sent to the collSurplusPool and can be claimed by the borrower. */ or_vals.collToSendToSP.tokens = _collsToLiquidate.tokens; or_vals.collToSendToSP.amounts = new uint256[](_collsToLiquidate.tokens.length); or_vals.collSurplus.tokens = _collsToLiquidate.tokens; or_vals.collSurplus.amounts = new uint256[](_collsToLiquidate.tokens.length); or_vals.debtToOffset = LiquityMath._min(_entireTroveDebt, _YUSDInStabPool); or_vals.debtToRedistribute = _entireTroveDebt.sub(or_vals.debtToOffset); uint toLiquidateCollValueUSD = _getUSDColls(_collsToLiquidate); // collOffsetRatio: max percentage of the collateral that can be sent to the SP as offsetting collateral // collOffsetRatio = percentage of the trove's debt that can be offset by the stability pool uint256 collOffsetRatio = _100pct.mul(_100pct).mul(or_vals.debtToOffset).div(_entireTroveDebt); // SPRatio: percentage of liquidated collateral that needs to be sent to SP in order to give SP depositors // $110 of collateral for every 100 YUSD they are using to liquidate. uint256 SPRatio = or_vals.debtToOffset.mul(_100pct).mul(_110pct).div(toLiquidateCollValueUSD); // But SP ratio is capped at collOffsetRatio: SPRatio = LiquityMath._min(collOffsetRatio, SPRatio); // if there is extra collateral left in the offset portion of the collateral after // giving stability pool holders $110 of collateral for every 100 YUSD that is taken from them, // then this is surplus collateral that can be claimed by the borrower uint256 collSurplusRatio = collOffsetRatio.sub(SPRatio); for (uint256 i = 0; i < _collsToLiquidate.tokens.length; i++) { or_vals.collToSendToSP.amounts[i] = _collsToLiquidate.amounts[i].mul(SPRatio).div( _100pct ).div(_100pct); or_vals.collSurplus.amounts[i] = _collsToLiquidate .amounts[i] .mul(collSurplusRatio) .div(_100pct) .div(_100pct); // remaining collateral is redistributed: or_vals.collToRedistribute.amounts[i] = _collsToLiquidate .amounts[i] .sub(or_vals.collToSendToSP.amounts[i]) .sub(or_vals.collSurplus.amounts[i]); } } else { // all colls are redistributed because no YUSD in stability pool to liquidate or_vals.debtToOffset = 0; for (uint256 i = 0; i < _collsToLiquidate.tokens.length; i++) { or_vals.collToRedistribute.amounts[i] = _collsToLiquidate.amounts[i]; } or_vals.debtToRedistribute = _entireTroveDebt; } } function _addLiquidationValuesToTotals( LiquidationTotals memory oldTotals, LiquidationValues memory singleLiquidation ) internal view returns (LiquidationTotals memory newTotals) { // Tally all the values with their respective running totals //update one of these newTotals.totalCollGasCompensation = _sumColls( oldTotals.totalCollGasCompensation, singleLiquidation.collGasCompensation ); newTotals.totalYUSDGasCompensation = oldTotals.totalYUSDGasCompensation.add( singleLiquidation.YUSDGasCompensation ); newTotals.totalDebtInSequence = oldTotals.totalDebtInSequence.add( singleLiquidation.entireTroveDebt ); newTotals.totalDebtToOffset = oldTotals.totalDebtToOffset.add( singleLiquidation.debtToOffset ); newTotals.totalCollToSendToSP = _sumColls( oldTotals.totalCollToSendToSP, singleLiquidation.collToSendToSP ); newTotals.totalDebtToRedistribute = oldTotals.totalDebtToRedistribute.add( singleLiquidation.debtToRedistribute ); newTotals.totalCollToRedistribute = _sumColls( oldTotals.totalCollToRedistribute, singleLiquidation.collToRedistribute ); newTotals.totalCollSurplus = _sumColls( oldTotals.totalCollSurplus, singleLiquidation.collSurplus ); return newTotals; } /* * Get its offset coll/debt and Collateral gas comp, and close the trove. */ function _getCappedOffsetVals ( uint _entireTroveDebt, address[] memory _troveTokens, uint[] memory _troveAmounts, uint _MCR ) internal view returns (LiquidationValues memory singleLiquidation) { newColls memory _entireTroveColl; _entireTroveColl.tokens = _troveTokens; _entireTroveColl.amounts = _troveAmounts; uint USD_Value_To_Send_To_SP = _MCR.mul(_entireTroveDebt).div(_100pct); uint USD_Value_of_Trove_Colls = _getUSDColls(_entireTroveColl); uint SPRatio = USD_Value_To_Send_To_SP.mul(_100pct).div(USD_Value_of_Trove_Colls); SPRatio = LiquityMath._min(SPRatio, _100pct); singleLiquidation.entireTroveDebt = _entireTroveDebt; singleLiquidation.entireTroveColl = _entireTroveColl; singleLiquidation.YUSDGasCompensation = YUSD_GAS_COMPENSATION; singleLiquidation.debtToOffset = _entireTroveDebt; singleLiquidation.debtToRedistribute = 0; singleLiquidation.collToSendToSP.tokens = _troveTokens; singleLiquidation.collToSendToSP.amounts = new uint[](_troveTokens.length); singleLiquidation.collSurplus.tokens = _troveTokens; singleLiquidation.collSurplus.amounts = new uint[](_troveTokens.length); singleLiquidation.collGasCompensation.tokens = _troveTokens; singleLiquidation.collGasCompensation.amounts = new uint[](_troveTokens.length); for (uint i = 0; i < _troveTokens.length; i++) { uint _cappedCollAmount = SPRatio.mul(_troveAmounts[i]).div(_100pct); uint _gasComp = _cappedCollAmount.div(PERCENT_DIVISOR); uint _toSP = _cappedCollAmount.sub(_gasComp); uint _collSurplus = _troveAmounts[i].sub(_cappedCollAmount); singleLiquidation.collGasCompensation.amounts[i] = _gasComp; singleLiquidation.collToSendToSP.amounts[i] = _toSP; singleLiquidation.collSurplus.amounts[i] = _collSurplus; } } function _sendGasCompensation( IActivePool _activePool, address _liquidator, uint256 _YUSD, address[] memory _tokens, uint256[] memory _amounts ) internal { if (_YUSD > 0) { yusdTokenContract.returnFromPool(gasPoolAddress, _liquidator, _YUSD); } _activePool.sendCollateralsUnwrap(_liquidator, _tokens, _amounts, false); } /* * Update rewards tracking so future rewards go to Yeti Finance Treasury * for the trove's asset that have been liquidated and moved to either the * Stability Pool or Default Pool */ function _updateWAssetsRewardOwner(newColls memory _colls, address _borrower, address _newOwner) internal { for (uint i = 0; i < _colls.tokens.length; i++) { address token = _colls.tokens[i]; uint amount = _colls.amounts[i]; if (whitelist.isWrapped(token)) { IWAsset(token).updateReward(_borrower, _newOwner, amount); } } } function _requireCallerisTroveManager() internal view { require(msg.sender == troveManagerAddress); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; // Wrapped Asset interface IWAsset { function wrap(uint _amount, address _from, address _to, address _rewardOwner) external; function unwrapFor(address _for, uint amount) external; function updateReward(address from, address to, uint amount) external; function claimReward(address _to) external; function claimRewardFor(address _for) external; function getPendingRewards(address _for) external returns (address[] memory tokens, uint[] memory amounts); function endTreasuryReward(uint _amount) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "../Interfaces/ITroveManager.sol"; import "../Interfaces/IStabilityPool.sol"; import "../Interfaces/ICollSurplusPool.sol"; import "../Interfaces/IYUSDToken.sol"; import "../Interfaces/ISortedTroves.sol"; import "../Interfaces/IYETIToken.sol"; import "../Interfaces/ISYETI.sol"; import "../Interfaces/IActivePool.sol"; import "../Interfaces/IWhitelist.sol"; import "../Interfaces/ITroveManagerLiquidations.sol"; import "../Interfaces/ITroveManagerRedemptions.sol"; import "./LiquityBase.sol"; import "./Ownable.sol"; import "./CheckContract.sol"; /** * Contains shared functionality of TroveManagerLiquidations, TroveManagerRedemptions, and TroveManager. * Keeps addresses to cache, events, structs, status, etc. Also keeps Trove struct. */ contract TroveManagerBase is LiquityBase, Ownable, CheckContract { // --- Connected contract declarations --- address public borrowerOperationsAddress; IStabilityPool stabilityPoolContract; ITroveManager public troveManager; IYUSDToken yusdTokenContract; IYETIToken yetiTokenContract; ISYETI sYETIContract; ITroveManagerRedemptions troveManagerRedemptions; ITroveManagerLiquidations troveManagerLiquidations; address gasPoolAddress; address public troveManagerAddress; address public troveManagerRedemptionsAddress; address public troveManagerLiquidationsAddress; // A doubly linked list of Troves, sorted by their sorted by their individual collateral ratios ISortedTroves public sortedTroves; ICollSurplusPool collSurplusPool; struct ContractsCache { IActivePool activePool; IDefaultPool defaultPool; IYUSDToken yusdToken; ISYETI sYETI; ISortedTroves sortedTroves; ICollSurplusPool collSurplusPool; address gasPoolAddress; } struct SingleRedemptionValues { uint YUSDLot; newColls CollLot; bool cancelledPartial; } enum Status { nonExistent, active, closedByOwner, closedByLiquidation, closedByRedemption } enum TroveManagerOperation { applyPendingRewards, liquidateInNormalMode, liquidateInRecoveryMode, redeemCollateral } // Store the necessary data for a trove struct Trove { newColls colls; uint debt; mapping(address => uint) stakes; Status status; uint128 arrayIndex; } event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress); event YUSDTokenAddressChanged(address _newYUSDTokenAddress); event ActivePoolAddressChanged(address _activePoolAddress); event DefaultPoolAddressChanged(address _defaultPoolAddress); event StabilityPoolAddressChanged(address _stabilityPoolAddress); event GasPoolAddressChanged(address _gasPoolAddress); event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress); event SortedTrovesAddressChanged(address _sortedTrovesAddress); event YETITokenAddressChanged(address _yetiTokenAddress); event SYETIAddressChanged(address _sYETIAddress); event TroveUpdated(address indexed _borrower, uint _debt, address[] _tokens, uint[] _amounts, TroveManagerOperation operation); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./ILiquityBase.sol"; import "./IStabilityPool.sol"; import "./IYUSDToken.sol"; import "./IYETIToken.sol"; import "./ISYETI.sol"; import "./IActivePool.sol"; import "./IDefaultPool.sol"; // Common interface for the Trove Manager. interface ITroveManager is ILiquityBase { // --- Events --- event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress); event PriceFeedAddressChanged(address _newPriceFeedAddress); event YUSDTokenAddressChanged(address _newYUSDTokenAddress); event ActivePoolAddressChanged(address _activePoolAddress); event DefaultPoolAddressChanged(address _defaultPoolAddress); event StabilityPoolAddressChanged(address _stabilityPoolAddress); event GasPoolAddressChanged(address _gasPoolAddress); event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress); event SortedTrovesAddressChanged(address _sortedTrovesAddress); event YETITokenAddressChanged(address _yetiTokenAddress); event SYETIAddressChanged(address _sYETIAddress); event Liquidation(uint liquidatedAmount, uint totalYUSDGasCompensation, address[] totalCollTokens, uint[] totalCollAmounts, address[] totalCollGasCompTokens, uint[] totalCollGasCompAmounts); event Redemption(uint _attemptedYUSDAmount, uint _actualYUSDAmount, uint YUSDfee, address[] tokens, uint[] amounts); event TroveLiquidated(address indexed _borrower, uint _debt, uint _coll, uint8 operation); event BaseRateUpdated(uint _baseRate); event LastFeeOpTimeUpdated(uint _lastFeeOpTime); event TotalStakesUpdated(address token, uint _newTotalStakes); event SystemSnapshotsUpdated(uint _totalStakesSnapshot, uint _totalCollateralSnapshot); event LTermsUpdated(uint _L_ETH, uint _L_YUSDDebt); event TroveSnapshotsUpdated(uint _L_ETH, uint _L_YUSDDebt); event TroveIndexUpdated(address _borrower, uint _newIndex); // --- Functions --- function setAddresses( address _borrowerOperationsAddress, address _activePoolAddress, address _defaultPoolAddress, address _stabilityPoolAddress, address _gasPoolAddress, address _collSurplusPoolAddress, address _yusdTokenAddress, address _sortedTrovesAddress, address _yetiTokenAddress, address _sYETIAddress, address _whitelistAddress, address _troveManagerRedemptionsAddress, address _troveManagerLiquidationsAddress ) external; function stabilityPool() external view returns (IStabilityPool); function yusdToken() external view returns (IYUSDToken); function yetiToken() external view returns (IYETIToken); function sYETI() external view returns (ISYETI); function getTroveOwnersCount() external view returns (uint); function getTroveFromTroveOwnersArray(uint _index) external view returns (address); function getCurrentICR(address _borrower) external view returns (uint); function liquidate(address _borrower) external; function batchLiquidateTroves(address[] calldata _troveArray, address _liquidator) external; function redeemCollateral( uint _YUSDAmount, uint _YUSDMaxFee, address _firstRedemptionHint, address _upperPartialRedemptionHint, address _lowerPartialRedemptionHint, uint _partialRedemptionHintNICR, uint _maxIterations ) external; function updateStakeAndTotalStakes(address _borrower) external; function updateTroveCollTMR(address _borrower, address[] memory addresses, uint[] memory amounts) external; function updateTroveRewardSnapshots(address _borrower) external; function addTroveOwnerToArray(address _borrower) external returns (uint index); function applyPendingRewards(address _borrower) external; // function getPendingETHReward(address _borrower) external view returns (uint); function getPendingCollRewards(address _borrower) external view returns (address[] memory, uint[] memory); function getPendingYUSDDebtReward(address _borrower) external view returns (uint); function hasPendingRewards(address _borrower) external view returns (bool); // function getEntireDebtAndColl(address _borrower) external view returns ( // uint debt, // uint coll, // uint pendingYUSDDebtReward, // uint pendingETHReward // ); function closeTrove(address _borrower) external; function removeStake(address _borrower) external; function removeStakeTMR(address _borrower) external; function updateTroveDebt(address _borrower, uint debt) external; function getRedemptionRate() external view returns (uint); function getRedemptionRateWithDecay() external view returns (uint); function getRedemptionFeeWithDecay(uint _ETHDrawn) external view returns (uint); function getBorrowingRate() external view returns (uint); function getBorrowingRateWithDecay() external view returns (uint); function getBorrowingFee(uint YUSDDebt) external view returns (uint); function getBorrowingFeeWithDecay(uint _YUSDDebt) external view returns (uint); function decayBaseRateFromBorrowing() external; function getTroveStatus(address _borrower) external view returns (uint); function isTroveActive(address _borrower) external view returns (bool); function getTroveStake(address _borrower, address _token) external view returns (uint); function getTotalStake(address _token) external view returns (uint); function getTroveDebt(address _borrower) external view returns (uint); function getL_Coll(address _token) external view returns (uint); function getL_YUSD(address _token) external view returns (uint); function getRewardSnapshotColl(address _borrower, address _token) external view returns (uint); function getRewardSnapshotYUSD(address _borrower, address _token) external view returns (uint); // returns the VC value of a trove function getTroveVC(address _borrower) external view returns (uint); function getTroveColls(address _borrower) external view returns (address[] memory, uint[] memory); function getCurrentTroveState(address _borrower) external view returns (address[] memory, uint[] memory, uint); function setTroveStatus(address _borrower, uint num) external; function updateTroveColl(address _borrower, address[] memory _tokens, uint[] memory _amounts) external; function increaseTroveDebt(address _borrower, uint _debtIncrease) external returns (uint); function decreaseTroveDebt(address _borrower, uint _collDecrease) external returns (uint); function getTCR() external view returns (uint); function checkRecoveryMode() external view returns (bool); function closeTroveRedemption(address _borrower) external; function closeTroveLiquidation(address _borrower) external; function removeStakeTLR(address _borrower) external; function updateBaseRate(uint newBaseRate) external; function calcDecayedBaseRate() external view returns (uint); function redistributeDebtAndColl(IActivePool _activePool, IDefaultPool _defaultPool, uint _debt, address[] memory _tokens, uint[] memory _amounts) external; function updateSystemSnapshots_excludeCollRemainder(IActivePool _activePool, address[] memory _tokens, uint[] memory _amounts) external; function getEntireDebtAndColls(address _borrower) external view returns (uint, address[] memory, uint[] memory, uint, address[] memory, uint[] memory); function movePendingTroveRewardsToActivePool(IActivePool _activePool, IDefaultPool _defaultPool, uint _YUSD, address[] memory _tokens, uint[] memory _amounts, address _borrower) external; function collSurplusUpdate(address _account, address[] memory _tokens, uint[] memory _amounts) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./ICollateralReceiver.sol"; /* * The Stability Pool holds YUSD tokens deposited by Stability Pool depositors. * * When a trove is liquidated, then depending on system conditions, some of its YUSD debt gets offset with * YUSD in the Stability Pool: that is, the offset debt evaporates, and an equal amount of YUSD tokens in the Stability Pool is burned. * * Thus, a liquidation causes each depositor to receive a YUSD loss, in proportion to their deposit as a share of total deposits. * They also receive an ETH gain, as the ETH collateral of the liquidated trove is distributed among Stability depositors, * in the same proportion. * * When a liquidation occurs, it depletes every deposit by the same fraction: for example, a liquidation that depletes 40% * of the total YUSD in the Stability Pool, depletes 40% of each deposit. * * A deposit that has experienced a series of liquidations is termed a "compounded deposit": each liquidation depletes the deposit, * multiplying it by some factor in range ]0,1[ * * Please see the implementation spec in the proof document, which closely follows on from the compounded deposit / ETH gain derivations: * https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf * * --- YETI ISSUANCE TO STABILITY POOL DEPOSITORS --- * * An YETI issuance event occurs at every deposit operation, and every liquidation. * * Each deposit is tagged with the address of the front end through which it was made. * * All deposits earn a share of the issued YETI in proportion to the deposit as a share of total deposits. The YETI earned * by a given deposit, is split between the depositor and the front end through which the deposit was made, based on the front end's kickbackRate. * * Please see the system Readme for an overview: * https://github.com/liquity/dev/blob/main/README.md#yeti-issuance-to-stability-providers */ interface IStabilityPool is ICollateralReceiver { // --- Events --- event StabilityPoolETHBalanceUpdated(uint _newBalance); event StabilityPoolYUSDBalanceUpdated(uint _newBalance); event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress); event TroveManagerAddressChanged(address _newTroveManagerAddress); event ActivePoolAddressChanged(address _newActivePoolAddress); event DefaultPoolAddressChanged(address _newDefaultPoolAddress); event YUSDTokenAddressChanged(address _newYUSDTokenAddress); event SortedTrovesAddressChanged(address _newSortedTrovesAddress); event PriceFeedAddressChanged(address _newPriceFeedAddress); event CommunityIssuanceAddressChanged(address _newCommunityIssuanceAddress); event P_Updated(uint _P); event S_Updated(uint _S, uint128 _epoch, uint128 _scale); event G_Updated(uint _G, uint128 _epoch, uint128 _scale); event EpochUpdated(uint128 _currentEpoch); event ScaleUpdated(uint128 _currentScale); event FrontEndRegistered(address indexed _frontEnd, uint _kickbackRate); event FrontEndTagSet(address indexed _depositor, address indexed _frontEnd); event DepositSnapshotUpdated(address indexed _depositor, uint _P, uint _S, uint _G); event FrontEndSnapshotUpdated(address indexed _frontEnd, uint _P, uint _G); event UserDepositChanged(address indexed _depositor, uint _newDeposit); event FrontEndStakeChanged(address indexed _frontEnd, uint _newFrontEndStake, address _depositor); event ETHGainWithdrawn(address indexed _depositor, uint _ETH, uint _YUSDLoss); event YETIPaidToDepositor(address indexed _depositor, uint _YETI); event YETIPaidToFrontEnd(address indexed _frontEnd, uint _YETI); event EtherSent(address _to, uint _amount); // --- Functions --- /* * Called only once on init, to set addresses of other Liquity contracts * Callable only by owner, renounces ownership at the end */ function setAddresses( address _borrowerOperationsAddress, address _troveManagerAddress, address _activePoolAddress, address _yusdTokenAddress, address _sortedTrovesAddress, address _communityIssuanceAddress, address _whitelistAddress, address _troveManagerLiquidationsAddress ) external; /* * Initial checks: * - Frontend is registered or zero address * - Sender is not a registered frontend * - _amount is not zero * --- * - Triggers a YETI issuance, based on time passed since the last issuance. The YETI issuance is shared between *all* depositors and front ends * - Tags the deposit with the provided front end tag param, if it's a new deposit * - Sends depositor's accumulated gains (YETI, ETH) to depositor * - Sends the tagged front end's accumulated YETI gains to the tagged front end * - Increases deposit and tagged front end's stake, and takes new snapshots for each. */ function provideToSP(uint _amount, address _frontEndTag) external; /* * Initial checks: * - _amount is zero or there are no under collateralized troves left in the system * - User has a non zero deposit * --- * - Triggers a YETI issuance, based on time passed since the last issuance. The YETI issuance is shared between *all* depositors and front ends * - Removes the deposit's front end tag if it is a full withdrawal * - Sends all depositor's accumulated gains (YETI, ETH) to depositor * - Sends the tagged front end's accumulated YETI gains to the tagged front end * - Decreases deposit and tagged front end's stake, and takes new snapshots for each. * * If _amount > userDeposit, the user withdraws all of their compounded deposit. */ function withdrawFromSP(uint _amount) external; /* * Initial checks: * - Frontend (sender) not already registered * - User (sender) has no deposit * - _kickbackRate is in the range [0, 100%] * --- * Front end makes a one-time selection of kickback rate upon registering */ function registerFrontEnd(uint _kickbackRate) external; /* * Initial checks: * - Caller is TroveManager * --- * Cancels out the specified debt against the YUSD contained in the Stability Pool (as far as possible) * and transfers the Trove's ETH collateral from ActivePool to StabilityPool. * Only called by liquidation functions in the TroveManager. */ function offset(uint _debt, address[] memory _assets, uint[] memory _amountsAdded) external; // /* // * Returns the total amount of ETH held by the pool, accounted in an internal variable instead of `balance`, // * to exclude edge cases like ETH received from a self-destruct. // */ // function getETH() external view returns (uint); //* // * Calculates and returns the total gains a depositor has accumulated // */ function getDepositorGains(address _depositor) external view returns (address[] memory assets, uint[] memory amounts); /* * Returns the total amount of VC held by the pool, accounted for by multipliying the * internal balances of collaterals by the price that is found at the time getVC() is called. */ function getVC() external view returns (uint); /* * Returns YUSD held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset. */ function getTotalYUSDDeposits() external view returns (uint); /* * Calculate the YETI gain earned by a deposit since its last snapshots were taken. * If not tagged with a front end, the depositor gets a 100% cut of what their deposit earned. * Otherwise, their cut of the deposit's earnings is equal to the kickbackRate, set by the front end through * which they made their deposit. */ function getDepositorYETIGain(address _depositor) external view returns (uint); /* * Return the YETI gain earned by the front end. */ function getFrontEndYETIGain(address _frontEnd) external view returns (uint); /* * Return the user's compounded deposit. */ function getCompoundedYUSDDeposit(address _depositor) external view returns (uint); /* * Return the front end's compounded stake. * * The front end's compounded stake is equal to the sum of its depositors' compounded deposits. */ function getCompoundedFrontEndStake(address _frontEnd) external view returns (uint); /* * Add collateral type to totalColl */ function addCollateralType(address _collateral) external; function getDepositSnapshotS(address depositor, address collateral) external view returns (uint); function getCollateral(address _collateral) external view returns (uint); function getAllCollateral() external view returns (address[] memory, uint256[] memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "../Dependencies/YetiCustomBase.sol"; import "./ICollateralReceiver.sol"; interface ICollSurplusPool is ICollateralReceiver { // --- Events --- event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress); event TroveManagerAddressChanged(address _newTroveManagerAddress); event ActivePoolAddressChanged(address _newActivePoolAddress); event CollBalanceUpdated(address indexed _account); event CollateralSent(address _to); // --- Contract setters --- function setAddresses( address _borrowerOperationsAddress, address _troveManagerAddress, address _troveManagerRedemptionsAddress, address _activePoolAddress, address _whitelistAddress ) external; function getCollVC() external view returns (uint); function getAmountClaimable(address _account, address _collateral) external view returns (uint); function getCollateral(address _collateral) external view returns (uint); function getAllCollateral() external view returns (address[] memory, uint256[] memory); function accountSurplus(address _account, address[] memory _tokens, uint[] memory _amounts) external; function claimColl(address _account) external; function addCollateralType(address _collateral) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "../Interfaces/IERC20.sol"; import "../Interfaces/IERC2612.sol"; interface IYUSDToken is IERC20, IERC2612 { // --- Events --- event TroveManagerAddressChanged(address _troveManagerAddress); event StabilityPoolAddressChanged(address _newStabilityPoolAddress); event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress); event YUSDTokenBalanceUpdated(address _user, uint _amount); // --- Functions --- function mint(address _account, uint256 _amount) external; function burn(address _account, uint256 _amount) external; function sendToPool(address _sender, address poolAddress, uint256 _amount) external; function returnFromPool(address poolAddress, address user, uint256 _amount ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; // Common interface for the SortedTroves Doubly Linked List. interface ISortedTroves { // --- Events --- event SortedTrovesAddressChanged(address _sortedDoublyLLAddress); event BorrowerOperationsAddressChanged(address _borrowerOperationsAddress); event NodeAdded(address _id, uint _NICR); event NodeRemoved(address _id); // --- Functions --- function setParams(uint256 _size, address _TroveManagerAddress, address _borrowerOperationsAddress, address _troveManagerRedemptionsAddress) external; function insert(address _id, uint256 _ICR, address _prevId, address _nextId) external; function remove(address _id) external; function reInsert(address _id, uint256 _newICR, address _prevId, address _nextId) external; function contains(address _id) external view returns (bool); function isFull() external view returns (bool); function isEmpty() external view returns (bool); function getSize() external view returns (uint256); function getMaxSize() external view returns (uint256); function getFirst() external view returns (address); function getLast() external view returns (address); function getNext(address _id) external view returns (address); function getPrev(address _id) external view returns (address); function getOldICR(address _id) external view returns (uint256); function validInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (bool); function findInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (address, address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./IERC20.sol"; import "./IERC2612.sol"; interface IYETIToken is IERC20, IERC2612 { function sendToSYETI(address _sender, uint256 _amount) external; function getDeploymentStartTime() external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; interface ISYETI { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); function increaseAllowance(address spender, uint256 addedValue) external returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function mint(uint256 amount) external returns (bool); function burn(address to, uint256 shares) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./IPool.sol"; interface IActivePool is IPool { // --- Events --- event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress); event TroveManagerAddressChanged(address _newTroveManagerAddress); event ActivePoolYUSDDebtUpdated(uint _YUSDDebt); event ActivePoolCollateralBalanceUpdated(address _collateral, uint _amount); // --- Functions --- function sendCollaterals(address _to, address[] memory _tokens, uint[] memory _amounts) external returns (bool); function sendCollateralsUnwrap( address _to, address[] memory _tokens, uint[] memory _amounts, bool _collectRewards) external returns (bool); function getCollateralVC(address collateralAddress) external view returns (uint); function addCollateralType(address _collateral) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; interface IWhitelist { function getValidCollateral() view external returns (address[] memory); function setAddresses( address _activePoolAddress, address _defaultPoolAddress, address _stabilityPoolAddress, address _collSurplusPoolAddress, address _borrowerOperationsAddress ) external; function isValidRouter(address _router) external view returns (bool); function getOracle(address _collateral) view external returns (address); function getRatio(address _collateral) view external returns (uint256); function getIsActive(address _collateral) view external returns (bool); function getPriceCurve(address _collateral) external view returns (address); function getDecimals(address _collateral) external view returns (uint256); function getFee(address _collateral, uint _collateralVCInput, uint256 _collateralVCBalancePost, uint256 _totalVCBalancePre, uint256 _totalVCBalancePost) external view returns (uint256 fee); function getFeeAndUpdate(address _collateral, uint _collateralVCInput, uint256 _collateralVCBalancePost, uint256 _totalVCBalancePre, uint256 _totalVCBalancePost) external returns (uint256 fee); function getIndex(address _collateral) external view returns (uint256); function isWrapped(address _collateral) external view returns (bool); function setDefaultRouter(address _collateral, address _router) external; function getValueVC(address _collateral, uint _amount) view external returns (uint); function getValueUSD(address _collateral, uint _amount) view external returns (uint256); function getDefaultRouterAddress(address _collateral) external view returns (address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; interface ITroveManagerLiquidations { function batchLiquidateTroves(address[] memory _troveArray, address _liquidator) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; interface ITroveManagerRedemptions { function redeemCollateral( uint _YUSDamount, uint _YUSDMaxFee, address _firstRedemptionHint, address _upperPartialRedemptionHint, address _lowerPartialRedemptionHint, uint _partialRedemptionHintNICR, uint _maxIterations, // uint _maxFeePercentage, address _redeemSender ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./LiquityMath.sol"; import "../Interfaces/IActivePool.sol"; import "../Interfaces/IDefaultPool.sol"; import "../Interfaces/ILiquityBase.sol"; import "../Interfaces/IWhitelist.sol"; import "./YetiCustomBase.sol"; /* * Base contract for TroveManager, BorrowerOperations and StabilityPool. Contains global system constants and * common functions. */ contract LiquityBase is ILiquityBase, YetiCustomBase { uint constant public _100pct = 1000000000000000000; // 1e18 == 100% uint constant public _110pct = 1100000000000000000; // 1.1e18 == 110% // Minimum collateral ratio for individual troves uint constant public MCR = 1100000000000000000; // 110% // Critical system collateral ratio. If the system's total collateral ratio (TCR) falls below the CCR, Recovery Mode is triggered. uint constant public CCR = 1500000000000000000; // 150% // Amount of YUSD to be locked in gas pool on opening troves uint constant public YUSD_GAS_COMPENSATION = 200e18; // Minimum amount of net YUSD debt a must have uint constant public MIN_NET_DEBT = 1800e18; // uint constant public MIN_NET_DEBT = 0; uint constant public PERCENT_DIVISOR = 200; // dividing by 200 yields 0.5% uint constant public BORROWING_FEE_FLOOR = DECIMAL_PRECISION / 1000 * 5; // 0.5% uint constant public REDEMPTION_FEE_FLOOR = DECIMAL_PRECISION / 1000 * 5; // 0.5% IActivePool public activePool; IDefaultPool public defaultPool; // --- Gas compensation functions --- // Returns the composite debt (drawn debt + gas compensation) of a trove, for the purpose of ICR calculation function _getCompositeDebt(uint _debt) internal pure returns (uint) { return _debt.add(YUSD_GAS_COMPENSATION); } function _getNetDebt(uint _debt) internal pure returns (uint) { return _debt.sub(YUSD_GAS_COMPENSATION); } // Return the amount of collateral to be drawn from a trove's collateral and sent as gas compensation. function _getCollGasCompensation(newColls memory _coll) internal pure returns (newColls memory) { require(_coll.tokens.length == _coll.amounts.length, "_getCollGasCompensation(): Collateral length mismatch"); uint[] memory amounts = new uint[](_coll.tokens.length); for (uint i = 0; i < _coll.tokens.length; i++) { amounts[i] = _coll.amounts[i] / PERCENT_DIVISOR; } return newColls(_coll.tokens, amounts); } // Return the system's Total Virtual Coin Balance // Virtual Coins are a way to keep track of the system collateralization given // the collateral ratios of each collateral type function getEntireSystemColl() public view returns (uint entireSystemColl) { uint activeColl = activePool.getVC(); uint liquidatedColl = defaultPool.getVC(); return activeColl.add(liquidatedColl); } function getEntireSystemDebt() public override view returns (uint entireSystemDebt) { uint activeDebt = activePool.getYUSDDebt(); uint closedDebt = defaultPool.getYUSDDebt(); return activeDebt.add(closedDebt); } function _getICRColls(newColls memory _colls, uint _debt) internal view returns (uint ICR) { uint totalVC = _getVCColls(_colls); ICR = LiquityMath._computeCR(totalVC, _debt); return ICR; } function _getVC(address[] memory _tokens, uint[] memory _amounts) internal view returns (uint totalVC) { require(_tokens.length == _amounts.length, "Not same length"); for (uint i = 0; i < _tokens.length; i++) { uint tokenVC = whitelist.getValueVC(_tokens[i], _amounts[i]); totalVC = totalVC.add(tokenVC); } return totalVC; } function _getVCColls(newColls memory _colls) internal view returns (uint VC) { for (uint i = 0; i < _colls.tokens.length; i++) { uint valueVC = whitelist.getValueVC(_colls.tokens[i], _colls.amounts[i]); VC = VC.add(valueVC); } return VC; } function _getUSDColls(newColls memory _colls) internal view returns (uint USDValue) { for (uint i = 0; i < _colls.tokens.length; i++) { uint valueUSD = whitelist.getValueUSD(_colls.tokens[i], _colls.amounts[i]); USDValue = USDValue.add(valueUSD); } return USDValue; } function _getTCR() internal view returns (uint TCR) { uint entireSystemColl = getEntireSystemColl(); uint entireSystemDebt = getEntireSystemDebt(); TCR = LiquityMath._computeCR(entireSystemColl, entireSystemDebt); return TCR; } function _checkRecoveryMode() internal view returns (bool) { uint TCR = _getTCR(); return TCR < CCR; } // fee and amount are denominated in dollar function _requireUserAcceptsFee(uint _fee, uint _amount, uint _maxFeePercentage) internal pure { uint feePercentage = _fee.mul(DECIMAL_PRECISION).div(_amount); require(feePercentage <= _maxFeePercentage, "Fee exceeded provided maximum"); } // get Colls struct for the given tokens and amounts function _getColls(address[] memory tokens, uint[] memory amounts) internal view returns (newColls memory coll) { require(tokens.length == amounts.length); coll.tokens = tokens; for (uint i = 0; i < tokens.length; i++) { coll.amounts[whitelist.getIndex(tokens[i])] = amounts[i]; } return coll; } // checks coll has a nonzero balance of at least one token in coll.tokens function _CollsIsNonZero(newColls memory coll) internal pure returns (bool) { for (uint i = 0; i < coll.tokens.length; i++) { if (coll.amounts[i] > 0) { return true; } } return false; } function _sendColl(address _to, newColls memory _coll) internal returns (bool) { for (uint i = 0; i < _coll.tokens.length; i++) { IERC20 token = IERC20(_coll.tokens[i]); if (!token.transfer(_to, _coll.amounts[i])) { return false; } } return true; } // Check whether or not the system *would be* in Recovery Mode, given the entire system coll and debt. // returns true if the system would be in recovery mode and false if not function _checkPotentialRecoveryMode(uint _entireSystemColl, uint _entireSystemDebt) internal pure returns (bool) { uint TCR = LiquityMath._computeCR(_entireSystemColl, _entireSystemDebt); return TCR < CCR; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; /** * Based on OpenZeppelin's Ownable contract: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol * * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { _owner = msg.sender; emit OwnershipTransferred(address(0), msg.sender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. * * NOTE: This function is not safe, as it doesn’t check owner is calling it. * Make sure you check it before calling it. */ function _renounceOwnership() internal { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; contract CheckContract { /** * Check that the account is an already deployed non-destroyed contract. * See: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L12 */ function checkContract(address _account) internal view { require(_account != address(0), "Account cannot be zero address"); uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(_account) } require(size > 0, "Account code size cannot be zero"); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./IPriceFeed.sol"; interface ILiquityBase { function getEntireSystemDebt() external view returns (uint entireSystemDebt); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./IPool.sol"; interface IDefaultPool is IPool { // --- Events --- event TroveManagerAddressChanged(address _newTroveManagerAddress); event DefaultPoolYUSDDebtUpdated(uint _YUSDDebt); event DefaultPoolETHBalanceUpdated(uint _ETH); // --- Functions --- function sendCollsToActivePool(address[] memory _collaterals, uint[] memory _amounts, address _borrower) external; function addCollateralType(address _collateral) external; function getCollateralVC(address collateralAddress) external view returns (uint); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; interface IPriceFeed { // --- Events --- event LastGoodPriceUpdated(uint _lastGoodPrice); // --- Function --- // function fetchPrice() external returns (uint); function fetchPrice_v() view external returns (uint); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; interface ICollateralReceiver { function receiveCollateral(address[] memory _tokens, uint[] memory _amounts) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; /** * Based on the OpenZeppelin IER20 interface: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol * * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); function increaseAllowance(address spender, uint256 addedValue) external returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; /** * @dev Interface of the ERC2612 standard as defined in the EIP. * * Adds the {permit} method, which can be used to change one's * {IERC20-allowance} without having to send a transaction, by signing a * message. This allows users to spend tokens without having to hold Ether. * * See https://eips.ethereum.org/EIPS/eip-2612. * * Code adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/ */ interface IERC2612 { /** * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens, * given `owner`'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /** * @dev Returns the current ERC2612 nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases `owner`'s nonce by one. This * prevents a signature from being used multiple times. * * `owner` can limit the time a Permit is valid for by setting `deadline` to * a value in the near future. The deadline argument can be set to uint(-1) to * create Permits that effectively never expire. */ function nonces(address owner) external view returns (uint256); function version() external view returns (string memory); function permitTypeHash() external view returns (bytes32); function domainSeparator() external view returns (bytes32); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./ICollateralReceiver.sol"; // Common interface for the Pools. interface IPool is ICollateralReceiver { // --- Events --- event ETHBalanceUpdated(uint _newBalance); event YUSDBalanceUpdated(uint _newBalance); event ActivePoolAddressChanged(address _newActivePoolAddress); event DefaultPoolAddressChanged(address _newDefaultPoolAddress); event StabilityPoolAddressChanged(address _newStabilityPoolAddress); event WhitelistAddressChanged(address _newWhitelistAddress); event EtherSent(address _to, uint _amount); event CollateralSent(address _collateral, address _to, uint _amount); // --- Functions --- function getVC() external view returns (uint); function getCollateral(address collateralAddress) external view returns (uint); function getAllCollateral() external view returns (address[] memory, uint256[] memory); function getYUSDDebt() external view returns (uint); function increaseYUSDDebt(uint _amount) external; function decreaseYUSDDebt(uint _amount) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./BaseMath.sol"; import "./SafeMath.sol"; import "../Interfaces/IERC20.sol"; import "../Interfaces/IWhitelist.sol"; contract YetiCustomBase is BaseMath { using SafeMath for uint256; IWhitelist whitelist; struct newColls { // tokens and amounts should be the same length address[] tokens; uint256[] amounts; } // Collateral math // gets the sum of _coll1 and _coll2 function _sumColls(newColls memory _coll1, newColls memory _coll2) internal view returns (newColls memory finalColls) { newColls memory coll3; coll3.tokens = whitelist.getValidCollateral(); coll3.amounts = new uint256[](coll3.tokens.length); uint256 n = 0; for (uint256 i = 0; i < _coll1.tokens.length; i++) { uint256 tokenIndex = whitelist.getIndex(_coll1.tokens[i]); if (_coll1.amounts[i] > 0) { n++; coll3.amounts[tokenIndex] = _coll1.amounts[i]; } } for (uint256 i = 0; i < _coll2.tokens.length; i++) { uint256 tokenIndex = whitelist.getIndex(_coll2.tokens[i]); if (_coll2.amounts[i] > 0) { if (coll3.amounts[tokenIndex] == 0) { n++; } coll3.amounts[tokenIndex] = coll3.amounts[tokenIndex].add(_coll2.amounts[i]); } } address[] memory sumTokens = new address[](n); uint256[] memory sumAmounts = new uint256[](n); uint256 j = 0; // should only find n amounts over 0 for (uint256 i = 0; i < coll3.tokens.length; i++) { if (coll3.amounts[i] > 0) { sumTokens[j] = coll3.tokens[i]; sumAmounts[j] = coll3.amounts[i]; j++; } } finalColls.tokens = sumTokens; finalColls.amounts = sumAmounts; } // gets the sum of coll1 with tokens and amounts function _sumColls( newColls memory _coll1, address[] memory tokens, uint256[] memory amounts ) internal view returns (newColls memory) { newColls memory coll2 = newColls(tokens, amounts); return _sumColls(_coll1, coll2); } function _sumColls( address[] memory tokens1, uint256[] memory amounts1, address[] memory tokens2, uint256[] memory amounts2 ) internal view returns (newColls memory) { newColls memory coll1 = newColls(tokens1, amounts1); return _sumColls(coll1, tokens2, amounts2); } // Function for summing colls when coll1 includes all the tokens in the whitelist // Used in active, default, stability, and surplus pools // assumes _coll1.tokens = all whitelisted tokens function _leftSumColls( newColls memory _coll1, address[] memory _tokens, uint256[] memory _amounts ) internal view returns (uint[] memory) { uint[] memory sumAmounts = _getArrayCopy(_coll1.amounts); // assumes that sumAmounts length = whitelist tokens length. for (uint256 i = 0; i < _tokens.length; i++) { uint tokenIndex = whitelist.getIndex(_tokens[i]); sumAmounts[tokenIndex] = sumAmounts[tokenIndex].add(_amounts[i]); } return sumAmounts; } // Function for summing colls when one list is all tokens. Used in active, default, stability, and surplus pools function _leftSubColls(newColls memory _coll1, address[] memory _subTokens, uint[] memory _subAmounts) internal view returns (uint[] memory) { uint[] memory diffAmounts = _getArrayCopy(_coll1.amounts); //assumes that coll1.tokens = whitelist tokens. Keeps all of coll1's tokens, and subtracts coll2's amounts for (uint256 i = 0; i < _subTokens.length; i++) { uint256 tokenIndex = whitelist.getIndex(_subTokens[i]); diffAmounts[tokenIndex] = diffAmounts[tokenIndex].sub(_subAmounts[i]); } return diffAmounts; } // Returns _coll1 minus _tokens and _amounts // will error if _tokens include a token not in _coll1.tokens function _subColls(newColls memory _coll1, address[] memory _tokens, uint[] memory _amounts) internal view returns (newColls memory finalColls) { require(_tokens.length == _amounts.length, "Sub Colls invalid input"); newColls memory coll3; coll3.tokens = whitelist.getValidCollateral(); coll3.amounts = new uint256[](coll3.tokens.length); uint256 n = 0; for (uint256 i = 0; i < _coll1.tokens.length; i++) { if (_coll1.amounts[i] > 0) { uint256 tokenIndex = whitelist.getIndex(_coll1.tokens[i]); coll3.amounts[tokenIndex] = _coll1.amounts[i]; n++; } } for (uint256 i = 0; i < _tokens.length; i++) { uint256 tokenIndex = whitelist.getIndex(_tokens[i]); require(coll3.amounts[tokenIndex] >= _amounts[i], "illegal sub"); coll3.amounts[tokenIndex] = coll3.amounts[tokenIndex].sub(_amounts[i]); if (coll3.amounts[tokenIndex] == 0) { n--; } } address[] memory diffTokens = new address[](n); uint256[] memory diffAmounts = new uint256[](n); uint256 j = 0; for (uint256 i = 0; i < coll3.tokens.length; i++) { if (coll3.amounts[i] > 0) { diffTokens[j] = coll3.tokens[i]; diffAmounts[j] = coll3.amounts[i]; j++; } } finalColls.tokens = diffTokens; finalColls.amounts = diffAmounts; } function _getArrayCopy(uint[] memory _arr) internal pure returns (uint[] memory){ uint[] memory copy = new uint[](_arr.length); for (uint i = 0; i < _arr.length; i++) { copy[i] = _arr[i]; } return copy; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; contract BaseMath { uint constant public DECIMAL_PRECISION = 1e18; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; /** * Based on OpenZeppelin's SafeMath: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol * * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.6.11; import "./SafeMath.sol"; library LiquityMath { using SafeMath for uint; uint internal constant DECIMAL_PRECISION = 1e18; function _min(uint _a, uint _b) internal pure returns (uint) { return (_a < _b) ? _a : _b; } function _max(uint _a, uint _b) internal pure returns (uint) { return (_a >= _b) ? _a : _b; } /* * Multiply two decimal numbers and use normal rounding rules: * -round product up if 19'th mantissa digit >= 5 * -round product down if 19'th mantissa digit < 5 * * Used only inside the exponentiation, _decPow(). */ function decMul(uint x, uint y) internal pure returns (uint decProd) { uint prod_xy = x.mul(y); decProd = prod_xy.add(DECIMAL_PRECISION / 2).div(DECIMAL_PRECISION); } /* * _decPow: Exponentiation function for 18-digit decimal base, and integer exponent n. * * Uses the efficient "exponentiation by squaring" algorithm. O(log(n)) complexity. * * Called by two functions that represent time in units of minutes: * 1) TroveManager._calcDecayedBaseRate * 2) CommunityIssuance._getCumulativeIssuanceFraction * * The exponent is capped to avoid reverting due to overflow. The cap 525600000 equals * "minutes in 1000 years": 60 * 24 * 365 * 1000 * * If a period of > 1000 years is ever used as an exponent in either of the above functions, the result will be * negligibly different from just passing the cap, since: * * In function 1), the decayed base rate will be 0 for 1000 years or > 1000 years * In function 2), the difference in tokens issued at 1000 years and any time > 1000 years, will be negligible */ function _decPow(uint _base, uint _minutes) internal pure returns (uint) { if (_minutes > 525600000) {_minutes = 525600000;} // cap to avoid overflow if (_minutes == 0) {return DECIMAL_PRECISION;} uint y = DECIMAL_PRECISION; uint x = _base; uint n = _minutes; // Exponentiation-by-squaring while (n > 1) { if (n % 2 == 0) { x = decMul(x, x); n = n.div(2); } else { // if (n % 2 != 0) y = decMul(x, y); x = decMul(x, x); n = (n.sub(1)).div(2); } } return decMul(x, y); } function _getAbsoluteDifference(uint _a, uint _b) internal pure returns (uint) { return (_a >= _b) ? _a.sub(_b) : _b.sub(_a); } // _coll should be the amount of VC and _debt is debt of YUSD\ // new collateral ratio is 10**18 times the collateral ratio. (150% => 1.5e18) function _computeCR(uint _coll, uint _debt) internal pure returns (uint) { if (_debt > 0) { uint newCollRatio = _coll.mul(10**18).div(_debt); return newCollRatio; } // Return the maximal value for uint256 if the Trove has a debt of 0. Represents "infinite" CR. else { // if (_debt == 0) return 2**256 - 1; } } }
{ "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_activePoolAddress","type":"address"}],"name":"ActivePoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newBorrowerOperationsAddress","type":"address"}],"name":"BorrowerOperationsAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_collSurplusPoolAddress","type":"address"}],"name":"CollSurplusPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_defaultPoolAddress","type":"address"}],"name":"DefaultPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_gasPoolAddress","type":"address"}],"name":"GasPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"liquidatedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalYUSDGasCompensation","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"totalCollTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"totalCollAmounts","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"totalCollGasCompTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"totalCollGasCompAmounts","type":"uint256[]"}],"name":"Liquidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_sYETIAddress","type":"address"}],"name":"SYETIAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_sortedTrovesAddress","type":"address"}],"name":"SortedTrovesAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_stabilityPoolAddress","type":"address"}],"name":"StabilityPoolAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_debt","type":"uint256"},{"indexed":false,"internalType":"enum TroveManagerBase.TroveManagerOperation","name":"_operation","type":"uint8"}],"name":"TroveLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_debt","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"indexed":false,"internalType":"enum TroveManagerBase.TroveManagerOperation","name":"operation","type":"uint8"}],"name":"TroveUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_yetiTokenAddress","type":"address"}],"name":"YETITokenAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newYUSDTokenAddress","type":"address"}],"name":"YUSDTokenAddressChanged","type":"event"},{"inputs":[],"name":"BORROWING_FEE_FLOOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_NET_DEBT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REDEMPTION_FEE_FLOOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"YUSD_GAS_COMPENSATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_100pct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_110pct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activePool","outputs":[{"internalType":"contract IActivePool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_troveArray","type":"address[]"},{"internalType":"address","name":"_liquidator","type":"address"}],"name":"batchLiquidateTroves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrowerOperationsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultPool","outputs":[{"internalType":"contract IDefaultPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntireSystemColl","outputs":[{"internalType":"uint256","name":"entireSystemColl","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntireSystemDebt","outputs":[{"internalType":"uint256","name":"entireSystemDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrowerOperationsAddress","type":"address"},{"internalType":"address","name":"_activePoolAddress","type":"address"},{"internalType":"address","name":"_defaultPoolAddress","type":"address"},{"internalType":"address","name":"_stabilityPoolAddress","type":"address"},{"internalType":"address","name":"_gasPoolAddress","type":"address"},{"internalType":"address","name":"_collSurplusPoolAddress","type":"address"},{"internalType":"address","name":"_yusdTokenAddress","type":"address"},{"internalType":"address","name":"_sortedTrovesAddress","type":"address"},{"internalType":"address","name":"_yetiTokenAddress","type":"address"},{"internalType":"address","name":"_sYETIAddress","type":"address"},{"internalType":"address","name":"_whitelistAddress","type":"address"},{"internalType":"address","name":"_troveManagerAddress","type":"address"},{"internalType":"address","name":"_yetiFinanceTreasury","type":"address"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sortedTroves","outputs":[{"internalType":"contract ISortedTroves","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"troveManager","outputs":[{"internalType":"contract ITroveManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"troveManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"troveManagerLiquidationsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"troveManagerRedemptionsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50600380546001600160a01b031916339081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a361479f806100606000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c8063795d26c3116100c3578063ae9187541161007c578063ae9187541461021f578063b7f8cf9b14610227578063db5e73211461022f578063e369e4ab146102bf578063f5f468ed1461036b578063f92d34331461019b57610158565b8063795d26c3146101e35780637f7dde4a146101eb578063887105d3146101f35780638da5cb5b146101fb5780638f32d59b14610203578063a20baee6146101db57610158565b80634870dd9a116101155780634870dd9a146101bb578063499f99d9146101c35780635733d58f146101cb5780635a4d28bb146101d357806372fe25aa146101db578063794e5724146101a357610158565b806316a81f311461015d5780631bf435551461018157806328d28b5b1461019b578063308e9647146101a35780633cc74225146101ab5780633d83908a146101b3575b600080fd5b610165610373565b604080516001600160a01b039092168252519081900360200190f35b610189610382565b60408051918252519081900360200190f35b61018961038f565b61018961039a565b6101656103a6565b6101656103b5565b6101896103c4565b6101896103c9565b6101896103d6565b6101656103e2565b6101896103f1565b6101896103fd565b61016561050a565b610189610519565b6101656105e1565b61020b6105f0565b604080519115158252519081900360200190f35b610165610601565b610165610610565b6102bd60048036036101a081101561024657600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e0810135821691610100820135811691610120810135821691610140820135811691610160810135821691610180909101351661061f565b005b6102bd600480360360408110156102d557600080fd5b810190602081018135600160201b8111156102ef57600080fd5b82018360208201111561030157600080fd5b803590602001918460208302840111600160201b8311171561032257600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b03169150610b8a9050565b6101656112f6565b600f546001600160a01b031681565b686194049f30f720000081565b6611c37937e0800081565b670f43fc2c04ee000081565b6002546001600160a01b031681565b6006546001600160a01b031681565b60c881565b680ad78ebc5ac620000081565b6714d1120d7b16000081565b600d546001600160a01b031681565b670de0b6b3a764000081565b600080600160009054906101000a90046001600160a01b03166001600160a01b0316638df709926040518163ffffffff1660e01b815260040160206040518083038186803b15801561044e57600080fd5b505afa158015610462573d6000803e3d6000fd5b505050506040513d602081101561047857600080fd5b5051600254604080516346fb84c960e11b815290519293506000926001600160a01b0390921691638df7099291600480820192602092909190829003018186803b1580156104c557600080fd5b505afa1580156104d9573d6000803e3d6000fd5b505050506040513d60208110156104ef57600080fd5b50519050610503828263ffffffff61130516565b9250505090565b6001546001600160a01b031681565b600080600160009054906101000a90046001600160a01b03166001600160a01b03166301d40b636040518163ffffffff1660e01b815260040160206040518083038186803b15801561056a57600080fd5b505afa15801561057e573d6000803e3d6000fd5b505050506040513d602081101561059457600080fd5b5051600254604080516301d40b6360e01b815290519293506000926001600160a01b03909216916301d40b6391600480820192602092909190829003018186803b1580156104c557600080fd5b6003546001600160a01b031690565b6003546001600160a01b0316331490565b6010546001600160a01b031681565b6004546001600160a01b031681565b6106276105f0565b610678576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6106818d611368565b61068a8c611368565b6106938b611368565b61069c8a611368565b6106a589611368565b6106ae88611368565b6106b787611368565b6106c086611368565b6106c985611368565b6106d284611368565b6106db83611368565b6106e482611368565b6106ed81611368565b8c600460006101000a8154816001600160a01b0302191690836001600160a01b031602179055508b600160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a600260006101000a8154816001600160a01b0302191690836001600160a01b0316021790555089600560006101000a8154816001600160a01b0302191690836001600160a01b03160217905550826000806101000a8154816001600160a01b0302191690836001600160a01b0316021790555088600c60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087601160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555086600760006101000a8154816001600160a01b0302191690836001600160a01b0316021790555085601060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555084600860006101000a8154816001600160a01b0302191690836001600160a01b0316021790555083600960006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600660006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600d60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080601260006101000a8154816001600160a01b0302191690836001600160a01b031602179055507f3ca631ffcd2a9b5d9ae18543fc82f58eb4ca33af9e6ab01b7a8e95331e6ed9858d60405180826001600160a01b03166001600160a01b0316815260200191505060405180910390a1604080516001600160a01b038e16815290517f78f058b189175430c48dc02699e3a0031ea4ff781536dc2fab847de4babdd8829181900360200190a1604080516001600160a01b038d16815290517f5ee0cae2f063ed938bb55046f6a932fb6ae792bf43624806bb90abe68a50be9b9181900360200190a1604080516001600160a01b038c16815290517f82966d27eea39b038ee0fa30cd16532bb24f6e65d31cb58fb227aa5766cdcc7f9181900360200190a1604080516001600160a01b038b16815290517fcfb07d791fcafc032b35837b50eb84b74df518cf4cc287e8084f47630fa70fa09181900360200190a1604080516001600160a01b038a16815290517fe67f36a6e961157d6eff83b91f3af5a62131ceb6f04954ef74f51c1c05e7f88d9181900360200190a1604080516001600160a01b038916815290517fc3cd2681391697b6aa2901e9d80dd9dd3218bb54e24e0817c566fa568adeba369181900360200190a1604080516001600160a01b038816815290517f65f4cf077bc01e4742eb5ad98326f6e95b63548ea24b17f8d5e823111fe788009181900360200190a1604080516001600160a01b038716815290517f449ef232e1f38887f74a15dce9059e717b689423d5270f46e1d478e4bbd1c91e9181900360200190a1604080516001600160a01b038616815290517f2ea605b72d3979601397bc2b968c2390809927edefe7ec75779d5325fb0ba0799181900360200190a1610b7b61141b565b50505050505050505050505050565b610b92611465565b8151610bcf5760405162461bcd60e51b81526004018080602001828103825260368152602001806146dd6036913960400191505060405180910390fd5b6001546002546005546001600160a01b03928316929182169116610bf161452a565b610bf961454d565b826001600160a01b031663a6db9b236040518163ffffffff1660e01b815260040160206040518083038186803b158015610c3257600080fd5b505afa158015610c46573d6000803e3d6000fd5b505050506040513d6020811015610c5c57600080fd5b50518252610c6861147e565b1580156020840152610c8b57610c84858584600001518a611499565b9050610c9e565b610c9b858584600001518a6117e4565b90505b6000816020015111610ce15760405162461bcd60e51b81526004018080602001828103825260228152602001806147486022913960400191505060405180910390fd5b608081015160a0820151805160209182015160405163768cc57560e01b8152600481018581526060602483019081528451606484015284516001600160a01b038b169763768cc57597909695946044810192608490910191808801910280838360005b83811015610d5c578181015183820152602001610d44565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610d9b578181015183820152602001610d83565b5050505090500195505050505050600060405180830381600087803b158015610dc357600080fd5b505af1158015610dd7573d6000803e3d6000fd5b505060065460c084015160e085015180516020918201516040516338d3db5160e21b81526001600160a01b038d8116600483019081528d821660248401526044830187905260a060648401908152855160a4850152855192909816995063e34f6d4498508e978e979691939092608482019260c490920191808801910280838360005b83811015610e72578181015183820152602001610e5a565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610eb1578181015183820152602001610e99565b50505050905001975050505050505050600060405180830381600087803b158015610edb57600080fd5b505af1158015610eef573d6000803e3d6000fd5b50505050610f0181610100015161190e565b1561101c57601154610100820151805160209182015160405163d0d8c20d60e01b81526001600160a01b0394851660048201818152606060248401908152855160648501528551978d169763d0d8c20d9793969594929391926044810192608490910191818801910280838360005b83811015610f88578181015183820152602001610f70565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610fc7578181015183820152602001610faf565b5050505090500195505050505050602060405180830381600087803b158015610fef57600080fd5b505af1158015611003573d6000803e3d6000fd5b505050506040513d602081101561101957600080fd5b50505b60065460408083015180516020918201519251630e1f182560e41b81526001600160a01b038a811660048301908152606060248401908152845160648501528451929097169663e1f18250968d969094929391926044810192608490910191808801910280838360005b8381101561109e578181015183820152602001611086565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156110dd5781810151838201526020016110c5565b5050505090500195505050505050600060405180830381600087803b15801561110557600080fd5b505af1158015611119573d6000803e3d6000fd5b505050602082015160408401525061112f6145b0565b6111418260a001518360e00151611959565b905061115281836101000151611959565b90507ff9c8e708c82ad9ab70e0c58ca02ae4dceef6c9546eacbeb0b7ac025be81c460a83604001518360600151836000015184602001518660400151600001518760400151602001516040518087815260200186815260200180602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156111f35781810151838201526020016111db565b50505050905001858103845288818151815260200191508051906020019060200280838360005b8381101561123257818101518382015260200161121a565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015611271578181015183820152602001611259565b50505050905001858103825286818151815260200191508051906020019060200280838360005b838110156112b0578181015183820152602001611298565b505050509050019a505050505050505050505060405180910390a16112ec86888460600151856040015160000151866040015160200151611e74565b5050505050505050565b600e546001600160a01b031681565b60008282018381101561135f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6001600160a01b0381166113c3576040805162461bcd60e51b815260206004820152601e60248201527f4163636f756e742063616e6e6f74206265207a65726f20616464726573730000604482015290519081900360640190fd5b803b80611417576040805162461bcd60e51b815260206004820181905260248201527f4163636f756e7420636f64652073697a652063616e6e6f74206265207a65726f604482015290519081900360640190fd5b5050565b6003546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600380546001600160a01b0319169055565b600d546001600160a01b0316331461147c57600080fd5b565b600080611489612017565b6714d1120d7b1600001191505090565b6114a161454d565b6114a96145ca565b6114b1614612565b848252600060808301526114c36103fd565b60a08301526114d0610519565b60c0830152600060208301525b8351826020015110156117da57838260200151815181106114fa57fe5b6020908102919091018101516001600160a01b0390811660608501819052600654604080516321e3780160e01b815260048101939093525160009491909316926321e37801926024808201939291829003018186803b15801561155c57600080fd5b505afa158015611570573d6000803e3d6000fd5b505050506040513d602081101561158657600080fd5b5051600481111561159357fe5b905060018160048111156115a357fe5b146115ae57506117ca565b6006546060840151604080516327fb7d8960e01b81526001600160a01b039283166004820152905191909216916327fb7d89916024808301926020929190829003018186803b15801561160057600080fd5b505afa158015611614573d6000803e3d6000fd5b505050506040513d602081101561162a57600080fd5b50516040840152608083015161176057670f43fc2c04ee000083604001511015801561165557508251155b1561166057506117ca565b60006116748460c001518560a00151612036565b905061169089898660600151876040015188600001518661207a565b608081015185519194506116aa919063ffffffff612fab16565b8452608083015160a08501516116c59163ffffffff612fab16565b8460a001818152505060006116dd8460a00151612fed565b905060006116ee8560400151612fed565b90506000611700866101000151612fed565b905061172d8161172184611721878c60c00151612fab90919063ffffffff16565b9063ffffffff612fab16565b60c088015261173c88876130dc565b97506117508760c001518860a001516131c5565b156080880152506117c892505050565b8260800151801561177c5750670f43fc2c04ee00008360400151105b156117c2576117958888856060015186600001516131e4565b608081015184519193506117af919063ffffffff612fab16565b83526117bb84836130dc565b93506117c8565b506117ca565b505b60208201805160010190526114dd565b5050949350505050565b6117ec61454d565b6117f46145ca565b6117fc614612565b848252600060208301525b8351826020015110156117da578382602001518151811061182457fe5b6020908102919091018101516001600160a01b0390811660608501819052600654604080516327fb7d8960e01b81526004810193909352519216926327fb7d8992602480840193829003018186803b15801561187f57600080fd5b505afa158015611893573d6000803e3d6000fd5b505050506040513d60208110156118a957600080fd5b505160408301819052670f43fc2c04ee000011156118fe576118d58787846060015185600001516131e4565b608081015183519192506118ef919063ffffffff612fab16565b82526118fb83826130dc565b92505b6020820180516001019052611807565b6000805b82515181101561194e5760008360200151828151811061192e57fe5b60200260200101511115611946576001915050611954565b600101611912565b50600090505b919050565b6119616145b0565b6119696145b0565b6000805460408051634eb5750560e11b815290516001600160a01b0390921692639d6aea0a92600480840193829003018186803b1580156119a957600080fd5b505afa1580156119bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156119e657600080fd5b8101908080516040519392919084600160201b821115611a0557600080fd5b908301906020820185811115611a1a57600080fd5b82518660208202830111600160201b82111715611a3657600080fd5b82525081516020918201928201910280838360005b83811015611a63578181015183820152602001611a4b565b505050509190910160405250505081835250516001600160401b0381118015611a8b57600080fd5b50604051908082528060200260200182016040528015611ab5578160200160208202803683370190505b5060208201526000805b855151811015611bd25760008054875180516001600160a01b039092169163b31610db919085908110611aee57fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611b3c57600080fd5b505afa158015611b50573d6000803e3d6000fd5b505050506040513d6020811015611b6657600080fd5b50516020880151805191925060009184908110611b7f57fe5b60200260200101511115611bc9576020870151805160019094019383908110611ba457fe5b602002602001015184602001518281518110611bbc57fe5b6020026020010181815250505b50600101611abf565b5060005b845151811015611d325760008054865180516001600160a01b039092169163b31610db919085908110611c0557fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611c5357600080fd5b505afa158015611c67573d6000803e3d6000fd5b505050506040513d6020811015611c7d57600080fd5b50516020870151805191925060009184908110611c9657fe5b60200260200101511115611d295783602001518181518110611cb457fe5b602002602001015160001415611ccb576001909201915b611d0c86602001518381518110611cde57fe5b602002602001015185602001518381518110611cf657fe5b602002602001015161130590919063ffffffff16565b84602001518281518110611d1c57fe5b6020026020010181815250505b50600101611bd6565b506060816001600160401b0381118015611d4b57600080fd5b50604051908082528060200260200182016040528015611d75578160200160208202803683370190505b5090506060826001600160401b0381118015611d9057600080fd5b50604051908082528060200260200182016040528015611dba578160200160208202803683370190505b5090506000805b855151811015611e6157600086602001518281518110611ddd57fe5b60200260200101511115611e59578551805182908110611df957fe5b6020026020010151848381518110611e0d57fe5b6001600160a01b03909216602092830291909101820152860151805182908110611e3357fe5b6020026020010151838381518110611e4757fe5b60209081029190910101526001909101905b600101611dc1565b5050908452602084015250909392505050565b8215611ef357600754600c5460408051631062c15f60e11b81526001600160a01b039283166004820152878316602482015260448101879052905191909216916320c582be91606480830192600092919082900301818387803b158015611eda57600080fd5b505af1158015611eee573d6000803e3d6000fd5b505050505b846001600160a01b031663ab471ec585848460006040518563ffffffff1660e01b815260040180856001600160a01b03166001600160a01b03168152602001806020018060200184151515158152602001838103835286818151815260200191508051906020019060200280838360005b83811015611f7c578181015183820152602001611f64565b50505050905001838103825285818151815260200191508051906020019060200280838360005b83811015611fbb578181015183820152602001611fa3565b505050509050019650505050505050602060405180830381600087803b158015611fe457600080fd5b505af1158015611ff8573d6000803e3d6000fd5b505050506040513d602081101561200e57600080fd5b50505050505050565b600080612022610519565b9050600061202e6103fd565b905061050382825b600081156120715760006120688361205c86670de0b6b3a764000063ffffffff613a1d16565b9063ffffffff613a7616565b91506113629050565b50600019611362565b612082614612565b61208a61463a565b600654604080516324f77f7760e11b815290516001926001600160a01b0316916349eefeee916004808301926020929190829003018186803b1580156120cf57600080fd5b505afa1580156120e3573d6000803e3d6000fd5b505050506040513d60208110156120f957600080fd5b5051116121065750612fa1565b60065460408051630956f86160e11b81526001600160a01b038981166004830152915191909216916312adf0c2916024808301926000929190829003018186803b15801561215357600080fd5b505afa158015612167573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260c081101561219057600080fd5b815160208301805160405192949293830192919084600160201b8211156121b657600080fd5b9083019060208201858111156121cb57600080fd5b82518660208202830111600160201b821117156121e757600080fd5b82525081516020918201928201910280838360005b838110156122145781810151838201526020016121fc565b5050505090500160405260200180516040519392919084600160201b82111561223c57600080fd5b90830190602082018581111561225157600080fd5b82518660208202830111600160201b8211171561226d57600080fd5b82525081516020918201928201910280838360005b8381101561229a578181015183820152602001612282565b505050509050016040526020018051906020019092919080516040519392919084600160201b8211156122cc57600080fd5b9083019060208201858111156122e157600080fd5b82518660208202830111600160201b821117156122fd57600080fd5b82525081516020918201928201910280838360005b8381101561232a578181015183820152602001612312565b5050505090500160405260200180516040519392919084600160201b82111561235257600080fd5b90830190602082018581111561236757600080fd5b82518660208202830111600160201b8211171561238357600080fd5b82525081516020918201928201910280838360005b838110156123b0578181015183820152602001612398565b505050509190910160409081526020808e018051928e015180830198909852979096528b8601979097525050505082019290925291909152908352516123f590613ab8565b6040830181905261240890876000613bb3565b680ad78ebc5ac62000006060830152602082015151815152805151516001600160401b038111801561243957600080fd5b50604051908082528060200260200182016040528015612463578160200160208202803683370190505b5081516020015260005b815151518110156124e6576124c1836040015160200151828151811061248f57fe5b602002602001015184602001516020015183815181106124ab57fe5b6020026020010151612fab90919063ffffffff16565b8251602001518051839081106124d357fe5b602090810291909101015260010161246d565b50670de0b6b3a7640000851161288057600660009054906101000a90046001600160a01b03166001600160a01b0316637837eeeb898984602001518560400151600001518660400151602001518c6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b031681526020018581526020018060200180602001846001600160a01b03166001600160a01b03168152602001838103835286818151815260200191508051906020019060200280838360005b838110156125d55781810151838201526020016125bd565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156126145781810151838201526020016125fc565b5050505090500198505050505050505050600060405180830381600087803b15801561263f57600080fd5b505af1158015612653573d6000803e3d6000fd5b505060065460408051630bce3bf960e41b81526001600160a01b038b81166004830152915191909216935063bce3bf909250602480830192600092919082900301818387803b1580156126a557600080fd5b505af11580156126b9573d6000803e3d6000fd5b505060006080850152506126cd90506145b0565b60a08301819052825160c0840152815160e084018190526012546126fc919089906001600160a01b0316613bb3565b600654604080516322962f6560e01b81526001600160a01b038a81166004830152915191909216916322962f6591602480830192600092919082900301818387803b15801561274a57600080fd5b505af115801561275e573d6000803e3d6000fd5b50508451604080519182526002602083015280516001600160a01b038c16945060008051602061469d8339815191529350918290030190a261279e6145b0565b876001600160a01b03166000805160206146bd83398151915260008360000151846020015160026040518085815260200180602001806020018460038111156127e357fe5b60ff168152602001838103835286818151815260200191508051906020019060200280838360005b8381101561282357818101518382015260200161280b565b50505050905001838103825285818151815260200191508051906020019060200280838360005b8381101561286257818101518382015260200161284a565b50505050905001965050505050505060405180910390a25050612e89565b670f43fc2c04ee0000851015612c3757600660009054906101000a90046001600160a01b03166001600160a01b0316637837eeeb898984602001518560400151600001518660400151602001518c6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b031681526020018581526020018060200180602001846001600160a01b03166001600160a01b03168152602001838103835286818151815260200191508051906020019060200280838360005b8381101561296f578181015183820152602001612957565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156129ae578181015183820152602001612996565b5050505090500198505050505050505050600060405180830381600087803b1580156129d957600080fd5b505af11580156129ed573d6000803e3d6000fd5b505060065460408051630bce3bf960e41b81526001600160a01b038b81166004830152915191909216935063bce3bf909250602480830192600092919082900301818387803b158015612a3f57600080fd5b505af1158015612a53573d6000803e3d6000fd5b50505050612a5f614661565b82518251612a6e919087613cf7565b9050612a786145b0565b612a8a82602001518360600151611959565b601254909150612aa69082908a906001600160a01b0316613bb3565b612ab08285614053565b600654604080516322962f6560e01b81526001600160a01b038c8116600483015291519397509116916322962f659160248082019260009290919082900301818387803b158015612b0057600080fd5b505af1158015612b14573d6000803e3d6000fd5b50508551604080519182526002602083015280516001600160a01b038d16945060008051602061469d8339815191529350918290030190a2612b546145b0565b886001600160a01b03166000805160206146bd8339815191526000836000015184602001516002604051808581526020018060200180602001846003811115612b9957fe5b60ff168152602001838103835286818151815260200191508051906020019060200280838360005b83811015612bd9578181015183820152602001612bc1565b50505050905001838103825285818151815260200191508051906020019060200280838360005b83811015612c18578181015183820152602001612c00565b50505050905001965050505050505060405180910390a2505050612e89565b8285108015612c47575081518410155b15612e7857600660009054906101000a90046001600160a01b03166001600160a01b0316637837eeeb898984602001518560400151600001518660400151602001518c6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b031681526020018581526020018060200180602001846001600160a01b03166001600160a01b03168152602001838103835286818151815260200191508051906020019060200280838360005b83811015612d2b578181015183820152602001612d13565b50505050905001838103825285818151815260200191508051906020019060200280838360005b83811015612d6a578181015183820152602001612d52565b5050505090500198505050505050505050600060405180830381600087803b158015612d9557600080fd5b505af1158015612da9573d6000803e3d6000fd5b505050508360001415612db857fe5b60065460408051630bce3bf960e41b81526001600160a01b0389811660048301529151919092169163bce3bf9091602480830192600092919082900301818387803b158015612e0657600080fd5b505af1158015612e1a573d6000803e3d6000fd5b505083516020808601518051910151612e40945091925090670f43fc2c04ee0000614092565b9150612e4a6145b0565b612e5c8360a001518460e00151611959565b6012549091506126fc90829089906001600160a01b0316613bb3565b612e80614612565b9150612fa19050565b612e9782610100015161190e565b15612f9f5760065461010083015180516020918201516040516396755e5560e01b81526001600160a01b038b81166004830190815260606024840190815285516064850152855192909716966396755e55968e969594929391926044810192608490910191808801910280838360005b83811015612f1f578181015183820152602001612f07565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015612f5e578181015183820152602001612f46565b5050505090500195505050505050600060405180830381600087803b158015612f8657600080fd5b505af1158015612f9a573d6000803e3d6000fd5b505050505b505b9695505050505050565b600061135f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061432f565b6000805b8251518110156130d65760008054845180516001600160a01b0390921691632e2b1a8891908590811061302057fe5b60200260200101518660200151858151811061303857fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b15801561308d57600080fd5b505afa1580156130a1573d6000803e3d6000fd5b505050506040513d60208110156130b757600080fd5b505190506130cb838263ffffffff61130516565b925050600101612ff1565b50919050565b6130e461454d565b6130f683604001518360400151611959565b6040820152606080830151908401516131149163ffffffff61130516565b60608201528151602084015161312f9163ffffffff61130516565b60208201526080808301519084015161314d9163ffffffff61130516565b608082015260a080840151908301516131669190611959565b60a082015260c080830151908401516131849163ffffffff61130516565b60c082015260e0808401519083015161319d9190611959565b8160e001819052506131b9836101000151836101000151611959565b61010082015292915050565b6000806131d28484612036565b6714d1120d7b16000011949350505050565b6131ec614612565b6131f461463a565b60065460408051630956f86160e11b81526001600160a01b038781166004830152915191909216916312adf0c2916024808301926000929190829003018186803b15801561324157600080fd5b505afa158015613255573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260c081101561327e57600080fd5b815160208301805160405192949293830192919084600160201b8211156132a457600080fd5b9083019060208201858111156132b957600080fd5b82518660208202830111600160201b821117156132d557600080fd5b82525081516020918201928201910280838360005b838110156133025781810151838201526020016132ea565b5050505090500160405260200180516040519392919084600160201b82111561332a57600080fd5b90830190602082018581111561333f57600080fd5b82518660208202830111600160201b8211171561335b57600080fd5b82525081516020918201928201910280838360005b83811015613388578181015183820152602001613370565b505050509050016040526020018051906020019092919080516040519392919084600160201b8211156133ba57600080fd5b9083019060208201858111156133cf57600080fd5b82518660208202830111600160201b821117156133eb57600080fd5b82525081516020918201928201910280838360005b83811015613418578181015183820152602001613400565b5050505090500160405260200180516040519392919084600160201b82111561344057600080fd5b90830190602082018581111561345557600080fd5b82518660208202830111600160201b8211171561347157600080fd5b82525081516020918201928201910280838360005b8381101561349e578181015183820152602001613486565b505050509190910160409081526020808e01518d8301805180840199909952989097528c81019889528681019990995298909452505050948752600654915190518051908401519451637837eeeb60e01b81526001600160a01b038d8116600483019081528d82166024840152604483018590528c821660a484015260c060648401908152845160c48501528451929096169850637837eeeb978f978f9791948f94608482019260e490920191888101910280838360005b8381101561356e578181015183820152602001613556565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156135ad578181015183820152602001613595565b5050505090500198505050505050505050600060405180830381600087803b1580156135d857600080fd5b505af11580156135ec573d6000803e3d6000fd5b505060065460408051630bce3bf960e41b81526001600160a01b038981166004830152915191909216935063bce3bf909250602480830192600092919082900301818387803b15801561363e57600080fd5b505af1158015613652573d6000803e3d6000fd5b505050506136638260200151613ab8565b6040830181905261367690856000613bb3565b680ad78ebc5ac62000006060830152602082015151815152805151516001600160401b03811180156136a757600080fd5b506040519080825280602002602001820160405280156136d1578160200160208202803683370190505b5081516020015260005b81515151811015613722576136fd836040015160200151828151811061248f57fe5b82516020015180518390811061370f57fe5b60209081029190910101526001016136db565b5061372b614661565b8251825161373a919086613cf7565b90506137446145b0565b61375682602001518360600151611959565b60125490915061377290829088906001600160a01b0316613bb3565b61377c8285614053565b600654604080516322962f6560e01b81526001600160a01b038a8116600483015291519397509116916322962f659160248082019260009290919082900301818387803b1580156137cc57600080fd5b505af11580156137e0573d6000803e3d6000fd5b505050506137f284610100015161190e565b156138fa5760065461010085015180516020918201516040516396755e5560e01b81526001600160a01b038b81166004830190815260606024840190815285516064850152855192909716966396755e55968e969594929391926044810192608490910191808801910280838360005b8381101561387a578181015183820152602001613862565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156138b95781810151838201526020016138a1565b5050505090500195505050505050600060405180830381600087803b1580156138e157600080fd5b505af11580156138f5573d6000803e3d6000fd5b505050505b8351604080519182526001602083015280516001600160a01b0389169260008051602061469d83398151915292908290030190a26139366145b0565b866001600160a01b03166000805160206146bd833981519152600083600001518460200151600160405180858152602001806020018060200184600381111561397b57fe5b60ff168152602001838103835286818151815260200191508051906020019060200280838360005b838110156139bb5781810151838201526020016139a3565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156139fa5781810151838201526020016139e2565b50505050905001965050505050505060405180910390a250505050949350505050565b600082613a2c57506000611362565b82820282848281613a3957fe5b041461135f5760405162461bcd60e51b815260040180806020018281038252602181526020018061467c6021913960400191505060405180910390fd5b600061135f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506143c6565b613ac06145b0565b60208201515182515114613b055760405162461bcd60e51b81526004018080602001828103825260358152602001806147136035913960400191505060405180910390fd5b8151516060906001600160401b0381118015613b2057600080fd5b50604051908082528060200260200182016040528015613b4a578160200160208202803683370190505b50905060005b835151811015613b9b5760c884602001518281518110613b6c57fe5b602002602001015181613b7b57fe5b04828281518110613b8857fe5b6020908102919091010152600101613b50565b50604080518082019091529251835260208301525090565b60005b835151811015613cf157600084600001518281518110613bd257fe5b60200260200101519050600085602001518381518110613bee57fe5b602090810291909101810151600054604080516324af709f60e11b81526001600160a01b038781166004830152915193955091169263495ee13e92602480840193829003018186803b158015613c4357600080fd5b505afa158015613c57573d6000803e3d6000fd5b505050506040513d6020811015613c6d57600080fd5b505115613ce7576040805163164746fd60e11b81526001600160a01b038781166004830152868116602483015260448201849052915191841691632c8e8dfa9160648082019260009290919082900301818387803b158015613cce57600080fd5b505af1158015613ce2573d6000803e3d6000fd5b505050505b5050600101613bb6565b50505050565b613cff614661565b82516060820151528251516001600160401b0381118015613d1f57600080fd5b50604051908082528060200260200182016040528015613d49578160200160208202803683370190505b506060820151602001528115613ff45782516020820151528251516001600160401b0381118015613d7957600080fd5b50604051908082528060200260200182016040528015613da3578160200160208202803683370190505b50602080830151015282516080820151528251516001600160401b0381118015613dcc57600080fd5b50604051908082528060200260200182016040528015613df6578160200160208202803683370190505b50608082015160200152613e0a848361442b565b808252613e1e90859063ffffffff612fab16565b60408201526000613e2e84614441565b90506000613e658661205c8560000151613e59670de0b6b3a764000080613a1d90919063ffffffff16565b9063ffffffff613a1d16565b90506000613e988361205c670f43fc2c04ee0000613e59670de0b6b3a76400008960000151613a1d90919063ffffffff16565b9050613ea4828261442b565b90506000613eb8838363ffffffff612fab16565b905060005b875151811015613fea57613f09670de0b6b3a764000061205c670de0b6b3a764000061205c878d602001518781518110613ef357fe5b6020026020010151613a1d90919063ffffffff16565b8660200151602001518281518110613f1d57fe5b602002602001018181525050613f55670de0b6b3a764000061205c670de0b6b3a764000061205c868d602001518781518110613ef357fe5b8660800151602001518281518110613f6957fe5b602002602001018181525050613fc38660800151602001518281518110613f8c57fe5b60200260200101516117218860200151602001518481518110613fab57fe5b60200260200101518b6020015185815181106124ab57fe5b8660600151602001518281518110613fd757fe5b6020908102919091010152600101613ebd565b505050505061404c565b60008082525b835151811015614043578360200151818151811061401457fe5b6020026020010151826060015160200151828151811061403057fe5b6020908102919091010152600101613ffa565b50604081018490525b9392505050565b61405b614612565b508151608082810191909152602083015160a0830152604083015160c0830152606083015160e08301529091015161010082015290565b61409a614612565b6140a26145b0565b8481526020810184905260006140ca670de0b6b3a764000061205c868a63ffffffff613a1d16565b905060006140d783614441565b905060006140f78261205c85670de0b6b3a764000063ffffffff613a1d16565b905061410b81670de0b6b3a764000061442b565b89865260208601859052680ad78ebc5ac62000006060870152608086018a9052600060c087015260a086015189905288519091506001600160401b038111801561415457600080fd5b5060405190808252806020026020018201604052801561417e578160200160208202803683370190505b5060a08601516020015261010085015188905287516001600160401b03811180156141a857600080fd5b506040519080825280602002602001820160405280156141d2578160200160208202803683370190505b5061010086015160200152604085015188905287516001600160401b03811180156141fc57600080fd5b50604051908082528060200260200182016040528015614226578160200160208202803683370190505b5060408601516020015260005b8851811015614322576000614270670de0b6b3a764000061205c8b858151811061425957fe5b602002602001015186613a1d90919063ffffffff16565b905060006142858260c863ffffffff613a7616565b90506000614299838363ffffffff612fab16565b905060006142ad848d87815181106124ab57fe5b9050828a604001516020015186815181106142c457fe5b602002602001018181525050818a60a001516020015186815181106142e557fe5b602002602001018181525050808a610100015160200151868151811061430757fe5b60209081029190910101525050600190920191506142339050565b5050505050949350505050565b600081848411156143be5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561438357818101518382015260200161436b565b50505050905090810190601f1680156143b05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836144155760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561438357818101518382015260200161436b565b50600083858161442157fe5b0495945050505050565b600081831061443a578161135f565b5090919050565b6000805b8251518110156130d65760008054845180516001600160a01b039092169163cacabd2791908590811061447457fe5b60200260200101518660200151858151811061448c57fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018281526020019250505060206040518083038186803b1580156144e157600080fd5b505afa1580156144f5573d6000803e3d6000fd5b505050506040513d602081101561450b57600080fd5b5051905061451f838263ffffffff61130516565b925050600101614445565b604051806060016040528060008152602001600015158152602001600081525090565b604051806101200160405280600081526020016000815260200161456f6145b0565b8152602001600081526020016000815260200161458a6145b0565b81526020016000815260200161459e6145b0565b81526020016145ab6145b0565b905290565b604051806040016040528060608152602001606081525090565b6040518060e0016040528060008152602001600081526020016000815260200160006001600160a01b0316815260200160001515815260200160008152602001600081525090565b6040518061012001604052806000815260200161462d6145b0565b815260200161456f6145b0565b604051806060016040528061464d6145b0565b8152602001600081526020016145ab6145b0565b6040518060a001604052806000815260200161458a6145b056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77679aef5b8c9f79ba6e1427981d7b06db55d0eadf337f8ed36e4ba5395a9111a398c96bbf8d2aa6be678259387225d169084fca483ed9598bde8ea258036bcacf54726f76654d616e616765723a2043616c6c646174612061646472657373206172726179206d757374206e6f7420626520656d7074795f676574436f6c6c476173436f6d70656e736174696f6e28293a20436f6c6c61746572616c206c656e677468206d69736d6174636854726f76654d616e616765723a206e6f7468696e6720746f206c6971756964617465a2646970667358221220feb1318e8b95d940fd870f4d604685db20e65a109272bd356553ce5ba224f12a64736f6c634300060b0033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|