Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
TroveManager
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import "../interfaces/IBorrowerOperations.sol"; import "../interfaces/IDebtToken.sol"; import "../interfaces/ISortedTroves.sol"; import "../interfaces/IVault.sol"; import "../interfaces/IPriceFeed.sol"; import { ReedemedTrove, ITroveRedemptionsCallback } from "../interfaces/IPrismaCallbacks.sol"; import "../dependencies/SystemStart.sol"; import "../dependencies/PrismaBase.sol"; import "../dependencies/PrismaMath.sol"; import "../dependencies/PrismaOwnable.sol"; /** @title Prisma Trove Manager @notice Based on Liquity's `TroveManager` https://github.com/liquity/dev/blob/main/packages/contracts/contracts/TroveManager.sol Prisma's implementation is modified so that multiple `TroveManager` and `SortedTroves` contracts are deployed in tandem, with each pair managing troves of a single collateral type. Functionality related to liquidations has been moved to `LiquidationManager`. This was necessary to avoid the restriction on deployed bytecode size. */ contract TroveManager is PrismaBase, PrismaOwnable, SystemStart { using SafeERC20 for IERC20; // --- Connected contract declarations --- address public immutable borrowerOperationsAddress; address public immutable liquidationManager; address immutable gasPoolAddress; IDebtToken public immutable debtToken; IPrismaVault public immutable vault; // During bootsrap period redemptions are not allowed uint256 public immutable bootstrapPeriod; IPriceFeed public priceFeed; IERC20 public collateralToken; // A doubly linked list of Troves, sorted by their collateral ratios ISortedTroves public sortedTroves; EmissionId public emissionId; // Minimum collateral ratio for individual troves uint256 public MCR; uint256 constant SECONDS_IN_ONE_MINUTE = 60; uint256 constant INTEREST_PRECISION = 1e27; uint256 constant SECONDS_IN_YEAR = 365 days; uint256 constant REWARD_DURATION = 1 weeks; // volume-based amounts are divided by this value to allow storing as uint32 uint256 constant VOLUME_MULTIPLIER = 1e20; uint256 public constant SUNSETTING_INTEREST_RATE = (INTEREST_PRECISION * 5000) / (10000 * SECONDS_IN_YEAR); //50% // During bootsrap period redemptions are not allowed /* * BETA: 18 digit decimal. Parameter by which to divide the redeemed fraction, in order to calc the new base rate from a redemption. * Corresponds to (1 / ALPHA) in the white paper. */ uint256 constant BETA = 2; // commented values are Liquity's fixed settings for each parameter uint256 public minuteDecayFactor; // 999037758833783000 (half-life of 12 hours) uint256 public redemptionFeeFloor; // DECIMAL_PRECISION / 1000 * 5 (0.5%) uint256 public maxRedemptionFee; // DECIMAL_PRECISION (100%) uint256 public borrowingFeeFloor; // DECIMAL_PRECISION / 1000 * 5 (0.5%) uint256 public maxBorrowingFee; // DECIMAL_PRECISION / 100 * 5 (5%) uint256 public maxSystemDebt; uint256 public interestRate; uint256 public activeInterestIndex; uint256 public lastActiveIndexUpdate; uint256 public systemDeploymentTime; bool public sunsetting; bool public paused; uint256 public baseRate; // The timestamp of the latest fee operation (redemption or new debt issuance) uint256 public lastFeeOperationTime; uint256 public totalStakes; // Snapshot of the value of totalStakes, taken immediately after the latest liquidation uint256 public totalStakesSnapshot; // Snapshot of the total collateral taken immediately after the latest liquidation. uint256 public totalCollateralSnapshot; /* * L_collateral and L_debt track the sums of accumulated liquidation rewards per unit staked. During its lifetime, each stake earns: * * An collateral gain of ( stake * [L_collateral - L_collateral(0)] ) * A debt increase of ( stake * [L_debt - L_debt(0)] ) * * Where L_collateral(0) and L_debt(0) are snapshots of L_collateral and L_debt for the active Trove taken at the instant the stake was made */ uint256 public L_collateral; uint256 public L_debt; // Error trackers for the trove redistribution calculation uint256 public lastCollateralError_Redistribution; uint256 public lastDebtError_Redistribution; uint256 internal totalActiveCollateral; uint256 internal totalActiveDebt; uint256 public interestPayable; uint256 public defaultedCollateral; uint256 public defaultedDebt; uint256 public rewardIntegral; uint128 public rewardRate; uint32 public lastUpdate; uint32 public periodFinish; uint16 public redemptionFeesRebate; ITroveRedemptionsCallback private _redemptionsCallback; mapping(address => uint256) public rewardIntegralFor; mapping(address => uint256) private storedPendingReward; // week -> total available rewards for 1 day within this week uint256[65535] public dailyMintReward; // week -> day -> total amount redeemed this day uint32[7][65535] private totalMints; // account -> data for latest activity mapping(address => VolumeData) public accountLatestMint; mapping(address => Trove) public Troves; mapping(address => uint256) public surplusBalances; // Map addresses with active troves to their RewardSnapshot mapping(address => RewardSnapshot) public rewardSnapshots; // Array of all active trove addresses - used to to compute an approximate hint off-chain, for the sorted list insertion address[] TroveOwners; struct VolumeData { uint32 amount; uint32 week; uint32 day; } struct EmissionId { uint16 debt; uint16 minting; } // Store the necessary data for a trove struct Trove { uint256 debt; uint256 coll; uint256 stake; Status status; uint128 arrayIndex; uint256 activeInterestIndex; } struct RedemptionTotals { uint256 remainingDebt; uint256 totalDebtToRedeem; uint256 totalCollateralDrawn; uint256 collateralFee; uint256 collateralToSendToRedeemer; uint256 decayedBaseRate; uint256 price; uint256 totalDebtSupplyAtStart; uint256 numberOfRedemptions; ReedemedTrove[] trovesRedeemed; } struct SingleRedemptionValues { uint256 debtLot; uint256 collateralLot; bool cancelledPartial; } // Object containing the collateral and debt snapshots for a given active trove struct RewardSnapshot { uint256 collateral; uint256 debt; } enum TroveManagerOperation { open, close, adjust, liquidate, redeemCollateral } enum Status { nonExistent, active, closedByOwner, closedByLiquidation, closedByRedemption } event TroveUpdated( address indexed _borrower, uint256 _debt, uint256 _coll, uint256 _stake, TroveManagerOperation _operation ); event Redemption( uint256 _attemptedDebtAmount, uint256 _actualDebtAmount, uint256 _collateralSent, uint256 _collateralFee ); event BaseRateUpdated(uint256 _baseRate); event LastFeeOpTimeUpdated(uint256 _lastFeeOpTime); event TotalStakesUpdated(uint256 _newTotalStakes); event SystemSnapshotsUpdated(uint256 _totalStakesSnapshot, uint256 _totalCollateralSnapshot); event LTermsUpdated(uint256 _L_collateral, uint256 _L_debt); event TroveSnapshotsUpdated(uint256 _L_collateral, uint256 _L_debt); event TroveIndexUpdated(address _borrower, uint256 _newIndex); event CollateralSent(address _to, uint256 _amount); event RewardClaimed(address indexed account, address indexed recipient, uint256 claimed); event RedemptionFeesRebateSet(uint16 redemptionFeesRebate); modifier whenNotPaused() { require(!paused, "Collateral Paused"); _; } constructor( address _prismaCore, address _gasPoolAddress, address _debtTokenAddress, address _borrowerOperationsAddress, address _vault, address _liquidationManager, uint256 _gasCompensation, uint256 _bootstrapPeriod ) PrismaOwnable(_prismaCore) PrismaBase(_gasCompensation) SystemStart(_prismaCore) { gasPoolAddress = _gasPoolAddress; debtToken = IDebtToken(_debtTokenAddress); borrowerOperationsAddress = _borrowerOperationsAddress; vault = IPrismaVault(_vault); liquidationManager = _liquidationManager; bootstrapPeriod = _bootstrapPeriod; } function setAddresses(address _priceFeedAddress, address _sortedTrovesAddress, address _collateralToken) external { require(address(sortedTroves) == address(0)); priceFeed = IPriceFeed(_priceFeedAddress); sortedTroves = ISortedTroves(_sortedTrovesAddress); collateralToken = IERC20(_collateralToken); systemDeploymentTime = block.timestamp; sunsetting = false; activeInterestIndex = INTEREST_PRECISION; lastActiveIndexUpdate = block.timestamp; } function notifyRegisteredId(uint256[] calldata _assignedIds) external returns (bool) { require(msg.sender == address(vault)); require(emissionId.debt == 0, "Already assigned"); uint256 length = _assignedIds.length; require(length == 2, "Incorrect ID count"); emissionId = EmissionId({ debt: uint16(_assignedIds[0]), minting: uint16(_assignedIds[1]) }); periodFinish = uint32(((block.timestamp / 1 weeks) + 1) * 1 weeks); return true; } /** * @notice Sets the pause state for this trove manager * Pausing is used to mitigate risks in exceptional circumstances * Functionalities affected by pausing are: * - New borrowing is not possible * - New collateral deposits are not possible * @param _paused If true the protocol is paused */ function setPaused(bool _paused) external { require((_paused && msg.sender == guardian()) || msg.sender == owner(), "Unauthorized"); paused = _paused; } /** * @notice Sets a custom price feed for this trove manager * @param _priceFeedAddress Price feed address */ function setPriceFeed(address _priceFeedAddress) external onlyOwner { priceFeed = IPriceFeed(_priceFeedAddress); } /** * @notice Sets a callback contract for redemptions on this trove manager * @param redemptionsCallback Callback contract */ function setRedemptionsCallback(ITroveRedemptionsCallback redemptionsCallback) external onlyOwner { _redemptionsCallback = redemptionsCallback; } /** * @notice Starts sunsetting a collateral * During sunsetting only the following are possible: 1) Disable collateral handoff to SP 2) Greatly Increase interest rate to incentivize redemptions 3) Remove redemptions fees 4) Disable new loans @dev IMPORTANT: When sunsetting a collateral altogether this function should be called on all TM linked to that collateral as well as `StabilityPool.startCollateralSunset` */ function startSunset() external onlyOwner { sunsetting = true; _accrueActiveInterests(); interestRate = SUNSETTING_INTEREST_RATE; // accrual function doesn't update timestamp if interest was 0 lastActiveIndexUpdate = block.timestamp; redemptionFeeFloor = 0; maxSystemDebt = 0; } /** * @notice Sets the redemption fees rebate percentage * @param _redemptionFeesRebate Percentage of redemption fees rebated to users expressed in bps */ function setRedemptionFeesRebate(uint16 _redemptionFeesRebate) external onlyOwner { require(_redemptionFeesRebate <= 10000, "Too large"); redemptionFeesRebate = _redemptionFeesRebate; emit RedemptionFeesRebateSet(_redemptionFeesRebate); } /* _minuteDecayFactor is calculated as 10**18 * (1/2)**(1/n) where n = the half-life in minutes */ function setParameters( uint256 _minuteDecayFactor, uint256 _redemptionFeeFloor, uint256 _maxRedemptionFee, uint256 _borrowingFeeFloor, uint256 _maxBorrowingFee, uint256 _interestRateInBPS, uint256 _maxSystemDebt, uint256 _MCR ) public { require(!sunsetting, "Cannot change after sunset"); require(_MCR <= CCR && _MCR >= 1100000000000000000, "MCR cannot be > CCR or < 110%"); if (minuteDecayFactor != 0) { require(msg.sender == owner(), "Only owner"); } require( _minuteDecayFactor >= 977159968434245000 && // half-life of 30 minutes _minuteDecayFactor <= 999931237762985000 // half-life of 1 week ); require(_redemptionFeeFloor <= _maxRedemptionFee && _maxRedemptionFee <= DECIMAL_PRECISION); require(_borrowingFeeFloor <= _maxBorrowingFee && _maxBorrowingFee <= DECIMAL_PRECISION); _decayBaseRate(); minuteDecayFactor = _minuteDecayFactor; redemptionFeeFloor = _redemptionFeeFloor; maxRedemptionFee = _maxRedemptionFee; borrowingFeeFloor = _borrowingFeeFloor; maxBorrowingFee = _maxBorrowingFee; maxSystemDebt = _maxSystemDebt; uint256 newInterestRate = (INTEREST_PRECISION * _interestRateInBPS) / (10000 * SECONDS_IN_YEAR); if (newInterestRate != interestRate) { _accrueActiveInterests(); // accrual function doesn't update timestamp if interest was 0 lastActiveIndexUpdate = block.timestamp; interestRate = newInterestRate; } MCR = _MCR; } function collectInterests() external { uint256 interestPayableCached = interestPayable; require(interestPayableCached > 0, "Nothing to collect"); debtToken.mint(PRISMA_CORE.feeReceiver(), interestPayableCached); interestPayable = 0; } // --- Getters --- function fetchPrice() public returns (uint256) { IPriceFeed _priceFeed = priceFeed; if (address(_priceFeed) == address(0)) { _priceFeed = IPriceFeed(PRISMA_CORE.priceFeed()); } return _priceFeed.fetchPrice(address(collateralToken)); } function getWeekAndDay() public view returns (uint256, uint256) { uint256 duration = (block.timestamp - startTime); uint256 week = duration / 1 weeks; uint256 day = (duration % 1 weeks) / 1 days; return (week, day); } function getTotalMints(uint256 week) external view returns (uint32[7] memory) { return totalMints[week]; } function getTroveOwnersCount() external view returns (uint256) { return TroveOwners.length; } function getInterestRateInBps() external view returns (uint256) { return (interestRate * 10000 * SECONDS_IN_YEAR) / INTEREST_PRECISION; } function getTroveFromTroveOwnersArray(uint256 _index) external view returns (address) { return TroveOwners[_index]; } function getTroveStatus(address _borrower) external view returns (uint256) { return uint256(Troves[_borrower].status); } function getTroveStake(address _borrower) external view returns (uint256) { return Troves[_borrower].stake; } /** @notice Get the current total collateral and debt amounts for a trove @dev Also includes pending rewards from redistribution */ function getTroveCollAndDebt(address _borrower) public view returns (uint256 coll, uint256 debt) { (debt, coll, , ) = getEntireDebtAndColl(_borrower); return (coll, debt); } /** @notice Get the total and pending collateral and debt amounts for a trove @dev Used by the liquidation manager */ function getEntireDebtAndColl( address _borrower ) public view returns (uint256 debt, uint256 coll, uint256 pendingDebtReward, uint256 pendingCollateralReward) { Trove storage t = Troves[_borrower]; debt = t.debt; coll = t.coll; (pendingCollateralReward, pendingDebtReward) = getPendingCollAndDebtRewards(_borrower); // Accrued trove interest for correct liquidation values. This assumes the index to be updated. uint256 troveInterestIndex = t.activeInterestIndex; if (troveInterestIndex > 0) { (uint256 currentIndex, ) = _calculateInterestIndex(); debt = (debt * currentIndex) / troveInterestIndex; } debt = debt + pendingDebtReward; coll = coll + pendingCollateralReward; } function getEntireSystemColl() public view returns (uint256) { return totalActiveCollateral + defaultedCollateral; } function getEntireSystemDebt() public view returns (uint256) { uint256 currentActiveDebt = totalActiveDebt; (, uint256 interestFactor) = _calculateInterestIndex(); if (interestFactor > 0) { uint256 activeInterests = Math.mulDiv(currentActiveDebt, interestFactor, INTEREST_PRECISION); currentActiveDebt = currentActiveDebt + activeInterests; } return currentActiveDebt + defaultedDebt; } function getEntireSystemBalances() external returns (uint256, uint256, uint256) { return (getEntireSystemColl(), getEntireSystemDebt(), fetchPrice()); } // --- Helper functions --- // Return the nominal collateral ratio (ICR) of a given Trove, without the price. Takes a trove's pending coll and debt rewards from redistributions into account. function getNominalICR(address _borrower) public view returns (uint256) { (uint256 currentCollateral, uint256 currentDebt) = getTroveCollAndDebt(_borrower); uint256 NICR = PrismaMath._computeNominalCR(currentCollateral, currentDebt); return NICR; } // Return the current collateral ratio (ICR) of a given Trove. Takes a trove's pending coll and debt rewards from redistributions into account. function getCurrentICR(address _borrower, uint256 _price) public view returns (uint256) { (uint256 currentCollateral, uint256 currentDebt) = getTroveCollAndDebt(_borrower); uint256 ICR = PrismaMath._computeCR(currentCollateral, currentDebt, _price); return ICR; } function getTotalActiveCollateral() public view returns (uint256) { return totalActiveCollateral; } function getTotalActiveDebt() public view returns (uint256) { uint256 currentActiveDebt = totalActiveDebt; (, uint256 interestFactor) = _calculateInterestIndex(); if (interestFactor > 0) { uint256 activeInterests = Math.mulDiv(currentActiveDebt, interestFactor, INTEREST_PRECISION); currentActiveDebt = currentActiveDebt + activeInterests; } return currentActiveDebt; } // Get the borrower's pending accumulated collateral and debt rewards, earned by their stake function getPendingCollAndDebtRewards(address _borrower) public view returns (uint256, uint256) { RewardSnapshot memory snapshot = rewardSnapshots[_borrower]; uint256 coll = L_collateral - snapshot.collateral; uint256 debt = L_debt - snapshot.debt; if (coll + debt == 0 || Troves[_borrower].status != Status.active) return (0, 0); uint256 stake = Troves[_borrower].stake; return ((stake * coll) / DECIMAL_PRECISION, (stake * debt) / DECIMAL_PRECISION); } function hasPendingRewards(address _borrower) public view returns (bool) { /* * A Trove has pending rewards if its snapshot is less than the current rewards per-unit-staked sum: * this indicates that rewards have occured since the snapshot was made, and the user therefore has * pending rewards */ if (Troves[_borrower].status != Status.active) { return false; } return (rewardSnapshots[_borrower].collateral < L_collateral); } // --- Redemption fee functions --- /* * This function has two impacts on the baseRate state variable: * 1) decays the baseRate based on time passed since last redemption or debt borrowing operation. * then, * 2) increases the baseRate based on the amount redeemed, as a proportion of total supply */ function _updateBaseRateFromRedemption( uint256 _collateralDrawn, uint256 _price, uint256 _totalDebtSupply ) internal returns (uint256) { uint256 decayedBaseRate = _calcDecayedBaseRate(); /* Convert the drawn collateral back to debt at face value rate (1 debt:1 USD), in order to get * the fraction of total supply that was redeemed at face value. */ uint256 redeemedDebtFraction = (_collateralDrawn * _price) / _totalDebtSupply; uint256 newBaseRate = decayedBaseRate + (redeemedDebtFraction / BETA); newBaseRate = PrismaMath._min(newBaseRate, DECIMAL_PRECISION); // cap baseRate at a maximum of 100% // Update the baseRate state variable baseRate = newBaseRate; emit BaseRateUpdated(newBaseRate); _updateLastFeeOpTime(); return newBaseRate; } function getRedemptionRate() public view returns (uint256) { return _calcRedemptionRate(baseRate); } function getRedemptionRateWithDecay() public view returns (uint256) { return _calcRedemptionRate(_calcDecayedBaseRate()); } function _calcRedemptionRate(uint256 _baseRate) internal view returns (uint256) { return PrismaMath._min( redemptionFeeFloor + _baseRate, maxRedemptionFee // cap at a maximum of 100% ); } function getRedemptionFeeWithDecay(uint256 _collateralDrawn) external view returns (uint256) { return _calcRedemptionFee(getRedemptionRateWithDecay(), _collateralDrawn); } function _calcRedemptionFee(uint256 _redemptionRate, uint256 _collateralDrawn) internal pure returns (uint256) { uint256 redemptionFee = (_redemptionRate * _collateralDrawn) / DECIMAL_PRECISION; require(redemptionFee < _collateralDrawn, "Fee exceeds returned collateral"); return redemptionFee; } // --- Borrowing fee functions --- function getBorrowingRate() public view returns (uint256) { return _calcBorrowingRate(baseRate); } function getBorrowingRateWithDecay() public view returns (uint256) { return _calcBorrowingRate(_calcDecayedBaseRate()); } function _calcBorrowingRate(uint256 _baseRate) internal view returns (uint256) { return PrismaMath._min(borrowingFeeFloor + _baseRate, maxBorrowingFee); } function getBorrowingFee(uint256 _debt) external view returns (uint256) { return _calcBorrowingFee(getBorrowingRate(), _debt); } function getBorrowingFeeWithDecay(uint256 _debt) external view returns (uint256) { return _calcBorrowingFee(getBorrowingRateWithDecay(), _debt); } function _calcBorrowingFee(uint256 _borrowingRate, uint256 _debt) internal pure returns (uint256) { return (_borrowingRate * _debt) / DECIMAL_PRECISION; } // --- Internal fee functions --- // Update the last fee operation time only if time passed >= decay interval. This prevents base rate griefing. function _updateLastFeeOpTime() internal { uint256 timePassed = block.timestamp - lastFeeOperationTime; if (timePassed >= SECONDS_IN_ONE_MINUTE) { lastFeeOperationTime = block.timestamp; emit LastFeeOpTimeUpdated(block.timestamp); } } function _calcDecayedBaseRate() internal view returns (uint256) { uint256 minutesPassed = (block.timestamp - lastFeeOperationTime) / SECONDS_IN_ONE_MINUTE; uint256 decayFactor = PrismaMath._decPow(minuteDecayFactor, minutesPassed); return (baseRate * decayFactor) / DECIMAL_PRECISION; } // --- Redemption functions --- /* Send _debtAmount debt to the system and redeem the corresponding amount of collateral from as many Troves as are needed to fill the redemption * request. Applies pending rewards to a Trove before reducing its debt and coll. * * Note that if _amount is very large, this function can run out of gas, specially if traversed troves are small. This can be easily avoided by * splitting the total _amount in appropriate chunks and calling the function multiple times. * * Param `_maxIterations` can also be provided, so the loop through Troves is capped (if it’s zero, it will be ignored).This makes it easier to * avoid OOG for the frontend, as only knowing approximately the average cost of an iteration is enough, without needing to know the “topology” * of the trove list. It also avoids the need to set the cap in stone in the contract, nor doing gas calculations, as both gas price and opcode * costs can vary. * * All Troves that are redeemed from -- with the likely exception of the last one -- will end up with no debt left, therefore they will be closed. * If the last Trove does have some remaining debt, it has a finite ICR, and the reinsertion could be anywhere in the list, therefore it requires a hint. * A frontend should use getRedemptionHints() to calculate what the ICR of this Trove will be after redemption, and pass a hint for its position * in the sortedTroves list along with the ICR value that the hint was found for. * * If another transaction modifies the list between calling getRedemptionHints() and passing the hints to redeemCollateral(), it * is very likely that the last (partially) redeemed Trove would end up with a different ICR than what the hint is for. In this case the * redemption will stop after the last completely redeemed Trove and the sender will keep the remaining debt amount, which they can attempt * to redeem later. */ function redeemCollateral( uint256 _debtAmount, address _firstRedemptionHint, address _upperPartialRedemptionHint, address _lowerPartialRedemptionHint, uint256 _partialRedemptionHintNICR, uint256 _maxIterations, uint256 _maxFeePercentage ) external { ISortedTroves _sortedTrovesCached = sortedTroves; RedemptionTotals memory totals; require( _maxFeePercentage >= redemptionFeeFloor && _maxFeePercentage <= maxRedemptionFee, "Max fee 0.5% to 100%" ); require(block.timestamp >= systemDeploymentTime + bootstrapPeriod, "BOOTSTRAP_PERIOD"); totals.price = fetchPrice(); uint256 _MCR = MCR; require(IBorrowerOperations(borrowerOperationsAddress).getTCR() >= _MCR, "Cannot redeem when TCR < MCR"); require(_debtAmount > 0, "Amount must be greater than zero"); require(debtToken.balanceOf(msg.sender) >= _debtAmount, "Insufficient balance"); _updateBalances(); totals.totalDebtSupplyAtStart = getEntireSystemDebt(); totals.remainingDebt = _debtAmount; address currentBorrower; if (_isValidFirstRedemptionHint(_sortedTrovesCached, _firstRedemptionHint, totals.price, _MCR)) { currentBorrower = _firstRedemptionHint; } else { currentBorrower = _sortedTrovesCached.getLast(); // Find the first trove with ICR >= MCR while (currentBorrower != address(0) && getCurrentICR(currentBorrower, totals.price) < _MCR) { currentBorrower = _sortedTrovesCached.getPrev(currentBorrower); } } // Loop through the Troves starting from the one with lowest collateral ratio until _amount of debt is exchanged for collateral if (_maxIterations == 0 || _maxIterations > 100) { _maxIterations = 100; } totals.trovesRedeemed = new ReedemedTrove[](_maxIterations); totals.numberOfRedemptions = 0; while (currentBorrower != address(0) && totals.remainingDebt > 0 && _maxIterations > 0) { _maxIterations--; // Save the address of the Trove preceding the current one, before potentially modifying the list address nextUserToCheck = _sortedTrovesCached.getPrev(currentBorrower); _applyPendingRewards(currentBorrower); SingleRedemptionValues memory singleRedemption = _redeemCollateralFromTrove( _sortedTrovesCached, currentBorrower, totals.remainingDebt, totals.price, _upperPartialRedemptionHint, _lowerPartialRedemptionHint, _partialRedemptionHintNICR ); if (singleRedemption.cancelledPartial) break; // Partial redemption was cancelled (out-of-date hint, or new net debt < minimum), therefore we could not redeem from the last Trove totals.trovesRedeemed[totals.numberOfRedemptions++] = ReedemedTrove( currentBorrower, singleRedemption.debtLot, singleRedemption.collateralLot ); totals.totalDebtToRedeem = totals.totalDebtToRedeem + singleRedemption.debtLot; totals.totalCollateralDrawn = totals.totalCollateralDrawn + singleRedemption.collateralLot; totals.remainingDebt = totals.remainingDebt - singleRedemption.debtLot; currentBorrower = nextUserToCheck; } require(totals.totalCollateralDrawn > 0, "Unable to redeem any amount"); // Decay the baseRate due to time passed, and then increase it according to the size of this redemption. // Use the saved total debt supply value, from before it was reduced by the redemption. _updateBaseRateFromRedemption(totals.totalCollateralDrawn, totals.price, totals.totalDebtSupplyAtStart); // Calculate the collateral fee totals.collateralFee = sunsetting ? 0 : _calcRedemptionFee(getRedemptionRate(), totals.totalCollateralDrawn); _requireUserAcceptsFee(totals.collateralFee, totals.totalCollateralDrawn, _maxFeePercentage); uint256 userRebate = (redemptionFeesRebate * totals.collateralFee) / 10000; uint256 _numberOfRedemptions = totals.numberOfRedemptions; if (userRebate > 0) { for (uint256 i; i < _numberOfRedemptions; ) { ReedemedTrove memory refund = totals.trovesRedeemed[i]; surplusBalances[refund.account] += (userRebate * refund.collateralLot) / totals.totalCollateralDrawn; unchecked { ++i; } } } if (redemptionFeesRebate < 10000) { uint256 treasuryRebate = totals.collateralFee - userRebate; _sendCollateral(PRISMA_CORE.feeReceiver(), treasuryRebate); } totals.collateralToSendToRedeemer = totals.totalCollateralDrawn - totals.collateralFee; emit Redemption(_debtAmount, totals.totalDebtToRedeem, totals.totalCollateralDrawn, totals.collateralFee); // Burn the total debt that is cancelled with debt, and send the redeemed collateral to msg.sender debtToken.burn(msg.sender, totals.totalDebtToRedeem); // Update Trove Manager debt, and send collateral to account totalActiveDebt = totalActiveDebt - totals.totalDebtToRedeem; _sendCollateral(msg.sender, totals.collateralToSendToRedeemer); _resetState(); if (address(_redemptionsCallback) != address(0)) { assembly { // Load array pointer value at slot 9 in the struct let trovesRedeemedLengthSlot := mload(add(totals, 0x120)) // Set array length in referenced location mstore(trovesRedeemedLengthSlot, _numberOfRedemptions) } _redemptionsCallback.onRedemptions(totals.trovesRedeemed); } } // Redeem as much collateral as possible from _borrower's Trove in exchange for debt up to _maxDebtAmount function _redeemCollateralFromTrove( ISortedTroves _sortedTrovesCached, address _borrower, uint256 _maxDebtAmount, uint256 _price, address _upperPartialRedemptionHint, address _lowerPartialRedemptionHint, uint256 _partialRedemptionHintNICR ) internal returns (SingleRedemptionValues memory singleRedemption) { Trove storage t = Troves[_borrower]; // Determine the remaining amount (lot) to be redeemed, capped by the entire debt of the Trove minus the liquidation reserve singleRedemption.debtLot = PrismaMath._min(_maxDebtAmount, t.debt - DEBT_GAS_COMPENSATION); // Get the CollateralLot of equivalent value in USD singleRedemption.collateralLot = (singleRedemption.debtLot * DECIMAL_PRECISION) / _price; // Decrease the debt and collateral of the current Trove according to the debt lot and corresponding collateral to send uint256 newDebt = (t.debt) - singleRedemption.debtLot; uint256 newColl = (t.coll) - singleRedemption.collateralLot; if (newDebt == DEBT_GAS_COMPENSATION) { // No debt left in the Trove (except for the liquidation reserve), therefore the trove gets closed _removeStake(_borrower); _closeTrove(_borrower, Status.closedByRedemption); _redeemCloseTrove(_borrower, DEBT_GAS_COMPENSATION, newColl); emit TroveUpdated(_borrower, 0, 0, 0, TroveManagerOperation.redeemCollateral); } else { uint256 newNICR = PrismaMath._computeNominalCR(newColl, newDebt); /* * If the provided hint is out of date, we bail since trying to reinsert without a good hint will almost * certainly result in running out of gas. * * If the resultant net debt of the partial is less than the minimum, net debt we bail. */ { // We check if the ICR hint is reasonable up to date, with continuous interest there might be slight differences (<1bps) uint256 icrError = _partialRedemptionHintNICR > newNICR ? _partialRedemptionHintNICR - newNICR : newNICR - _partialRedemptionHintNICR; if ( icrError > 5e14 || _getNetDebt(newDebt) < IBorrowerOperations(borrowerOperationsAddress).minNetDebt() ) { singleRedemption.cancelledPartial = true; return singleRedemption; } } _sortedTrovesCached.reInsert(_borrower, newNICR, _upperPartialRedemptionHint, _lowerPartialRedemptionHint); t.debt = newDebt; t.coll = newColl; _updateStakeAndTotalStakes(t); emit TroveUpdated(_borrower, newDebt, newColl, t.stake, TroveManagerOperation.redeemCollateral); } return singleRedemption; } /* * Called when a full redemption occurs, and closes the trove. * The redeemer swaps (debt - liquidation reserve) debt for (debt - liquidation reserve) worth of collateral, so the debt liquidation reserve left corresponds to the remaining debt. * In order to close the trove, the debt liquidation reserve is burned, and the corresponding debt is removed. * The debt recorded on the trove's struct is zero'd elswhere, in _closeTrove. * Any surplus collateral left in the trove can be later claimed by the borrower. */ function _redeemCloseTrove(address _borrower, uint256 _debt, uint256 _collateral) internal { debtToken.burn(gasPoolAddress, _debt); totalActiveDebt = totalActiveDebt - _debt; surplusBalances[_borrower] += _collateral; totalActiveCollateral -= _collateral; } function _isValidFirstRedemptionHint( ISortedTroves _sortedTroves, address _firstRedemptionHint, uint256 _price, uint256 _MCR ) internal view returns (bool) { if ( _firstRedemptionHint == address(0) || !_sortedTroves.contains(_firstRedemptionHint) || getCurrentICR(_firstRedemptionHint, _price) < _MCR ) { return false; } address nextTrove = _sortedTroves.getNext(_firstRedemptionHint); return nextTrove == address(0) || getCurrentICR(nextTrove, _price) < _MCR; } /** * Claim remaining collateral from a redemption or from a liquidation with ICR > MCR in Recovery Mode */ function claimCollateral(address _receiver) external { uint256 claimableColl = surplusBalances[msg.sender]; require(claimableColl > 0, "No collateral available to claim"); surplusBalances[msg.sender] = 0; collateralToken.safeTransfer(_receiver, claimableColl); } // --- Reward Claim functions --- function claimReward(address receiver) external returns (uint256) { uint256 amount = _claimReward(msg.sender); if (amount > 0) { vault.transferAllocatedTokens(msg.sender, receiver, amount); } emit RewardClaimed(msg.sender, receiver, amount); return amount; } function vaultClaimReward(address claimant, address) external returns (uint256) { require(msg.sender == address(vault)); return _claimReward(claimant); } function _claimReward(address account) internal returns (uint256) { require(emissionId.debt > 0, "Rewards not active"); // update active debt rewards _applyPendingRewards(account); uint256 amount = storedPendingReward[account]; if (amount > 0) storedPendingReward[account] = 0; // add pending mint awards uint256 mintAmount = _getPendingMintReward(account); if (mintAmount > 0) { amount += mintAmount; delete accountLatestMint[account]; } return amount; } function claimableReward(address account) external view returns (uint256) { // previously calculated rewards uint256 amount = storedPendingReward[account]; // pending active debt rewards uint256 updated = periodFinish; if (updated > block.timestamp) updated = block.timestamp; uint256 duration = updated - lastUpdate; uint256 integral = rewardIntegral; if (duration > 0) { uint256 supply = totalActiveDebt; if (supply > 0) { integral += (duration * rewardRate * 1e18) / supply; } } uint256 integralFor = rewardIntegralFor[account]; if (integral > integralFor) { amount += (Troves[account].debt * (integral - integralFor)) / 1e18; } // pending mint rewards amount += _getPendingMintReward(account); return amount; } function _getPendingMintReward(address account) internal view returns (uint256 amount) { VolumeData memory data = accountLatestMint[account]; if (data.amount > 0) { (uint256 week, uint256 day) = getWeekAndDay(); if (data.day != day || data.week != week) { return (dailyMintReward[data.week] * data.amount) / totalMints[data.week][data.day]; } } } function _updateIntegrals(address account, uint256 balance, uint256 supply) internal { uint256 integral = _updateRewardIntegral(supply); _updateIntegralForAccount(account, balance, integral); } function _updateIntegralForAccount(address account, uint256 balance, uint256 currentIntegral) internal { uint256 integralFor = rewardIntegralFor[account]; if (currentIntegral > integralFor) { storedPendingReward[account] += (balance * (currentIntegral - integralFor)) / 1e18; rewardIntegralFor[account] = currentIntegral; } } function _updateRewardIntegral(uint256 supply) internal returns (uint256 integral) { uint256 _periodFinish = periodFinish; uint256 updated = _periodFinish; if (updated > block.timestamp) updated = block.timestamp; uint256 duration = updated - lastUpdate; integral = rewardIntegral; if (duration > 0) { lastUpdate = uint32(updated); if (supply > 0) { integral += (duration * rewardRate * 1e18) / supply; rewardIntegral = integral; } } _fetchRewards(_periodFinish); return integral; } function _fetchRewards(uint256 _periodFinish) internal { EmissionId memory id = emissionId; if (id.debt == 0) return; uint256 currentWeek = getWeek(); if (currentWeek < (_periodFinish - startTime) / 1 weeks) return; uint256 previousWeek = (_periodFinish - startTime) / 1 weeks - 1; // active debt rewards uint256 amount = vault.allocateNewEmissions(id.debt); if (block.timestamp < _periodFinish) { uint256 remaining = _periodFinish - block.timestamp; amount += remaining * rewardRate; } rewardRate = uint128(amount / REWARD_DURATION); lastUpdate = uint32(block.timestamp); periodFinish = uint32(block.timestamp + REWARD_DURATION); // minting rewards amount = vault.allocateNewEmissions(id.minting); uint256 reward = dailyMintReward[previousWeek]; if (reward > 0) { uint32[7] memory totals = totalMints[previousWeek]; for (uint256 i = 0; i < 7; i++) { if (totals[i] == 0) { amount += reward; } } } dailyMintReward[currentWeek] = amount / 7; } // --- Trove Adjustment functions --- function openTrove( address _borrower, uint256 _collateralAmount, uint256 _compositeDebt, uint256 NICR, address _upperHint, address _lowerHint, bool _isRecoveryMode ) external whenNotPaused returns (uint256 stake, uint256 arrayIndex) { _requireCallerIsBO(); require(!sunsetting, "Cannot open while sunsetting"); uint256 supply = totalActiveDebt; Trove storage t = Troves[_borrower]; require(t.status != Status.active, "BorrowerOps: Trove is active"); t.status = Status.active; t.coll = _collateralAmount; t.debt = _compositeDebt; uint256 currentInterestIndex = _accrueActiveInterests(); t.activeInterestIndex = currentInterestIndex; _updateTroveRewardSnapshots(_borrower); stake = _updateStakeAndTotalStakes(t); sortedTroves.insert(_borrower, NICR, _upperHint, _lowerHint); TroveOwners.push(_borrower); arrayIndex = TroveOwners.length - 1; t.arrayIndex = uint128(arrayIndex); _updateIntegrals(_borrower, 0, supply); if (!_isRecoveryMode) _updateMintVolume(_borrower, _compositeDebt); totalActiveCollateral = totalActiveCollateral + _collateralAmount; uint256 _newTotalDebt = totalActiveDebt + _compositeDebt; require(_newTotalDebt + defaultedDebt <= maxSystemDebt, "Collateral debt limit reached"); totalActiveDebt = _newTotalDebt; emit TroveUpdated(_borrower, _compositeDebt, _collateralAmount, stake, TroveManagerOperation.open); } function updateTroveFromAdjustment( bool _isRecoveryMode, bool _isDebtIncrease, uint256 _debtChange, uint256 _netDebtChange, bool _isCollIncrease, uint256 _collChange, address _upperHint, address _lowerHint, address _borrower, address _receiver ) external returns (uint256, uint256, uint256) { _requireCallerIsBO(); if (_isCollIncrease || _isDebtIncrease) { require(!paused, "Collateral Paused"); require(!sunsetting, "Cannot increase while sunsetting"); } Trove storage t = Troves[_borrower]; require(t.status == Status.active, "Trove closed or does not exist"); uint256 newDebt = t.debt; if (_debtChange > 0) { if (_isDebtIncrease) { newDebt = newDebt + _netDebtChange; if (!_isRecoveryMode) _updateMintVolume(_borrower, _netDebtChange); _increaseDebt(_receiver, _netDebtChange, _debtChange); } else { newDebt = newDebt - _netDebtChange; _decreaseDebt(_receiver, _debtChange); } t.debt = newDebt; } uint256 newColl = t.coll; if (_collChange > 0) { if (_isCollIncrease) { newColl = newColl + _collChange; totalActiveCollateral = totalActiveCollateral + _collChange; // trust that BorrowerOperations sent the collateral } else { newColl = newColl - _collChange; _sendCollateral(_receiver, _collChange); } t.coll = newColl; } uint256 newNICR = PrismaMath._computeNominalCR(newColl, newDebt); sortedTroves.reInsert(_borrower, newNICR, _upperHint, _lowerHint); uint256 newStake = _updateStakeAndTotalStakes(t); emit TroveUpdated(_borrower, newDebt, newColl, newStake, TroveManagerOperation.adjust); return (newColl, newDebt, newStake); } function closeTrove(address _borrower, address _receiver, uint256 collAmount, uint256 debtAmount) external { _requireCallerIsBO(); require(Troves[_borrower].status == Status.active, "Trove closed or does not exist"); _removeStake(_borrower); _closeTrove(_borrower, Status.closedByOwner); if (TroveOwners.length > 0) { totalActiveDebt = totalActiveDebt - debtAmount; } else { // Account for dust discrepancies due to interest sampling totalActiveDebt = 0; } _sendCollateral(_receiver, collAmount); _resetState(); emit TroveUpdated(_borrower, 0, 0, 0, TroveManagerOperation.close); } /** @dev Only called from `closeTrove` because liquidating the final trove is blocked in `LiquidationManager`. Many liquidation paths involve redistributing debt and collateral to existing troves. If the collateral is being sunset, the final trove must be closed by repaying the debt or via a redemption. */ function _resetState() private { if (TroveOwners.length == 0) { activeInterestIndex = INTEREST_PRECISION; lastActiveIndexUpdate = block.timestamp; totalStakes = 0; totalStakesSnapshot = 0; totalCollateralSnapshot = 0; L_collateral = 0; L_debt = 0; lastCollateralError_Redistribution = 0; lastDebtError_Redistribution = 0; totalActiveCollateral = 0; totalActiveDebt = 0; defaultedCollateral = 0; defaultedDebt = 0; } } function _closeTrove(address _borrower, Status closedStatus) internal { uint256 TroveOwnersArrayLength = TroveOwners.length; Trove storage t = Troves[_borrower]; t.status = closedStatus; t.coll = 0; t.debt = 0; t.activeInterestIndex = 0; ISortedTroves sortedTrovesCached = sortedTroves; rewardSnapshots[_borrower].collateral = 0; rewardSnapshots[_borrower].debt = 0; if (TroveOwnersArrayLength > 1 && sortedTrovesCached.getSize() > 1) { // remove trove owner from the TroveOwners array, not preserving array order uint128 index = t.arrayIndex; address addressToMove = TroveOwners[TroveOwnersArrayLength - 1]; TroveOwners[index] = addressToMove; Troves[addressToMove].arrayIndex = index; emit TroveIndexUpdated(addressToMove, index); } TroveOwners.pop(); sortedTrovesCached.remove(_borrower); t.arrayIndex = 0; } function _updateMintVolume(address account, uint256 initialAmount) internal { uint32 amount = uint32(initialAmount / VOLUME_MULTIPLIER); (uint256 week, uint256 day) = getWeekAndDay(); totalMints[week][day] += amount; VolumeData memory data = accountLatestMint[account]; if (data.day == day && data.week == week) { // if the caller made a previous redemption today, we only increase their redeemed amount accountLatestMint[account].amount = data.amount + amount; } else { if (data.amount > 0) { // if the caller made a previous redemption on a different day, // calculate the emissions earned for that redemption uint256 pending = (dailyMintReward[data.week] * data.amount) / totalMints[data.week][data.day]; storedPendingReward[account] += pending; } accountLatestMint[account] = VolumeData({ week: uint32(week), day: uint32(day), amount: amount }); } } // Updates the baseRate state variable based on time elapsed since the last redemption or debt borrowing operation. function decayBaseRateAndGetBorrowingFee(uint256 _debt) external returns (uint256) { _requireCallerIsBO(); uint256 rate = _decayBaseRate(); return _calcBorrowingFee(_calcBorrowingRate(rate), _debt); } function _decayBaseRate() internal returns (uint256) { uint256 decayedBaseRate = _calcDecayedBaseRate(); baseRate = decayedBaseRate; emit BaseRateUpdated(decayedBaseRate); _updateLastFeeOpTime(); return decayedBaseRate; } function applyPendingRewards(address _borrower) external returns (uint256 coll, uint256 debt) { _requireCallerIsBO(); return _applyPendingRewards(_borrower); } // Add the borrowers's coll and debt rewards earned from redistributions, to their Trove function _applyPendingRewards(address _borrower) internal returns (uint256 coll, uint256 debt) { Trove storage t = Troves[_borrower]; if (t.status == Status.active) { uint256 troveInterestIndex = t.activeInterestIndex; uint256 supply = totalActiveDebt; uint256 currentInterestIndex = _accrueActiveInterests(); debt = t.debt; uint256 prevDebt = debt; coll = t.coll; // We accrued interests for this trove if not already updated if (troveInterestIndex < currentInterestIndex) { debt = (debt * currentInterestIndex) / troveInterestIndex; t.activeInterestIndex = currentInterestIndex; } if (rewardSnapshots[_borrower].collateral < L_collateral) { // Compute pending rewards (uint256 pendingCollateralReward, uint256 pendingDebtReward) = getPendingCollAndDebtRewards(_borrower); // Apply pending rewards to trove's state coll = coll + pendingCollateralReward; t.coll = coll; debt = debt + pendingDebtReward; _updateTroveRewardSnapshots(_borrower); _movePendingTroveRewardsToActiveBalance(pendingDebtReward, pendingCollateralReward); } if (prevDebt != debt) { t.debt = debt; } _updateIntegrals(_borrower, prevDebt, supply); } return (coll, debt); } function _updateTroveRewardSnapshots(address _borrower) internal { uint256 L_collateralCached = L_collateral; uint256 L_debtCached = L_debt; rewardSnapshots[_borrower] = RewardSnapshot(L_collateralCached, L_debtCached); emit TroveSnapshotsUpdated(L_collateralCached, L_debtCached); } // Remove borrower's stake from the totalStakes sum, and set their stake to 0 function _removeStake(address _borrower) internal { uint256 stake = Troves[_borrower].stake; totalStakes = totalStakes - stake; Troves[_borrower].stake = 0; } // Update borrower's stake based on their latest collateral value function _updateStakeAndTotalStakes(Trove storage t) internal returns (uint256) { uint256 newStake = _computeNewStake(t.coll); uint256 oldStake = t.stake; t.stake = newStake; uint256 newTotalStakes = totalStakes - oldStake + newStake; totalStakes = newTotalStakes; emit TotalStakesUpdated(newTotalStakes); return newStake; } // Calculate a new stake based on the snapshots of the totalStakes and totalCollateral taken at the last liquidation function _computeNewStake(uint256 _coll) internal view returns (uint256) { uint256 stake; uint256 totalCollateralSnapshotCached = totalCollateralSnapshot; if (totalCollateralSnapshotCached == 0) { stake = _coll; } else { /* * The following assert() holds true because: * - The system always contains >= 1 trove * - When we close or liquidate a trove, we redistribute the pending rewards, so if all troves were closed/liquidated, * rewards would’ve been emptied and totalCollateralSnapshot would be zero too. */ uint256 totalStakesSnapshotCached = totalStakesSnapshot; assert(totalStakesSnapshotCached > 0); stake = (_coll * totalStakesSnapshotCached) / totalCollateralSnapshotCached; } return stake; } // --- Liquidation Functions --- function closeTroveByLiquidation(address _borrower) external { _requireCallerIsLM(); uint256 debtBefore = Troves[_borrower].debt; _removeStake(_borrower); _closeTrove(_borrower, Status.closedByLiquidation); _updateIntegralForAccount(_borrower, debtBefore, rewardIntegral); emit TroveUpdated(_borrower, 0, 0, 0, TroveManagerOperation.liquidate); } function movePendingTroveRewardsToActiveBalances(uint256 _debt, uint256 _collateral) external { _requireCallerIsLM(); _movePendingTroveRewardsToActiveBalance(_debt, _collateral); } function _movePendingTroveRewardsToActiveBalance(uint256 _debt, uint256 _collateral) internal { defaultedDebt -= _debt; totalActiveDebt += _debt; defaultedCollateral -= _collateral; totalActiveCollateral += _collateral; } function addCollateralSurplus(address borrower, uint256 collSurplus) external { _requireCallerIsLM(); surplusBalances[borrower] += collSurplus; } function finalizeLiquidation( address _liquidator, uint256 _debt, uint256 _coll, uint256 _collSurplus, uint256 _debtGasComp, uint256 _collGasComp ) external { _requireCallerIsLM(); // redistribute debt and collateral _redistributeDebtAndColl(_debt, _coll); uint256 _activeColl = totalActiveCollateral; if (_collSurplus > 0) { _activeColl -= _collSurplus; totalActiveCollateral = _activeColl; } // update system snapshos totalStakesSnapshot = totalStakes; totalCollateralSnapshot = _activeColl - _collGasComp + defaultedCollateral; emit SystemSnapshotsUpdated(totalStakesSnapshot, totalCollateralSnapshot); // send gas compensation debtToken.returnFromPool(gasPoolAddress, _liquidator, _debtGasComp); _sendCollateral(_liquidator, _collGasComp); } function _redistributeDebtAndColl(uint256 _debt, uint256 _coll) internal { if (_debt == 0) { return; } /* * Add distributed coll and debt rewards-per-unit-staked to the running totals. Division uses a "feedback" * error correction, to keep the cumulative error low in the running totals L_collateral and L_debt: * * 1) Form numerators which compensate for the floor division errors that occurred the last time this * function was called. * 2) Calculate "per-unit-staked" ratios. * 3) Multiply each ratio back by its denominator, to reveal the current floor division error. * 4) Store these errors for use in the next correction when this function is called. * 5) Note: static analysis tools complain about this "division before multiplication", however, it is intended. */ uint256 collateralNumerator = (_coll * DECIMAL_PRECISION) + lastCollateralError_Redistribution; uint256 debtNumerator = (_debt * DECIMAL_PRECISION) + lastDebtError_Redistribution; uint256 totalStakesCached = totalStakes; // Get the per-unit-staked terms uint256 collateralRewardPerUnitStaked = collateralNumerator / totalStakesCached; uint256 debtRewardPerUnitStaked = debtNumerator / totalStakesCached; lastCollateralError_Redistribution = collateralNumerator - (collateralRewardPerUnitStaked * totalStakesCached); lastDebtError_Redistribution = debtNumerator - (debtRewardPerUnitStaked * totalStakesCached); // Add per-unit-staked terms to the running totals uint256 new_L_collateral = L_collateral + collateralRewardPerUnitStaked; uint256 new_L_debt = L_debt + debtRewardPerUnitStaked; L_collateral = new_L_collateral; L_debt = new_L_debt; emit LTermsUpdated(new_L_collateral, new_L_debt); totalActiveDebt -= _debt; defaultedDebt += _debt; defaultedCollateral += _coll; totalActiveCollateral -= _coll; } // --- Trove property setters --- function _sendCollateral(address _account, uint256 _amount) private { if (_amount > 0) { totalActiveCollateral = totalActiveCollateral - _amount; emit CollateralSent(_account, _amount); collateralToken.safeTransfer(_account, _amount); } } function _increaseDebt(address account, uint256 netDebtAmount, uint256 debtAmount) internal { uint256 _newTotalDebt = totalActiveDebt + netDebtAmount; require(_newTotalDebt + defaultedDebt <= maxSystemDebt, "Collateral debt limit reached"); totalActiveDebt = _newTotalDebt; debtToken.mint(account, debtAmount); } function decreaseDebtAndSendCollateral(address account, uint256 debt, uint256 coll) external { _requireCallerIsLM(); _decreaseDebt(account, debt); _sendCollateral(account, coll); } function _decreaseDebt(address account, uint256 amount) internal { debtToken.burn(account, amount); totalActiveDebt = totalActiveDebt - amount; } // --- Balances and interest --- function updateBalances() external { _requireCallerIsLM(); _updateBalances(); } function _updateBalances() private { _updateRewardIntegral(totalActiveDebt); _accrueActiveInterests(); } // This function must be called any time the debt or the interest changes function _accrueActiveInterests() internal returns (uint256) { (uint256 currentInterestIndex, uint256 interestFactor) = _calculateInterestIndex(); if (interestFactor > 0) { uint256 currentDebt = totalActiveDebt; uint256 activeInterests = Math.mulDiv(currentDebt, interestFactor, INTEREST_PRECISION); totalActiveDebt = currentDebt + activeInterests; interestPayable = interestPayable + activeInterests; activeInterestIndex = currentInterestIndex; lastActiveIndexUpdate = block.timestamp; } return currentInterestIndex; } function _calculateInterestIndex() internal view returns (uint256 currentInterestIndex, uint256 interestFactor) { uint256 lastIndexUpdateCached = lastActiveIndexUpdate; // Short circuit if we updated in the current block if (lastIndexUpdateCached == block.timestamp) return (activeInterestIndex, 0); uint256 currentInterest = interestRate; currentInterestIndex = activeInterestIndex; // we need to return this if it's already up to date if (currentInterest > 0) { /* * Calculate the interest accumulated and the new index: * We compound the index and increase the debt accordingly */ uint256 deltaT = block.timestamp - lastIndexUpdateCached; interestFactor = deltaT * currentInterest; currentInterestIndex = currentInterestIndex + Math.mulDiv(currentInterestIndex, interestFactor, INTEREST_PRECISION); } } // --- Requires --- function _requireCallerIsBO() internal view { require(msg.sender == borrowerOperationsAddress, "Caller not BO"); } function _requireCallerIsLM() internal view { require(msg.sender == liquidationManager, "Not Liquidation Manager"); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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); /** * @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 `from` to `to` 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 from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` 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: * * - `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 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current 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. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; /* * Base contract for TroveManager, BorrowerOperations and StabilityPool. Contains global system constants and * common functions. */ contract PrismaBase { uint256 public constant DECIMAL_PRECISION = 1e18; // Critical system collateral ratio. If the system's total collateral ratio (TCR) falls below the CCR, Recovery Mode is triggered. uint256 public constant CCR = 1500000000000000000; // 150% // Amount of debt to be locked in gas pool on opening troves uint256 public immutable DEBT_GAS_COMPENSATION; uint256 public constant PERCENT_DIVISOR = 200; // dividing by 200 yields 0.5% constructor(uint256 _gasCompensation) { DEBT_GAS_COMPENSATION = _gasCompensation; } // --- Gas compensation functions --- // Returns the composite debt (drawn debt + gas compensation) of a trove, for the purpose of ICR calculation function _getCompositeDebt(uint256 _debt) internal view returns (uint256) { return _debt + DEBT_GAS_COMPENSATION; } function _getNetDebt(uint256 _debt) internal view returns (uint256) { return _debt - DEBT_GAS_COMPENSATION; } // Return the amount of collateral to be drawn from a trove's collateral and sent as gas compensation. function _getCollGasCompensation(uint256 _entireColl) internal pure returns (uint256) { return _entireColl / PERCENT_DIVISOR; } function _requireUserAcceptsFee(uint256 _fee, uint256 _amount, uint256 _maxFeePercentage) internal pure { uint256 feePercentage = (_fee * DECIMAL_PRECISION) / _amount; require(feePercentage <= _maxFeePercentage, "Fee exceeded provided maximum"); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; library PrismaMath { uint256 internal constant DECIMAL_PRECISION = 1e18; /* Precision for Nominal ICR (independent of price). Rationale for the value: * * - Making it “too high” could lead to overflows. * - Making it “too low” could lead to an ICR equal to zero, due to truncation from Solidity floor division. * * This value of 1e20 is chosen for safety: the NICR will only overflow for numerator > ~1e39, * and will only truncate to 0 if the denominator is at least 1e20 times greater than the numerator. * */ uint256 internal constant NICR_PRECISION = 1e20; function _min(uint256 _a, uint256 _b) internal pure returns (uint256) { return (_a < _b) ? _a : _b; } function _max(uint256 _a, uint256 _b) internal pure returns (uint256) { 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(uint256 x, uint256 y) internal pure returns (uint256 decProd) { uint256 prod_xy = x * y; decProd = (prod_xy + (DECIMAL_PRECISION / 2)) / 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(uint256 _base, uint256 _minutes) internal pure returns (uint256) { if (_minutes > 525600000) { _minutes = 525600000; } // cap to avoid overflow if (_minutes == 0) { return DECIMAL_PRECISION; } uint256 y = DECIMAL_PRECISION; uint256 x = _base; uint256 n = _minutes; // Exponentiation-by-squaring while (n > 1) { if (n % 2 == 0) { x = decMul(x, x); n = n / 2; } else { // if (n % 2 != 0) y = decMul(x, y); x = decMul(x, x); n = (n - 1) / 2; } } return decMul(x, y); } function _getAbsoluteDifference(uint256 _a, uint256 _b) internal pure returns (uint256) { return (_a >= _b) ? _a - _b : _b - _a; } function _computeNominalCR(uint256 _coll, uint256 _debt) internal pure returns (uint256) { if (_debt > 0) { return (_coll * NICR_PRECISION) / _debt; } // 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; } } function _computeCR(uint256 _coll, uint256 _debt, uint256 _price) internal pure returns (uint256) { if (_debt > 0) { uint256 newCollRatio = (_coll * _price) / _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; } } function _computeCR(uint256 _coll, uint256 _debt) internal pure returns (uint256) { if (_debt > 0) { uint256 newCollRatio = (_coll) / _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; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import "../interfaces/IPrismaCore.sol"; /** @title Prisma Ownable @notice Contracts inheriting `PrismaOwnable` have the same owner as `PrismaCore`. The ownership cannot be independently modified or renounced. */ contract PrismaOwnable { IPrismaCore public immutable PRISMA_CORE; constructor(address _prismaCore) { PRISMA_CORE = IPrismaCore(_prismaCore); } modifier onlyOwner() { require(msg.sender == PRISMA_CORE.owner(), "Only owner"); _; } function owner() public view returns (address) { return PRISMA_CORE.owner(); } function guardian() public view returns (address) { return PRISMA_CORE.guardian(); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import "../interfaces/IPrismaCore.sol"; /** @title Prisma System Start Time @dev Provides a unified `startTime` and `getWeek`, used for emissions. */ contract SystemStart { uint256 immutable startTime; constructor(address prismaCore) { startTime = IPrismaCore(prismaCore).startTime(); } function getWeek() public view returns (uint256 week) { return (block.timestamp - startTime) / 1 weeks; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBorrowerOperations { struct Balances { uint256[] collaterals; uint256[] debts; uint256[] prices; } event BorrowingFeePaid(address indexed borrower, uint256 amount); event CollateralConfigured(address troveManager, address collateralToken); event TroveCreated(address indexed _borrower, uint256 arrayIndex); event TroveManagerRemoved(address troveManager); event TroveUpdated(address indexed _borrower, uint256 _debt, uint256 _coll, uint256 stake, uint8 operation); function addColl( address troveManager, address account, uint256 _collateralAmount, address _upperHint, address _lowerHint ) external; function adjustTrove( address troveManager, address account, uint256 _maxFeePercentage, uint256 _collDeposit, uint256 _collWithdrawal, uint256 _debtChange, bool _isDebtIncrease, address _upperHint, address _lowerHint ) external; function closeTrove(address troveManager, address account) external; function configureCollateral(address troveManager, address collateralToken) external; function fetchBalances() external returns (Balances memory balances); function getGlobalSystemBalances() external returns (uint256 totalPricedCollateral, uint256 totalDebt); function getTCR() external returns (uint256 globalTotalCollateralRatio); function openTrove( address troveManager, address account, uint256 _maxFeePercentage, uint256 _collateralAmount, uint256 _debtAmount, address _upperHint, address _lowerHint ) external; function removeTroveManager(address troveManager) external; function repayDebt( address troveManager, address account, uint256 _debtAmount, address _upperHint, address _lowerHint ) external; function setDelegateApproval(address _delegate, bool _isApproved) external; function setMinNetDebt(uint256 _minNetDebt) external; function withdrawColl( address troveManager, address account, uint256 _collWithdrawal, address _upperHint, address _lowerHint ) external; function withdrawDebt( address troveManager, address account, uint256 _maxFeePercentage, uint256 _debtAmount, address _upperHint, address _lowerHint ) external; function checkRecoveryMode(uint256 TCR) external pure returns (bool); function CCR() external view returns (uint256); function DEBT_GAS_COMPENSATION() external view returns (uint256); function DECIMAL_PRECISION() external view returns (uint256); function PERCENT_DIVISOR() external view returns (uint256); function PRISMA_CORE() external view returns (address); function _100pct() external view returns (uint256); function debtToken() external view returns (address); function factory() external view returns (address); function getCompositeDebt(uint256 _debt) external view returns (uint256); function guardian() external view returns (address); function isApprovedDelegate(address owner, address caller) external view returns (bool isApproved); function minNetDebt() external view returns (uint256); function owner() external view returns (address); function troveManagersData(address) external view returns (address collateralToken, uint16 index); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IDebtToken { event Approval(address indexed owner, address indexed spender, uint256 value); event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event ReceiveFromChain(uint16 indexed _srcChainId, address indexed _to, uint256 _amount); event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash); event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes _toAddress, uint256 _amount); event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint256 _minDstGas); event SetPrecrime(address precrime); event SetTrustedRemote(uint16 _remoteChainId, bytes _path); event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress); event SetUseCustomAdapterParams(bool _useCustomAdapterParams); event Transfer(address indexed from, address indexed to, uint256 value); function approve(address spender, uint256 amount) external returns (bool); function burn(address _account, uint256 _amount) external; function burnWithGasCompensation(address _account, uint256 _amount) external returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); function enableTroveManager(address _troveManager) external; function flashLoan(address receiver, address token, uint256 amount, bytes calldata data) external returns (bool); function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external; function increaseAllowance(address spender, uint256 addedValue) external returns (bool); function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external; function mint(address _account, uint256 _amount) external; function mintWithGasCompensation(address _account, uint256 _amount) external returns (bool); function nonblockingLzReceive( uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload ) external; function permit( address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function renounceOwnership() external; function returnFromPool(address _poolAddress, address _receiver, uint256 _amount) external; function sendToSP(address _sender, uint256 _amount) external; function setConfig(uint16 _version, uint16 _chainId, uint256 _configType, bytes calldata _config) external; function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint256 _minGas) external; function setPayloadSizeLimit(uint16 _dstChainId, uint256 _size) external; function setPrecrime(address _precrime) external; function setReceiveVersion(uint16 _version) external; function setSendVersion(uint16 _version) external; function setTrustedRemote(uint16 _srcChainId, bytes calldata _path) external; function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external; function setUseCustomAdapterParams(bool _useCustomAdapterParams) external; function transfer(address recipient, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); function transferOwnership(address newOwner) external; function retryMessage( uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload ) external payable; function sendFrom( address _from, uint16 _dstChainId, bytes calldata _toAddress, uint256 _amount, address _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams ) external payable; function DEBT_GAS_COMPENSATION() external view returns (uint256); function DEFAULT_PAYLOAD_SIZE_LIMIT() external view returns (uint256); function FLASH_LOAN_FEE() external view returns (uint256); function NO_EXTRA_GAS() external view returns (uint256); function PT_SEND() external view returns (uint16); function allowance(address owner, address spender) external view returns (uint256); function balanceOf(address account) external view returns (uint256); function borrowerOperationsAddress() external view returns (address); function circulatingSupply() external view returns (uint256); function decimals() external view returns (uint8); function domainSeparator() external view returns (bytes32); function estimateSendFee( uint16 _dstChainId, bytes calldata _toAddress, uint256 _amount, bool _useZro, bytes calldata _adapterParams ) external view returns (uint256 nativeFee, uint256 zroFee); function factory() external view returns (address); function failedMessages(uint16, bytes calldata, uint64) external view returns (bytes32); function flashFee(address token, uint256 amount) external view returns (uint256); function gasPool() external view returns (address); function getConfig( uint16 _version, uint16 _chainId, address, uint256 _configType ) external view returns (bytes memory); function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory); function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool); function lzEndpoint() external view returns (address); function maxFlashLoan(address token) external view returns (uint256); function minDstGasLookup(uint16, uint16) external view returns (uint256); function name() external view returns (string memory); function nonces(address owner) external view returns (uint256); function owner() external view returns (address); function payloadSizeLimitLookup(uint16) external view returns (uint256); function permitTypeHash() external view returns (bytes32); function precrime() external view returns (address); function stabilityPoolAddress() external view returns (address); function supportsInterface(bytes4 interfaceId) external view returns (bool); function symbol() external view returns (string memory); function token() external view returns (address); function totalSupply() external view returns (uint256); function troveManager(address) external view returns (bool); function trustedRemoteLookup(uint16) external view returns (bytes memory); function useCustomAdapterParams() external view returns (bool); function version() external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPriceFeed { event NewOracleRegistered(address token, address chainlinkAggregator, bool isEthIndexed); event PriceFeedStatusUpdated(address token, address oracle, bool isWorking); event PriceRecordUpdated(address indexed token, uint256 _price); function fetchPrice(address _token) external returns (uint256); function setOracle( address _token, address _chainlinkOracle, bytes4 sharePriceSignature, uint8 sharePriceDecimals, bool _isEthIndexed ) external; function MAX_PRICE_DEVIATION_FROM_PREVIOUS_ROUND() external view returns (uint256); function PRISMA_CORE() external view returns (address); function RESPONSE_TIMEOUT() external view returns (uint256); function TARGET_DIGITS() external view returns (uint256); function guardian() external view returns (address); function oracleRecords( address ) external view returns ( address chainLinkOracle, uint8 decimals, bytes4 sharePriceSignature, uint8 sharePriceDecimals, bool isFeedWorking, bool isEthIndexed ); function owner() external view returns (address); function priceRecords( address ) external view returns (uint96 scaledPrice, uint32 timestamp, uint32 lastUpdated, uint80 roundId); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; struct ReedemedTrove { address account; uint256 debtLot; uint256 collateralLot; } interface ITroveRedemptionsCallback { /** * @notice Function called after redemptions are executed in a Trove Manager * @dev This functions should be called EXCLUSIVELY by a registered Trove Manger * @param redemptions Values related to redeemed troves */ function onRedemptions(ReedemedTrove[] memory redemptions) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPrismaCore { event FeeReceiverSet(address feeReceiver); event GuardianSet(address guardian); event NewOwnerAccepted(address oldOwner, address owner); event NewOwnerCommitted(address owner, address pendingOwner, uint256 deadline); event NewOwnerRevoked(address owner, address revokedOwner); event Paused(); event PriceFeedSet(address priceFeed); event Unpaused(); function acceptTransferOwnership() external; function commitTransferOwnership(address newOwner) external; function revokeTransferOwnership() external; function setFeeReceiver(address _feeReceiver) external; function setGuardian(address _guardian) external; function setPaused(bool _paused) external; function setPriceFeed(address _priceFeed) external; function OWNERSHIP_TRANSFER_DELAY() external view returns (uint256); function feeReceiver() external view returns (address); function guardian() external view returns (address); function owner() external view returns (address); function ownershipTransferDeadline() external view returns (uint256); function paused() external view returns (bool); function pendingOwner() external view returns (address); function priceFeed() external view returns (address); function startTime() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ISortedTroves { event NodeAdded(address _id, uint256 _NICR); event NodeRemoved(address _id); function insert(address _id, uint256 _NICR, address _prevId, address _nextId) external; function reInsert(address _id, uint256 _newNICR, address _prevId, address _nextId) external; function remove(address _id) external; function setAddresses(address _troveManagerAddress) external; function contains(address _id) external view returns (bool); function data() external view returns (address head, address tail, uint256 size); function findInsertPosition( uint256 _NICR, address _prevId, address _nextId ) external view returns (address, address); 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 getSize() external view returns (uint256); function isEmpty() external view returns (bool); function troveManager() external view returns (address); function validInsertPosition(uint256 _NICR, address _prevId, address _nextId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPrismaVault { struct InitialAllowance { address receiver; uint256 amount; } event BoostCalculatorSet(address boostCalculator); event BoostDelegationSet(address indexed boostDelegate, bool isEnabled, uint256 feePct, address callback); event EmissionScheduleSet(address emissionScheduler); event IncreasedAllocation(address indexed receiver, uint256 increasedAmount); event NewReceiverRegistered(address receiver, uint256 id); event ReceiverIsActiveStatusModified(uint256 indexed id, bool isActive); event UnallocatedSupplyIncreased(uint256 increasedAmount, uint256 unallocatedTotal); event UnallocatedSupplyReduced(uint256 reducedAmount, uint256 unallocatedTotal); function allocateNewEmissions(uint256 id) external returns (uint256); function batchClaimRewards( address receiver, address boostDelegate, address[] calldata rewardContracts, uint256 maxFeePct ) external returns (bool); function increaseUnallocatedSupply(uint256 amount) external returns (bool); function registerReceiver(address receiver, uint256 count) external returns (bool); function setBoostCalculator(address _boostCalculator) external returns (bool); function setBoostDelegationParams(bool isEnabled, uint256 feePct, address callback) external returns (bool); function setEmissionSchedule(address _emissionSchedule) external returns (bool); function setInitialParameters( address _emissionSchedule, address _boostCalculator, uint256 totalSupply, uint64 initialLockWeeks, uint128[] calldata _fixedInitialAmounts, InitialAllowance[] calldata initialAllowances ) external; function setReceiverIsActive(uint256 id, bool isActive) external returns (bool); function transferAllocatedTokens(address claimant, address receiver, uint256 amount) external returns (bool); function transferTokens(address token, address receiver, uint256 amount) external returns (bool); function PRISMA_CORE() external view returns (address); function allocated(address) external view returns (uint256); function boostCalculator() external view returns (address); function boostDelegation(address) external view returns (bool isEnabled, uint16 feePct, address callback); function claimableRewardAfterBoost( address account, address receiver, address boostDelegate, address rewardContract ) external view returns (uint256 adjustedAmount, uint256 feeToDelegate); function emissionSchedule() external view returns (address); function getClaimableWithBoost(address claimant) external view returns (uint256 maxBoosted, uint256 boosted); function getWeek() external view returns (uint256 week); function guardian() external view returns (address); function idToReceiver(uint256) external view returns (address account, bool isActive); function lockWeeks() external view returns (uint64); function locker() external view returns (address); function owner() external view returns (address); function claimableBoostDelegationFees(address claimant) external view returns (uint256 amount); function prismaToken() external view returns (address); function receiverUpdatedWeek(uint256) external view returns (uint16); function totalUpdateWeek() external view returns (uint64); function unallocatedTotal() external view returns (uint128); function voter() external view returns (address); function weeklyEmissions(uint256) external view returns (uint128); }
{ "evmVersion": "paris", "libraries": {}, "metadata": { "bytecodeHash": "none", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 10 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_prismaCore","type":"address"},{"internalType":"address","name":"_gasPoolAddress","type":"address"},{"internalType":"address","name":"_debtTokenAddress","type":"address"},{"internalType":"address","name":"_borrowerOperationsAddress","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_liquidationManager","type":"address"},{"internalType":"uint256","name":"_gasCompensation","type":"uint256"},{"internalType":"uint256","name":"_bootstrapPeriod","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_baseRate","type":"uint256"}],"name":"BaseRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"CollateralSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_L_collateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_L_debt","type":"uint256"}],"name":"LTermsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_lastFeeOpTime","type":"uint256"}],"name":"LastFeeOpTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_attemptedDebtAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_actualDebtAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_collateralSent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_collateralFee","type":"uint256"}],"name":"Redemption","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"redemptionFeesRebate","type":"uint16"}],"name":"RedemptionFeesRebateSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimed","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_totalStakesSnapshot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalCollateralSnapshot","type":"uint256"}],"name":"SystemSnapshotsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newTotalStakes","type":"uint256"}],"name":"TotalStakesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_newIndex","type":"uint256"}],"name":"TroveIndexUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_L_collateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_L_debt","type":"uint256"}],"name":"TroveSnapshotsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_debt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_coll","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_stake","type":"uint256"},{"indexed":false,"internalType":"enum TroveManager.TroveManagerOperation","name":"_operation","type":"uint8"}],"name":"TroveUpdated","type":"event"},{"inputs":[],"name":"CCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEBT_GAS_COMPENSATION","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":"L_collateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L_debt","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":"PERCENT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRISMA_CORE","outputs":[{"internalType":"contract IPrismaCore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUNSETTING_INTEREST_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"Troves","outputs":[{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"coll","type":"uint256"},{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"enum TroveManager.Status","name":"status","type":"uint8"},{"internalType":"uint128","name":"arrayIndex","type":"uint128"},{"internalType":"uint256","name":"activeInterestIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accountLatestMint","outputs":[{"internalType":"uint32","name":"amount","type":"uint32"},{"internalType":"uint32","name":"week","type":"uint32"},{"internalType":"uint32","name":"day","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeInterestIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"collSurplus","type":"uint256"}],"name":"addCollateralSurplus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"applyPendingRewards","outputs":[{"internalType":"uint256","name":"coll","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"baseRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bootstrapPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowerOperationsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowingFeeFloor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"claimCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"claimReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"claimableReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"collAmount","type":"uint256"},{"internalType":"uint256","name":"debtAmount","type":"uint256"}],"name":"closeTrove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"closeTroveByLiquidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectInterests","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dailyMintReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtToken","outputs":[{"internalType":"contract IDebtToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debt","type":"uint256"}],"name":"decayBaseRateAndGetBorrowingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"coll","type":"uint256"}],"name":"decreaseDebtAndSendCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultedCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultedDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emissionId","outputs":[{"internalType":"uint16","name":"debt","type":"uint16"},{"internalType":"uint16","name":"minting","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fetchPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_liquidator","type":"address"},{"internalType":"uint256","name":"_debt","type":"uint256"},{"internalType":"uint256","name":"_coll","type":"uint256"},{"internalType":"uint256","name":"_collSurplus","type":"uint256"},{"internalType":"uint256","name":"_debtGasComp","type":"uint256"},{"internalType":"uint256","name":"_collGasComp","type":"uint256"}],"name":"finalizeLiquidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debt","type":"uint256"}],"name":"getBorrowingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debt","type":"uint256"}],"name":"getBorrowingFeeWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBorrowingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBorrowingRateWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"getCurrentICR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getEntireDebtAndColl","outputs":[{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"coll","type":"uint256"},{"internalType":"uint256","name":"pendingDebtReward","type":"uint256"},{"internalType":"uint256","name":"pendingCollateralReward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntireSystemBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getEntireSystemColl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntireSystemDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInterestRateInBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getNominalICR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getPendingCollAndDebtRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralDrawn","type":"uint256"}],"name":"getRedemptionFeeWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedemptionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedemptionRateWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalActiveCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalActiveDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"week","type":"uint256"}],"name":"getTotalMints","outputs":[{"internalType":"uint32[7]","name":"","type":"uint32[7]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getTroveCollAndDebt","outputs":[{"internalType":"uint256","name":"coll","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getTroveFromTroveOwnersArray","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTroveOwnersCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getTroveStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getTroveStatus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWeek","outputs":[{"internalType":"uint256","name":"week","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWeekAndDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"hasPendingRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestPayable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastActiveIndexUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastCollateralError_Redistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastDebtError_Redistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastFeeOperationTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdate","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidationManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBorrowingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRedemptionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSystemDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minuteDecayFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debt","type":"uint256"},{"internalType":"uint256","name":"_collateral","type":"uint256"}],"name":"movePendingTroveRewardsToActiveBalances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_assignedIds","type":"uint256[]"}],"name":"notifyRegisteredId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_collateralAmount","type":"uint256"},{"internalType":"uint256","name":"_compositeDebt","type":"uint256"},{"internalType":"uint256","name":"NICR","type":"uint256"},{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"},{"internalType":"bool","name":"_isRecoveryMode","type":"bool"}],"name":"openTrove","outputs":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"arrayIndex","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debtAmount","type":"uint256"},{"internalType":"address","name":"_firstRedemptionHint","type":"address"},{"internalType":"address","name":"_upperPartialRedemptionHint","type":"address"},{"internalType":"address","name":"_lowerPartialRedemptionHint","type":"address"},{"internalType":"uint256","name":"_partialRedemptionHintNICR","type":"uint256"},{"internalType":"uint256","name":"_maxIterations","type":"uint256"},{"internalType":"uint256","name":"_maxFeePercentage","type":"uint256"}],"name":"redeemCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redemptionFeeFloor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionFeesRebate","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardIntegral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardIntegralFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardSnapshots","outputs":[{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_priceFeedAddress","type":"address"},{"internalType":"address","name":"_sortedTrovesAddress","type":"address"},{"internalType":"address","name":"_collateralToken","type":"address"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minuteDecayFactor","type":"uint256"},{"internalType":"uint256","name":"_redemptionFeeFloor","type":"uint256"},{"internalType":"uint256","name":"_maxRedemptionFee","type":"uint256"},{"internalType":"uint256","name":"_borrowingFeeFloor","type":"uint256"},{"internalType":"uint256","name":"_maxBorrowingFee","type":"uint256"},{"internalType":"uint256","name":"_interestRateInBPS","type":"uint256"},{"internalType":"uint256","name":"_maxSystemDebt","type":"uint256"},{"internalType":"uint256","name":"_MCR","type":"uint256"}],"name":"setParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_priceFeedAddress","type":"address"}],"name":"setPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_redemptionFeesRebate","type":"uint16"}],"name":"setRedemptionFeesRebate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITroveRedemptionsCallback","name":"redemptionsCallback","type":"address"}],"name":"setRedemptionsCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sortedTroves","outputs":[{"internalType":"contract ISortedTroves","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startSunset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sunsetting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"surplusBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"systemDeploymentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCollateralSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakesSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateBalances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isRecoveryMode","type":"bool"},{"internalType":"bool","name":"_isDebtIncrease","type":"bool"},{"internalType":"uint256","name":"_debtChange","type":"uint256"},{"internalType":"uint256","name":"_netDebtChange","type":"uint256"},{"internalType":"bool","name":"_isCollIncrease","type":"bool"},{"internalType":"uint256","name":"_collChange","type":"uint256"},{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"updateTroveFromAdjustment","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IPrismaVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"claimant","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"vaultClaimReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101a06040523480156200001257600080fd5b50604051620062c3380380620062c3833981016040819052620000359162000103565b60808290526001600160a01b03881660a0819052604080516378e9792560e01b815290518a92916378e979259160048083019260209291908290030181865afa15801562000087573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ad919062000198565b60c052506001600160a01b0396871661012052948616610140525091841660e052831661016052909116610100526101805250620001b2565b80516001600160a01b0381168114620000fe57600080fd5b919050565b600080600080600080600080610100898b0312156200012157600080fd5b6200012c89620000e6565b97506200013c60208a01620000e6565b96506200014c60408a01620000e6565b95506200015c60608a01620000e6565b94506200016c60808a01620000e6565b93506200017c60a08a01620000e6565b60c08a015160e0909a0151989b979a5095989497939692505050565b600060208284031215620001ab57600080fd5b5051919050565b60805160a05160c05160e0516101005161012051610140516101605161018051615fb262000311600039600081816109eb01526123c8015260008181610cdd0152818161185601528181613009015281816134aa015281816151fb015261533d015260008181610cb601528181611cfd0152818161258901528181612c51015281816133ed01528181614153015281816141d9015261500501526000818161341a015261503201526000818161058401526136cf015260008181610a8001528181612451015281816134f501526145e3015260008181610e2a01528181611e9b0152818161515b01526151a3015260008181610b3f01528181610d2901528181610e9f01528181610f9f015281816114c5015281816119db01528181611b5501528181611d2c01528181611ed60152612b470152600081816106ce01528181614481015281816144fe0152818161453d01526150f30152615fb26000f3fe608060405234801561001057600080fd5b50600436106104b35760003560e01c80638235b284116102765780638235b284146108d1578063874d6d81146108e4578063887105d3146108ec5780638bbb1de8146108f45780638da5cb5b146108fd5780638e415ea81461090557806391245f9f146109185780639484fb8e1461092157806396660b181461092e57806396d711ff146109375780639ed7254214610940578063a20baee614610949578063a25fc26414610958578063a5713dcd1461097a578063ae9187541461099a578063b0d8e181146109ad578063b2016bd4146109c0578063b2f29d7b146109d3578063b354f6df146109e6578063b4997a1f14610a0d578063b49c6f8214610a16578063b7f8cf9b14610a7b578063b91af97c14610aa2578063bc006c3814610ac5578063bcd3752614610ace578063be2c377b14610ae1578063bf9befb114610aea578063c046371114610af3578063c52861f214610b1f578063c9a4cbf114610b27578063cc9641a814610b3a578063d128080c14610b61578063d12ae84114610b69578063d279c19114610b7c578063d293c71014610b8f578063d30612e114610ba2578063d380a37c14610baa578063d38b055814610bb3578063d5b3563514610bbc578063d9a7244414610bcf578063e0b7a2d814610be2578063e2ac77b014610bf5578063e47cf0c314610c08578063e9186c9414610c11578063e950342514610c24578063ea23a27a14610c37578063eb3007fd14610c4a578063ebe2b12b14610c5d578063ec38a05d14610c74578063f058203814610c96578063f36b242514610ca9578063f8d8989814610cb1578063fbfa77cf14610cd857600080fd5b806301c799fc146104b857806309c8bb14146104e05780630b076557146104f55780630f8490df1461051d5780630fdb11cf146105255780631289fefb1461053b5780631673c79a1461054357806316c38b3c1461056c5780631ef3a04c1461057f5780631f68f20a146105b357806320d17d7b146105bc57806321e37801146105c557806325019ee9146105d85780632879e488146105eb5780632b11551a146105f35780632b2b2bac146105fb5780632d587e101461060e5780632f5c83a81461061757806331c7a2611461062057806333d53b591461062957806334ba3c7114610632578063363bf964146106455780634056d9fc14610658578063452a9320146106615780634763637114610669578063477d66cf1461069c5780634820fe56146106af5780634870dd9a146106b757806349eefeee146106bf5780634ba4a28b146106c95780634cb653b7146106f05780635733d58f146107035780635bbe8aad146107125780635c975abb14610735578063616325ae14610747578063631203b01461075a57806364cee2601461076d57806366ca4a211461079b5780636ef64338146107a35780636f3fe40414610808578063720fbe2c14610810578063724e78da14610819578063741bef1a1461082c578063789c6b931461083f578063794e572414610852578063795d26c31461085b5780637a83a34e146108635780637b0a47ee1461086b5780637c3a00fd146108965780637e95d6641461089f578063807d138d146108a85780638140d077146108b1575b600080fd5b6104c0610cff565b604080519384526020840192909252908201526060015b60405180910390f35b6104f36104ee366004615643565b610d27565b005b610508610503366004615643565b610e04565b604080519283526020830191909152016104d7565b610508610e21565b61052d610e8b565b6040519081526020016104d7565b6104f3610f9d565b610508610551366004615643565b62020024602052600090815260409020805460019091015482565b6104f361057a36600461566e565b6110a9565b6105a67f000000000000000000000000000000000000000000000000000000000000000081565b6040516104d7919061568b565b61052d60105481565b61052d601d5481565b61052d6105d3366004615643565b611146565b6104f36105e6366004615643565b61117e565b61052d6111fe565b61052d61123a565b610508610609366004615643565b611247565b61052d600d5481565b61052d600a5481565b61052d60085481565b61052d60155481565b6104f361064036600461569f565b611260565b6104f36106533660046156f4565b61144a565b61052d60095481565b6105a66114c1565b6003546106819061ffff808216916201000090041682565b6040805161ffff9384168152929091166020830152016104d7565b61052d6106aa36600461573f565b611545565b60195461052d565b61052d60c881565b620200255461052d565b61052d7f000000000000000000000000000000000000000000000000000000000000000081565b6105086106fe366004615758565b611558565b61052d6714d1120d7b16000081565b6107256107203660046157d3565b611849565b60405190151581526020016104d7565b600f5461072590610100900460ff1681565b6104f3610755366004615847565b6119d9565b61052d61076836600461573f565b611b22565b61052d61077b366004615643565b6001600160a01b0316600090815262020022602052604090206002015490565b61052d611b2f565b6107f66107b1366004615643565b62020022602052600090815260409020805460018201546002830154600384015460049094015492939192909160ff8116916101009091046001600160801b03169086565b6040516104d79695949392919061589f565b6104f3611b41565b61052d600e5481565b6104f3610827366004615643565b611b53565b6000546105a6906001600160a01b031681565b6104f361084d3660046158e3565b611c27565b61052d60045481565b61052d611c62565b6104f3611cb6565b601f5461087e906001600160801b031681565b6040516001600160801b0390911681526020016104d7565b61052d600b5481565b61052d60065481565b61052d60135481565b61052d6108bf366004615643565b60216020526000908152604090205481565b6104f36108df366004615643565b611e04565b61052d611e90565b61052d611ec0565b61052d600c5481565b6105a6611ed2565b6104c061091336600461590f565b611f32565b61052d60075481565b600f546107259060ff1681565b61052d601b5481565b61052d60145481565b61052d60185481565b61052d670de0b6b3a764000081565b601f5461096d90600160c01b900461ffff1681565b6040516104d791906159c4565b61098d61098836600461573f565b6121a2565b6040516104d791906159d3565b6002546105a6906001600160a01b031681565b61052d6109bb366004615643565b612221565b6001546105a6906001600160a01b031681565b61052d6109e136600461573f565b612248565b61052d7f000000000000000000000000000000000000000000000000000000000000000081565b61052d601e5481565b610a54610a24366004615643565b620200216020526000908152604090205463ffffffff80821691600160201b8104821691600160401b9091041683565b6040805163ffffffff948516815292841660208401529216918101919091526060016104d7565b6105a67f000000000000000000000000000000000000000000000000000000000000000081565b610ab5610ab0366004615643565b612277565b6040516104d79493929190615a0a565b61052d60055481565b6104f3610adc366004615a25565b6122ff565b61052d601c5481565b61052d60125481565b601f54610b0a90600160801b900463ffffffff1681565b60405163ffffffff90911681526020016104d7565b61052d612d83565b6104f3610b35366004615a93565b612d95565b6105a67f000000000000000000000000000000000000000000000000000000000000000081565b61052d612e78565b610508610b77366004615643565b612ebe565b61052d610b8a366004615643565b612fde565b61052d610b9d3660046158e3565b6130cd565b61052d6130f6565b61052d60115481565b61052d60175481565b61052d610bca36600461573f565b61312a565b6105a6610bdd36600461573f565b61313d565b61052d610bf036600461573f565b61316f565b610725610c03366004615643565b613187565b61052d60165481565b6104f3610c1f366004615ad9565b6131ee565b61052d610c32366004615643565b61320f565b6104f3610c45366004615b0e565b613346565b6104f3610c58366004615b5a565b61348b565b601f54610b0a90600160a01b900463ffffffff1681565b61052d610c82366004615643565b620200236020526000908152604090205481565b61052d610ca4366004615b7c565b61349d565b61052d6134dd565b6105a67f000000000000000000000000000000000000000000000000000000000000000081565b6105a67f000000000000000000000000000000000000000000000000000000000000000081565b6000806000610d0c611ec0565b610d14611c62565b610d1c610e8b565b925092509250909192565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190615bb5565b6001600160a01b0316336001600160a01b031614610de25760405162461bcd60e51b8152600401610dd990615bd2565b60405180910390fd5b602080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610e0f6134ea565b610e1883613552565b91509150915091565b60008080610e4f7f000000000000000000000000000000000000000000000000000000000000000042615c0c565b90506000610e6062093a8083615c35565b9050600062015180610e7562093a8085615c49565b610e7f9190615c35565b91959194509092505050565b600080546001600160a01b031680610f22577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663741bef1a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610efb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1f9190615bb5565b90505b600154604051635670bcc760e11b81526001600160a01b038381169263ace1798e92610f54929091169060040161568b565b6020604051808303816000875af1158015610f73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f979190615c5d565b91505090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101f9190615bb5565b6001600160a01b0316336001600160a01b03161461104f5760405162461bcd60e51b8152600401610dd990615bd2565b600f805460ff19166001179055611064613660565b506110756301e13380612710615c76565b61108c676765c793fa10079d601b1b611388615c76565b6110969190615c35565b600b5542600d5560006006819055600a55565b8080156110ce57506110b96114c1565b6001600160a01b0316336001600160a01b0316145b806110f157506110dc611ed2565b6001600160a01b0316336001600160a01b0316145b61112c5760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610dd9565b600f80549115156101000261ff0019909216919091179055565b6001600160a01b038116600090815262020022602052604081206003015460ff1660048111156111785761117861586b565b92915050565b6111866136c4565b6001600160a01b03811660009081526202002260205260409020546111aa82613736565b6111b5826003613785565b6111c28282601e54613a31565b816001600160a01b0316600080516020615f66833981519152600080600060036040516111f29493929190615c8d565b60405180910390a25050565b6000676765c793fa10079d601b1b6301e13380600b546127106112219190615c76565b61122b9190615c76565b6112359190615c35565b905090565b6000611235601054613ac8565b60008061125383612277565b5090959194509092505050565b600f5460ff16156112b05760405162461bcd60e51b815260206004820152601a60248201527910d85b9b9bdd0818da185b99d94818599d195c881cdd5b9cd95d60321b6044820152606401610dd9565b6714d1120d7b16000081111580156112d05750670f43fc2c04ee00008110155b61131c5760405162461bcd60e51b815260206004820152601d60248201527f4d43522063616e6e6f74206265203e20434352206f72203c20313130250000006044820152606401610dd9565b6005541561135c5761132c611ed2565b6001600160a01b0316336001600160a01b03161461135c5760405162461bcd60e51b8152600401610dd990615bd2565b670d8f91d067414d88881015801561137c5750670de07829b2adec288811155b61138557600080fd5b85871115801561139d5750670de0b6b3a76400008611155b6113a657600080fd5b8385111580156113be5750670de0b6b3a76400008411155b6113c757600080fd5b6113cf613ae3565b5060058890556006879055600786905560088590556009849055600a82905560006114006301e13380612710615c76565b61141585676765c793fa10079d601b1b615c76565b61141f9190615c35565b9050600b54811461143d57611432613660565b5042600d55600b8190555b5060045550505050505050565b6002546001600160a01b03161561146057600080fd5b600080546001600160a01b039485166001600160a01b03199182161790915560028054938516938216939093179092556001805491909316911617905542600e819055600f805460ff19169055676765c793fa10079d601b1b600c55600d55565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015611521573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112359190615bb5565b6000611178611552611b2f565b83613b24565b600f546000908190610100900460ff16156115855760405162461bcd60e51b8152600401610dd990615cba565b61158d6134ea565b600f5460ff16156115df5760405162461bcd60e51b815260206004820152601c60248201527b43616e6e6f74206f70656e207768696c652073756e73657474696e6760201b6044820152606401610dd9565b601a546001600160a01b038a16600090815262020022602052604090206001600382015460ff1660048111156116175761161761586b565b036116635760405162461bcd60e51b815260206004820152601c60248201527b426f72726f7765724f70733a2054726f76652069732061637469766560201b6044820152606401610dd9565b60038101805460ff1916600190811790915581018a90558881556000611687613660565b6004830181905590506116998c613b43565b6116a282613bbe565b6002546040516346f7cf8760e01b81529196506001600160a01b0316906346f7cf87906116d9908f908d908d908d90600401615ce5565b600060405180830381600087803b1580156116f357600080fd5b505af1158015611707573d6000803e3d6000fd5b50505050620200258c9080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b031602179055506001620200258054905061176a9190615c0c565b600383018054610100600160881b0319166101006001600160801b03841602179055935061179a8c600085613c3d565b856117a9576117a98c8b613c55565b8a6019546117b79190615d10565b601955601a546000906117cb908c90615d10565b9050600a54601d54826117de9190615d10565b11156117fc5760405162461bcd60e51b8152600401610dd990615d23565b80601a819055508c6001600160a01b0316600080516020615f668339815191528c8e8960006040516118319493929190615c8d565b60405180910390a25050505097509795505050505050565b6000336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461188057600080fd5b60035461ffff16156118c75760405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e48185cdcda59db995960821b6044820152606401610dd9565b816002811461190d5760405162461bcd60e51b8152602060048201526012602482015271125b98dbdc9c9958dd0812510818dbdd5b9d60721b6044820152606401610dd9565b60405180604001604052808585600081811061192b5761192b615d5a565b9050602002013561ffff1681526020018585600181811061194e5761194e615d5a565b61ffff6020918202939093013583169093525082516003805494909301518216620100000263ffffffff1990941691161791909117905561199262093a8042615c35565b61199d906001615d10565b6119aa9062093a80615c76565b601f805463ffffffff92909216600160a01b0263ffffffff60a01b199092169190911790555060019392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5b9190615bb5565b6001600160a01b0316336001600160a01b031614611a8b5760405162461bcd60e51b8152600401610dd990615bd2565b6127108161ffff161115611acd5760405162461bcd60e51b8152602060048201526009602482015268546f6f206c6172676560b81b6044820152606401610dd9565b601f805461ffff60c01b1916600160c01b61ffff8416021790556040517fff345a981533a925d09cff73ce75383d5eba312951c0f20f8d20381a4da5cb6990611b179083906159c4565b60405180910390a150565b60006111786115526134dd565b6000611235611b3c613f03565b613f53565b611b496136c4565b611b51613f6e565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd59190615bb5565b6001600160a01b0316336001600160a01b031614611c055760405162461bcd60e51b8152600401610dd990615bd2565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b611c2f6136c4565b6001600160a01b038216600090815262020023602052604081208054839290611c59908490615d10565b90915550505050565b601a5460009081611c71613f85565b9150508015611ca2576000611c928383676765c793fa10079d601b1b613ff2565b9050611c9e8184615d10565b9250505b601d54611caf9083615d10565b9250505090565b601b5480611cfb5760405162461bcd60e51b8152602060048201526012602482015271139bdd1a1a5b99c81d1bc818dbdb1b1958dd60721b6044820152606401610dd9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166340c10f197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3f006746040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dac9190615bb5565b836040518363ffffffff1660e01b8152600401611dca929190615d70565b600060405180830381600087803b158015611de457600080fd5b505af1158015611df8573d6000803e3d6000fd5b50506000601b55505050565b33600090815262020023602052604090205480611e635760405162461bcd60e51b815260206004820181905260248201527f4e6f20636f6c6c61746572616c20617661696c61626c6520746f20636c61696d6044820152606401610dd9565b336000908152620200236020526040812055600154611e8c906001600160a01b031683836140a0565b5050565b600062093a8061122b7f000000000000000000000000000000000000000000000000000000000000000042615c0c565b6000601c546019546112359190615d10565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611521573d6000803e3d6000fd5b6000806000611f3f6134ea565b8880611f4857508b5b15611fc857600f54610100900460ff1615611f755760405162461bcd60e51b8152600401610dd990615cba565b600f5460ff1615611fc85760405162461bcd60e51b815260206004820181905260248201527f43616e6e6f7420696e637265617365207768696c652073756e73657474696e676044820152606401610dd9565b6001600160a01b038516600090815262020022602052604090206001600382015460ff166004811115611ffd57611ffd61586b565b1461201a5760405162461bcd60e51b8152600401610dd990615d89565b80548c1561206d578d15612053576120328c82615d10565b90508e61204357612043878d613c55565b61204e868d8f6140f6565b612069565b61205d8c82615c0c565b9050612069868e6141c2565b8082555b60018201548a156120be578b156120a0576120888b82615d10565b90508a6019546120989190615d10565b6019556120b6565b6120aa8b82615c0c565b90506120b6878c614257565b600183018190555b60006120ca82846142bf565b9050600260009054906101000a90046001600160a01b03166001600160a01b0316632be212608a838e8e6040518563ffffffff1660e01b81526004016121139493929190615ce5565b600060405180830381600087803b15801561212d57600080fd5b505af1158015612141573d6000803e3d6000fd5b50505050600061215085613bbe565b9050896001600160a01b0316600080516020615f6683398151915285858460026040516121809493929190615c8d565b60405180910390a2919650919450925050509a509a509a975050505050505050565b6121aa615610565b620100228261ffff81106121c0576121c0615d5a565b6040805160e0810191829052929190910190600790826000855b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116121da575094979650505050505050565b600080600061222f84611247565b91509150600061223f83836142bf565b95945050505050565b60006122526134ea565b600061225c613ae3565b905061227061226a82613f53565b84613b24565b9392505050565b6001600160a01b03811660009081526202002260205260408120805460018201549092909181906122a786612ebe565b600483015490945090925080156122de5760006122c2613f85565b509050816122d08289615c76565b6122da9190615c35565b9650505b6122e88487615d10565b95506122f48386615d10565b945050509193509193565b6000600260009054906101000a90046001600160a01b0316905061236f604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081525090565b600654831015801561238357506007548311155b6123c65760405162461bcd60e51b81526020600482015260146024820152734d61782066656520302e352520746f203130302560601b6044820152606401610dd9565b7f0000000000000000000000000000000000000000000000000000000000000000600e546123f49190615d10565b4210156124365760405162461bcd60e51b815260206004820152601060248201526f1093d3d514d514905417d411549253d160821b6044820152606401610dd9565b61243e610e8b565b8160c001818152505060006004549050807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b620115d6040518163ffffffff1660e01b81526004016020604051808303816000875af11580156124af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d39190615c5d565b10156125205760405162461bcd60e51b815260206004820152601c60248201527b21b0b73737ba103932b232b2b6903bb432b7102a21a9101e1026a1a960211b6044820152606401610dd9565b60008a116125705760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610dd9565b6040516370a0823160e01b81528a906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a08231906125be90339060040161568b565b602060405180830381865afa1580156125db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ff9190615c5d565b10156126445760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610dd9565b61264c613f6e565b612654611c62565b60e083015289825260c08201516000906126729085908c90856142f5565b1561267e575088612780565b836001600160a01b0316634d6228316040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e09190615bb5565b90505b6001600160a01b03811615801590612707575081612705828560c001516130cd565b105b1561278057604051632dc9c0eb60e21b81526001600160a01b0385169063b72703ac9061273890849060040161568b565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127799190615bb5565b90506126e3565b85158061278d5750606486115b1561279757606495505b856001600160401b038111156127af576127af615dc0565b60405190808252806020026020018201604052801561280d57816020015b6127fa604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b8152602001906001900390816127cd5790505b5061012084015260006101008401525b6001600160a01b038116158015906128355750825115155b80156128415750600086115b156129a9578561285081615dd6565b9650506000846001600160a01b031663b72703ac836040518263ffffffff1660e01b8152600401612881919061568b565b602060405180830381865afa15801561289e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c29190615bb5565b90506128cd82613552565b505060006128e8868487600001518860c001518f8f8f614433565b90508060400151156128fb5750506129a9565b6040518060600160405280846001600160a01b031681526020018260000151815260200182602001518152508561012001518661010001805180919061294090615ded565b90528151811061295257612952615d5a565b6020026020010181905250806000015185602001516129719190615d10565b602080870191909152810151604086015161298c9190615d10565b60408601528051855161299f9190615c0c565b855250905061281d565b60008360400151116129fb5760405162461bcd60e51b815260206004820152601b60248201527a155b98589b19481d1bc81c995919595b48185b9e48185b5bdd5b9d602a1b6044820152606401610dd9565b612a1283604001518460c001518560e00151614748565b50600f5460ff16612a3757612a32612a2861123a565b84604001516147ca565b612a3a565b60005b606084018190526040840151612a5191908761483b565b6060830151601f5460009161271091612a759190600160c01b900461ffff16615c76565b612a7f9190615c35565b6101008501519091508115612b165760005b81811015612b145760008661012001518281518110612ab257612ab2615d5a565b602002602001015190508660400151816040015185612ad19190615c76565b612adb9190615c35565b81516001600160a01b0316600090815262020023602052604081208054909190612b06908490615d10565b909155505050600101612a91565b505b601f54612710600160c01b90910461ffff161015612bcf576000828660600151612b409190615c0c565b9050612bcd7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3f006746040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc79190615bb5565b82614257565b505b84606001518560400151612be39190615c0c565b8560800181815250507f43a3f4082a4dbc33d78e317d2497d3a730bc7fc3574159dcea1056e62e5d9ad88d866020015187604001518860600151604051612c2d9493929190615a0a565b60405180910390a16020850151604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691639dc29fac91612c86913391600401615d70565b600060405180830381600087803b158015612ca057600080fd5b505af1158015612cb4573d6000803e3d6000fd5b5050506020860151601a54612cc99250615c0c565b601a556080850151612cdc903390614257565b612ce46148ac565b6020546001600160a01b031615612d7457610120850180518290526020549051604051637cd347f560e11b81526001600160a01b039092169163f9a68fea91612d2f91600401615e06565b6020604051808303816000875af1158015612d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d729190615e68565b505b50505050505050505050505050565b6000611235612d90613f03565b613ac8565b612d9d6134ea565b60016001600160a01b038516600090815262020022602052604090206003015460ff166004811115612dd157612dd161586b565b14612dee5760405162461bcd60e51b8152600401610dd990615d89565b612df784613736565b612e02846002613785565b620200255415612e225780601a54612e1a9190615c0c565b601a55612e28565b6000601a555b612e328383614257565b612e3a6148ac565b836001600160a01b0316600080516020615f6683398151915260008060006001604051612e6a9493929190615c8d565b60405180910390a250505050565b601a5460009081612e87613f85565b9150508015612eb8576000612ea88383676765c793fa10079d601b1b613ff2565b9050612eb48184615d10565b9250505b50919050565b6001600160a01b03811660009081526202002460209081526040808320815180830190925280548083526001909101549282019290925260155483928391612f069190615c0c565b905060008260200151601654612f1c9190615c0c565b9050612f288183615d10565b1580612f66575060016001600160a01b038716600090815262020022602052604090206003015460ff166004811115612f6357612f6361586b565b14155b15612f7957506000958695509350505050565b6001600160a01b0386166000908152620200226020526040902060020154670de0b6b3a7640000612faa8483615c76565b612fb49190615c35565b670de0b6b3a7640000612fc78484615c76565b612fd19190615c35565b9550955050505050915091565b600080612fea33614904565b90508015613087576040516335e97f1f60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636bd2fe3e9061304290339087908690600401615e85565b6020604051808303816000875af1158015613061573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130859190615e68565b505b6040518181526001600160a01b0384169033907f0aa4d283470c904c551d18bb894d37e17674920f3261a7f854be501e25f421b79060200160405180910390a392915050565b60008060006130db85611247565b9150915060006130ec8383876149e2565b9695505050505050565b6131066301e13380612710615c76565b61311d676765c793fa10079d601b1b611388615c76565b6131279190615c35565b81565b6000611178613137612d83565b836147ca565b600062020025828154811061315457613154615d5a565b6000918252602090912001546001600160a01b031692915050565b60238161ffff811061318057600080fd5b0154905081565b600060016001600160a01b038316600090815262020022602052604090206003015460ff1660048111156131bd576131bd61586b565b146131ca57506000919050565b506015546001600160a01b0390911660009081526202002460205260409020541090565b6131f66136c4565b61320083836141c2565b61320a8382614257565b505050565b6001600160a01b038116600090815260226020526040812054601f54600160a01b900463ffffffff16428111156132435750425b601f5460009061326090600160801b900463ffffffff1683615c0c565b601e5490915081156132b857601a5480156132b657601f54819061328d906001600160801b031685615c76565b61329f90670de0b6b3a7640000615c76565b6132a99190615c35565b6132b39083615d10565b91505b505b6001600160a01b0386166000908152602160205260409020548082111561332857670de0b6b3a76400006132ec8284615c0c565b6001600160a01b03891660009081526202002260205260409020546133119190615c76565b61331b9190615c35565b6133259086615d10565b94505b61333187614a13565b61333b9086615d10565b979650505050505050565b61334e6136c4565b6133588585614b47565b60195483156133735761336b8482615c0c565b601981905590505b601254601355601c546133868383615c0c565b6133909190615d10565b60148190556013546040517f51bf4c63ec3cba9d03d43238abbdd979dd91bd16d9895c74ceea9118c7baaf60926133ce928252602082015260400190565b60405180910390a1604051631062c15f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906320c582be90613446907f0000000000000000000000000000000000000000000000000000000000000000908b908890600401615e85565b600060405180830381600087803b15801561346057600080fd5b505af1158015613474573d6000803e3d6000fd5b505050506134828783614257565b50505050505050565b6134936136c4565b611e8c8282614cc0565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146134d457600080fd5b61227083614904565b6000611235601054613f53565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611b515760405162461bcd60e51b815260206004820152600d60248201526c43616c6c6572206e6f7420424f60981b6044820152606401610dd9565b6001600160a01b0381166000908152620200226020526040812081906001600382015460ff1660048111156135895761358961586b565b0361365a576004810154601a5460006135a0613660565b8454600186015497509550905084818410156135d557836135c18388615c76565b6135cb9190615c35565b6004860183905595505b6015546001600160a01b0389166000908152620200246020526040902054101561363f576000806136058a612ebe565b9092509050613614828a615d10565b6001880181905598506136278189615d10565b97506136328a613b43565b61363c8183614cc0565b50505b85811461364a578585555b613655888285613c3d565b505050505b50915091565b600080600061366d613f85565b90925090508015612eb857601a5460006136938284676765c793fa10079d601b1b613ff2565b905061369f8183615d10565b601a55601b546136b0908290615d10565b601b555050600c82905542600d5550919050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611b515760405162461bcd60e51b81526020600482015260176024820152762737ba102634b8bab4b230ba34b7b71026b0b730b3b2b960491b6044820152606401610dd9565b6001600160a01b0381166000908152620200226020526040902060020154601254613762908290615c0c565b601255506001600160a01b03166000908152620200226020526040812060020155565b62020025546001600160a01b0383166000908152620200226020526040902060038101805484919060ff191660018360048111156137c5576137c561586b565b021790555060006001808301829055818355600483018290556002546001600160a01b038781168452620200246020526040842084815583019390935591909116908311801561387657506001816001600160a01b031663de8fa4316040518163ffffffff1660e01b8152600401602060405180830381865afa158015613850573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138749190615c5d565b115b1561398457600382015461010090046001600160801b031660006202002561389f600187615c0c565b815481106138af576138af615d5a565b6000918252602090912001546202002580546001600160a01b03909216925082916001600160801b0385169081106138e9576138e9615d5a565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790559183168082526202002283526040918290206003018054610100600160881b0319166101006001600160801b038816908102919091179091558251918252928101929092527f02b04ae5f7be9ca7c103293a2aa15f3c339d15d6eda53b721fef7b0e609c831a910160405180910390a150505b6202002580548061399757613997615ea9565b600082815260209020810160001990810180546001600160a01b0319169055019055604051631484968760e11b81526001600160a01b038216906329092d0e906139e590889060040161568b565b600060405180830381600087803b1580156139ff57600080fd5b505af1158015613a13573d6000803e3d6000fd5b50505060039092018054610100600160881b03191690555050505050565b6001600160a01b03831660009081526021602052604090205480821115613ac257670de0b6b3a7640000613a658284615c0c565b613a6f9085615c76565b613a799190615c35565b6001600160a01b03851660009081526022602052604081208054909190613aa1908490615d10565b90915550506001600160a01b03841660009081526021602052604090208290555b50505050565b600061117882600654613adb9190615d10565b600754614d1d565b600080613aee613f03565b6010819055604051818152909150600080516020615f868339815191529060200160405180910390a1613b1f614d33565b919050565b6000670de0b6b3a7640000613b398385615c76565b6122709190615c35565b60155460165460408051808201825283815260208082018481526001600160a01b0387166000908152620200248352849020925183555160019092019190915581518481529081018390527fc437f324d85e369394148dd9d62f98f534b382e01ed3dd2eb98138fb6d3ab49a910160405180910390a1505050565b600080613bce8360010154614d83565b60028401805490829055601254919250906000908390613bef908490615c0c565b613bf99190615d10565b60128190556040518181529091507f6bac5e0eb3c44eb03a60ab11ec3a2c051771616aecadbcfff2630aabae5203829060200160405180910390a150909392505050565b6000613c4882614db5565b9050613ac2848483613a31565b6000613c6a68056bc75e2d6310000083615c35565b9050600080613c77610e21565b9150915082620100228361ffff8110613c9257613c92615d5a565b018260078110613ca457613ca4615d5a565b600891828204019190066004028282829054906101000a900463ffffffff16613ccd9190615ebf565b82546101009290920a63ffffffff8181021990931691831602179091556001600160a01b0387166000908152620200216020908152604091829020825160608101845290548085168252600160201b8104851692820192909252600160401b90910490921690820181905290915082148015613d52575082816020015163ffffffff16145b15613d9b578051613d64908590615ebf565b6001600160a01b03871660009081526202002160205260409020805463ffffffff191663ffffffff92909216919091179055613efb565b805163ffffffff1615613e7b57600062010022826020015163ffffffff1661ffff8110613dca57613dca615d5a565b01826040015163ffffffff1660078110613de657613de6615d5a565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16826000015163ffffffff166023846020015163ffffffff1661ffff8110613e3157613e31615d5a565b0154613e3d9190615c76565b613e479190615c35565b6001600160a01b038816600090815260226020526040812080549293508392909190613e74908490615d10565b9091555050505b6040805160608101825263ffffffff808716825285811660208084019182528683168486019081526001600160a01b038c1660009081526202002190925294902092518354915194518316600160401b0263ffffffff60401b19958416600160201b026001600160401b0319909316919093161717929092169190911790555b505050505050565b600080603c60115442613f169190615c0c565b613f209190615c35565b90506000613f3060055483614e71565b9050670de0b6b3a764000081601054613f499190615c76565b611caf9190615c35565b600061117882600854613f669190615d10565b600954614d1d565b613f79601a54614db5565b50613f82613660565b50565b600d546000908190428103613fa0575050600c549160009150565b600b54600c5493508015613fec576000613fba8342615c0c565b9050613fc68282615c76565b9350613fde8585676765c793fa10079d601b1b613ff2565b613fe89086615d10565b9450505b50509091565b600080806000198587098587029250828110838203039150508060000361402c5783828161402257614022615c1f565b0492505050612270565b80841161403857600080fd5b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b61320a8363a9059cbb60e01b84846040516024016140bf929190615d70565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614f1c565b600082601a546141069190615d10565b9050600a54601d54826141199190615d10565b11156141375760405162461bcd60e51b8152600401610dd990615d23565b601a8190556040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f199061418a9087908690600401615d70565b600060405180830381600087803b1580156141a457600080fd5b505af11580156141b8573d6000803e3d6000fd5b5050505050505050565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906142109085908590600401615d70565b600060405180830381600087803b15801561422a57600080fd5b505af115801561423e573d6000803e3d6000fd5b5050505080601a546142509190615c0c565b601a555050565b8015611e8c578060195461426b9190615c0c565b6019556040517f342693d2465f6f44931e41128424a0227e0cbc69d1c3917a839e6de71696d44c906142a09084908490615d70565b60405180910390a1600154611e8c906001600160a01b031683836140a0565b600081156142ec57816142db68056bc75e2d6310000085615c76565b6142e59190615c35565b9050611178565b50600019611178565b60006001600160a01b03841615806143775750604051630bb7c8fd60e31b81526001600160a01b03861690635dbe47e89061433490879060040161568b565b602060405180830381865afa158015614351573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143759190615e68565b155b8061438a57508161438885856130cd565b105b156143975750600061442b565b60405163765e015960e01b81526000906001600160a01b0387169063765e0159906143c690889060040161568b565b602060405180830381865afa1580156143e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144079190615bb5565b90506001600160a01b038116158061442757508261442582866130cd565b105b9150505b949350505050565b614459604051806060016040528060008152602001600081526020016000151581525090565b6001600160a01b0387166000908152620200226020526040902080546144ab9088906144a6907f000000000000000000000000000000000000000000000000000000000000000090615c0c565b614d1d565b80835286906144c390670de0b6b3a764000090615c76565b6144cd9190615c35565b6020830152815181546000916144e291615c0c565b90506000836020015183600101546144fa9190615c0c565b90507f0000000000000000000000000000000000000000000000000000000000000000820361459f5761452c8a613736565b6145378a6004613785565b6145628a7f000000000000000000000000000000000000000000000000000000000000000083614fee565b896001600160a01b0316600080516020615f66833981519152600080600060046040516145929493929190615c8d565b60405180910390a261473a565b60006145ab82846142bf565b905060008187116145c5576145c08783615c0c565b6145cf565b6145cf8288615c0c565b90506601c6bf5263400081118061466e57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663969c24526040518163ffffffff1660e01b8152600401602060405180830381865afa15801561463f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146639190615c5d565b61466c856150ec565b105b15614685575050600160408501525061333b915050565b5060405163015f109360e51b81526001600160a01b038d1690632be21260906146b8908e9085908d908d90600401615ce5565b600060405180830381600087803b1580156146d257600080fd5b505af11580156146e6573d6000803e3d6000fd5b50505083855550600184018290556146fd84613bbe565b508a6001600160a01b0316600080516020615f668339815191528484876002015460046040516147309493929190615c8d565b60405180910390a2505b505050979650505050505050565b600080614753613f03565b90506000836147628688615c76565b61476c9190615c35565b9050600061477b600283615c35565b6147859084615d10565b905061479981670de0b6b3a7640000614d1d565b6010819055604051818152909150600080516020615f868339815191529060200160405180910390a16130ec614d33565b600080670de0b6b3a76400006147e08486615c76565b6147ea9190615c35565b90508281106122705760405162461bcd60e51b815260206004820152601f60248201527f46656520657863656564732072657475726e656420636f6c6c61746572616c006044820152606401610dd9565b600082614850670de0b6b3a764000086615c76565b61485a9190615c35565b905081811115613ac25760405162461bcd60e51b815260206004820152601d60248201527f4665652065786365656465642070726f7669646564206d6178696d756d0000006044820152606401610dd9565b6202002554600003611b5157676765c793fa10079d601b1b600c5542600d55600060128190556013819055601481905560158190556016819055601781905560188190556019819055601a819055601c819055601d55565b60035460009061ffff1661494f5760405162461bcd60e51b815260206004820152601260248201527152657761726473206e6f742061637469766560701b6044820152606401610dd9565b61495882613552565b50506001600160a01b0382166000908152602260205260409020548015614993576001600160a01b0383166000908152602260205260408120555b600061499e84614a13565b905080156149db576149b08183615d10565b6001600160a01b0385166000908152620200216020526040902080546001600160601b031916905591505b5092915050565b60008215614a0a576000836149f78487615c76565b614a019190615c35565b91506122709050565b50600019612270565b6001600160a01b038116600090815262020021602090815260408083208151606081018352905463ffffffff808216808452600160201b8304821695840195909552600160401b90910416918101919091529015612eb857600080614a76610e21565b9150915080836040015163ffffffff16141580614a9d575081836020015163ffffffff1614155b15614b3f5762010022836020015163ffffffff1661ffff8110614ac257614ac2615d5a565b01836040015163ffffffff1660078110614ade57614ade615d5a565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16836000015163ffffffff166023856020015163ffffffff1661ffff8110614b2957614b29615d5a565b0154614b359190615c76565b61223f9190615c35565b505050919050565b81600003614b53575050565b601754600090614b6b670de0b6b3a764000084615c76565b614b759190615d10565b90506000601854670de0b6b3a764000085614b909190615c76565b614b9a9190615d10565b6012549091506000614bac8285615c35565b90506000614bba8385615c35565b9050614bc68383615c76565b614bd09086615c0c565b601755614bdd8382615c76565b614be79085615c0c565b601855601554600090614bfb908490615d10565b9050600082601654614c0d9190615d10565b6015839055601681905560408051848152602081018390529192507f9f8bc8ab0daf5bceef75ecfd2085d1fcc6548c657ea970d9a23a60610d0737e3910160405180910390a188601a6000828254614c659190615c0c565b9250508190555088601d6000828254614c7e9190615d10565b9250508190555087601c6000828254614c979190615d10565b925050819055508760196000828254614cb09190615c0c565b9091555050505050505050505050565b81601d6000828254614cd29190615c0c565b9250508190555081601a6000828254614ceb9190615d10565b9250508190555080601c6000828254614d049190615c0c565b925050819055508060196000828254611c599190615d10565b6000818310614d2c5781612270565b5090919050565b600060115442614d439190615c0c565b9050603c8110613f82574260118190556040519081527f860f8d2f0c74dd487e89e2883e3b25b8159ce1e1b3433a291cba7b82c508f3bc90602001611b17565b6014546000908190808203614d9a578391506149db565b60135480614daa57614daa615edc565b81614b358287615c76565b601f54600090600160a01b900463ffffffff168042811115614dd45750425b601f54600090614df190600160801b900463ffffffff1683615c0c565b601e54945090508015614e6857601f805463ffffffff60801b1916600160801b63ffffffff8516021790558415614e6857601f548590614e3a906001600160801b031683615c76565b614e4c90670de0b6b3a7640000615c76565b614e569190615c35565b614e609085615d10565b601e81905593505b614b3f83615118565b6000631f540500821115614e8757631f54050091505b81600003614e9e5750670de0b6b3a7640000611178565b670de0b6b3a764000083835b6001811115614f1257614ebe600282615c49565b600003614ee357614ecf82836154c6565b9150614edc600282615c35565b9050614eaa565b614eed82846154c6565b9250614ef982836154c6565b91506002614f08600183615c0c565b614edc9190615c35565b6130ec82846154c6565b6000614f71826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166154fd9092919063ffffffff16565b80519091501561320a5780806020019051810190614f8f9190615e68565b61320a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610dd9565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac9061505c907f0000000000000000000000000000000000000000000000000000000000000000908690600401615d70565b600060405180830381600087803b15801561507657600080fd5b505af115801561508a573d6000803e3d6000fd5b5050505081601a5461509c9190615c0c565b601a556001600160a01b0383166000908152620200236020526040812080548392906150c9908490615d10565b9250508190555080601960008282546150e29190615c0c565b9091555050505050565b60006111787f000000000000000000000000000000000000000000000000000000000000000083615c0c565b6040805180820190915260035461ffff80821680845262010000909204166020830152600003615146575050565b6000615150611e90565b905062093a806151807f000000000000000000000000000000000000000000000000000000000000000085615c0c565b61518a9190615c35565b81101561519657505050565b6000600162093a806151c87f000000000000000000000000000000000000000000000000000000000000000087615c0c565b6151d29190615c35565b6151dc9190615c0c565b835160405163378cbf7560e01b81529192506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163378cbf759161522f91906004016159c4565b6020604051808303816000875af115801561524e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152729190615c5d565b9050844210156152af5760006152884287615c0c565b601f549091506152a1906001600160801b031682615c76565b6152ab9083615d10565b9150505b6152bc62093a8082615c35565b601f805463ffffffff42908116600160801b026001600160a01b03199092166001600160801b0394909416939093171790556152fc9062093a8090615d10565b601f805463ffffffff92909216600160a01b0263ffffffff60a01b19909216919091179055602084015160405163378cbf7560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163378cbf759161537191906004016159c4565b6020604051808303816000875af1158015615390573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906153b49190615c5d565b9050600060238361ffff81106153cc576153cc615d5a565b01549050801561549d576000620100228461ffff81106153ee576153ee615d5a565b6040805160e0810191829052929190910190600790826000855b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116154085790505050505050905060005b600781101561549a5781816007811061546957615469615d5a565b602002015163ffffffff16600003615488576154858385615d10565b93505b8061549281615ded565b91505061544e565b50505b6154a8600783615c35565b60238561ffff81106154bc576154bc615d5a565b0155505050505050565b6000806154d38385615c76565b9050670de0b6b3a76400006154e9600282615c35565b6154f39083615d10565b61442b9190615c35565b606061442b848460008585600080866001600160a01b031685876040516155249190615f16565b60006040518083038185875af1925050503d8060008114615561576040519150601f19603f3d011682016040523d82523d6000602084013e615566565b606091505b509150915061333b87838387606083156155e15782516000036155da576001600160a01b0385163b6155da5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dd9565b508161442b565b61442b83838151156155f65781518083602001fd5b8060405162461bcd60e51b8152600401610dd99190615f32565b6040518060e001604052806007906020820280368337509192915050565b6001600160a01b0381168114613f8257600080fd5b60006020828403121561565557600080fd5b81356122708161562e565b8015158114613f8257600080fd5b60006020828403121561568057600080fd5b813561227081615660565b6001600160a01b0391909116815260200190565b600080600080600080600080610100898b0312156156bc57600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b60008060006060848603121561570957600080fd5b83356157148161562e565b925060208401356157248161562e565b915060408401356157348161562e565b809150509250925092565b60006020828403121561575157600080fd5b5035919050565b600080600080600080600060e0888a03121561577357600080fd5b873561577e8161562e565b965060208801359550604088013594506060880135935060808801356157a38161562e565b925060a08801356157b38161562e565b915060c08801356157c381615660565b8091505092959891949750929550565b600080602083850312156157e657600080fd5b82356001600160401b03808211156157fd57600080fd5b818501915085601f83011261581157600080fd5b81358181111561582057600080fd5b8660208260051b850101111561583557600080fd5b60209290920196919550909350505050565b60006020828403121561585957600080fd5b813561ffff8116811461227057600080fd5b634e487b7160e01b600052602160045260246000fd5b60058110613f8257634e487b7160e01b600052602160045260246000fd5b868152602081018690526040810185905260c081016158bd85615881565b60608201949094526001600160801b0392909216608083015260a0909101529392505050565b600080604083850312156158f657600080fd5b82356159018161562e565b946020939093013593505050565b6000806000806000806000806000806101408b8d03121561592f57600080fd5b8a3561593a81615660565b995060208b013561594a81615660565b985060408b0135975060608b0135965060808b013561596881615660565b955060a08b0135945060c08b013561597f8161562e565b935060e08b013561598f8161562e565b92506101008b01356159a08161562e565b91506101208b01356159b18161562e565b809150509295989b9194979a5092959850565b61ffff91909116815260200190565b60e08101818360005b6007811015615a0157815163ffffffff168352602092830192909101906001016159dc565b50505092915050565b93845260208401929092526040830152606082015260800190565b600080600080600080600060e0888a031215615a4057600080fd5b873596506020880135615a528161562e565b95506040880135615a628161562e565b94506060880135615a728161562e565b9699959850939660808101359560a0820135955060c0909101359350915050565b60008060008060808587031215615aa957600080fd5b8435615ab48161562e565b93506020850135615ac48161562e565b93969395505050506040820135916060013590565b600080600060608486031215615aee57600080fd5b8335615af98161562e565b95602085013595506040909401359392505050565b60008060008060008060c08789031215615b2757600080fd5b8635615b328161562e565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b60008060408385031215615b6d57600080fd5b50508035926020909101359150565b60008060408385031215615b8f57600080fd5b8235615b9a8161562e565b91506020830135615baa8161562e565b809150509250929050565b600060208284031215615bc757600080fd5b81516122708161562e565b6020808252600a908201526927b7363c9037bbb732b960b11b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561117857611178615bf6565b634e487b7160e01b600052601260045260246000fd5b600082615c4457615c44615c1f565b500490565b600082615c5857615c58615c1f565b500690565b600060208284031215615c6f57600080fd5b5051919050565b808202811582820484141761117857611178615bf6565b848152602081018490526040810183905260808101615cab83615881565b82606083015295945050505050565b60208082526011908201527010dbdb1b185d195c985b0814185d5cd959607a1b604082015260600190565b6001600160a01b03948516815260208101939093529083166040830152909116606082015260800190565b8082018082111561117857611178615bf6565b6020808252601d908201527f436f6c6c61746572616c2064656274206c696d69742072656163686564000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03929092168252602082015260400190565b6020808252601e908201527f54726f766520636c6f736564206f7220646f6573206e6f742065786973740000604082015260600190565b634e487b7160e01b600052604160045260246000fd5b600081615de557615de5615bf6565b506000190190565b600060018201615dff57615dff615bf6565b5060010190565b602080825282518282018190526000919060409081850190868401855b82811015615e5b57815180516001600160a01b0316855286810151878601528501518585015260609093019290850190600101615e23565b5091979650505050505050565b600060208284031215615e7a57600080fd5b815161227081615660565b6001600160a01b039384168152919092166020820152604081019190915260600190565b634e487b7160e01b600052603160045260246000fd5b63ffffffff8181168382160190808211156149db576149db615bf6565b634e487b7160e01b600052600160045260246000fd5b60005b83811015615f0d578181015183820152602001615ef5565b50506000910152565b60008251615f28818460208701615ef2565b9190910192915050565b6020815260008251806020840152615f51816040850160208701615ef2565b601f01601f1916919091016040019291505056fec3770d654ed33aeea6bf11ac8ef05d02a6a04ed4686dd2f624d853bbec43cc8bc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600ca164736f6c6343000813000a0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf8000000000000000000000000e0598d793baf7b4f49f4a003885e4180b28cab610000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2800000000000000000000000072c590349535ad52e6953744cb2a36b40954271900000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c0000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e200000000000000000000000000000000000000000000000ad78ebc5ac62000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104b35760003560e01c80638235b284116102765780638235b284146108d1578063874d6d81146108e4578063887105d3146108ec5780638bbb1de8146108f45780638da5cb5b146108fd5780638e415ea81461090557806391245f9f146109185780639484fb8e1461092157806396660b181461092e57806396d711ff146109375780639ed7254214610940578063a20baee614610949578063a25fc26414610958578063a5713dcd1461097a578063ae9187541461099a578063b0d8e181146109ad578063b2016bd4146109c0578063b2f29d7b146109d3578063b354f6df146109e6578063b4997a1f14610a0d578063b49c6f8214610a16578063b7f8cf9b14610a7b578063b91af97c14610aa2578063bc006c3814610ac5578063bcd3752614610ace578063be2c377b14610ae1578063bf9befb114610aea578063c046371114610af3578063c52861f214610b1f578063c9a4cbf114610b27578063cc9641a814610b3a578063d128080c14610b61578063d12ae84114610b69578063d279c19114610b7c578063d293c71014610b8f578063d30612e114610ba2578063d380a37c14610baa578063d38b055814610bb3578063d5b3563514610bbc578063d9a7244414610bcf578063e0b7a2d814610be2578063e2ac77b014610bf5578063e47cf0c314610c08578063e9186c9414610c11578063e950342514610c24578063ea23a27a14610c37578063eb3007fd14610c4a578063ebe2b12b14610c5d578063ec38a05d14610c74578063f058203814610c96578063f36b242514610ca9578063f8d8989814610cb1578063fbfa77cf14610cd857600080fd5b806301c799fc146104b857806309c8bb14146104e05780630b076557146104f55780630f8490df1461051d5780630fdb11cf146105255780631289fefb1461053b5780631673c79a1461054357806316c38b3c1461056c5780631ef3a04c1461057f5780631f68f20a146105b357806320d17d7b146105bc57806321e37801146105c557806325019ee9146105d85780632879e488146105eb5780632b11551a146105f35780632b2b2bac146105fb5780632d587e101461060e5780632f5c83a81461061757806331c7a2611461062057806333d53b591461062957806334ba3c7114610632578063363bf964146106455780634056d9fc14610658578063452a9320146106615780634763637114610669578063477d66cf1461069c5780634820fe56146106af5780634870dd9a146106b757806349eefeee146106bf5780634ba4a28b146106c95780634cb653b7146106f05780635733d58f146107035780635bbe8aad146107125780635c975abb14610735578063616325ae14610747578063631203b01461075a57806364cee2601461076d57806366ca4a211461079b5780636ef64338146107a35780636f3fe40414610808578063720fbe2c14610810578063724e78da14610819578063741bef1a1461082c578063789c6b931461083f578063794e572414610852578063795d26c31461085b5780637a83a34e146108635780637b0a47ee1461086b5780637c3a00fd146108965780637e95d6641461089f578063807d138d146108a85780638140d077146108b1575b600080fd5b6104c0610cff565b604080519384526020840192909252908201526060015b60405180910390f35b6104f36104ee366004615643565b610d27565b005b610508610503366004615643565b610e04565b604080519283526020830191909152016104d7565b610508610e21565b61052d610e8b565b6040519081526020016104d7565b6104f3610f9d565b610508610551366004615643565b62020024602052600090815260409020805460019091015482565b6104f361057a36600461566e565b6110a9565b6105a67f0000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e281565b6040516104d7919061568b565b61052d60105481565b61052d601d5481565b61052d6105d3366004615643565b611146565b6104f36105e6366004615643565b61117e565b61052d6111fe565b61052d61123a565b610508610609366004615643565b611247565b61052d600d5481565b61052d600a5481565b61052d60085481565b61052d60155481565b6104f361064036600461569f565b611260565b6104f36106533660046156f4565b61144a565b61052d60095481565b6105a66114c1565b6003546106819061ffff808216916201000090041682565b6040805161ffff9384168152929091166020830152016104d7565b61052d6106aa36600461573f565b611545565b60195461052d565b61052d60c881565b620200255461052d565b61052d7f00000000000000000000000000000000000000000000000ad78ebc5ac620000081565b6105086106fe366004615758565b611558565b61052d6714d1120d7b16000081565b6107256107203660046157d3565b611849565b60405190151581526020016104d7565b600f5461072590610100900460ff1681565b6104f3610755366004615847565b6119d9565b61052d61076836600461573f565b611b22565b61052d61077b366004615643565b6001600160a01b0316600090815262020022602052604090206002015490565b61052d611b2f565b6107f66107b1366004615643565b62020022602052600090815260409020805460018201546002830154600384015460049094015492939192909160ff8116916101009091046001600160801b03169086565b6040516104d79695949392919061589f565b6104f3611b41565b61052d600e5481565b6104f3610827366004615643565b611b53565b6000546105a6906001600160a01b031681565b6104f361084d3660046158e3565b611c27565b61052d60045481565b61052d611c62565b6104f3611cb6565b601f5461087e906001600160801b031681565b6040516001600160801b0390911681526020016104d7565b61052d600b5481565b61052d60065481565b61052d60135481565b61052d6108bf366004615643565b60216020526000908152604090205481565b6104f36108df366004615643565b611e04565b61052d611e90565b61052d611ec0565b61052d600c5481565b6105a6611ed2565b6104c061091336600461590f565b611f32565b61052d60075481565b600f546107259060ff1681565b61052d601b5481565b61052d60145481565b61052d60185481565b61052d670de0b6b3a764000081565b601f5461096d90600160c01b900461ffff1681565b6040516104d791906159c4565b61098d61098836600461573f565b6121a2565b6040516104d791906159d3565b6002546105a6906001600160a01b031681565b61052d6109bb366004615643565b612221565b6001546105a6906001600160a01b031681565b61052d6109e136600461573f565b612248565b61052d7f000000000000000000000000000000000000000000000000000000000000000081565b61052d601e5481565b610a54610a24366004615643565b620200216020526000908152604090205463ffffffff80821691600160201b8104821691600160401b9091041683565b6040805163ffffffff948516815292841660208401529216918101919091526060016104d7565b6105a67f00000000000000000000000072c590349535ad52e6953744cb2a36b40954271981565b610ab5610ab0366004615643565b612277565b6040516104d79493929190615a0a565b61052d60055481565b6104f3610adc366004615a25565b6122ff565b61052d601c5481565b61052d60125481565b601f54610b0a90600160801b900463ffffffff1681565b60405163ffffffff90911681526020016104d7565b61052d612d83565b6104f3610b35366004615a93565b612d95565b6105a67f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf881565b61052d612e78565b610508610b77366004615643565b612ebe565b61052d610b8a366004615643565b612fde565b61052d610b9d3660046158e3565b6130cd565b61052d6130f6565b61052d60115481565b61052d60175481565b61052d610bca36600461573f565b61312a565b6105a6610bdd36600461573f565b61313d565b61052d610bf036600461573f565b61316f565b610725610c03366004615643565b613187565b61052d60165481565b6104f3610c1f366004615ad9565b6131ee565b61052d610c32366004615643565b61320f565b6104f3610c45366004615b0e565b613346565b6104f3610c58366004615b5a565b61348b565b601f54610b0a90600160a01b900463ffffffff1681565b61052d610c82366004615643565b620200236020526000908152604090205481565b61052d610ca4366004615b7c565b61349d565b61052d6134dd565b6105a67f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2881565b6105a67f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c81565b6000806000610d0c611ec0565b610d14611c62565b610d1c610e8b565b925092509250909192565b7f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190615bb5565b6001600160a01b0316336001600160a01b031614610de25760405162461bcd60e51b8152600401610dd990615bd2565b60405180910390fd5b602080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610e0f6134ea565b610e1883613552565b91509150915091565b60008080610e4f7f0000000000000000000000000000000000000000000000000000000064d4288042615c0c565b90506000610e6062093a8083615c35565b9050600062015180610e7562093a8085615c49565b610e7f9190615c35565b91959194509092505050565b600080546001600160a01b031680610f22577f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b031663741bef1a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610efb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1f9190615bb5565b90505b600154604051635670bcc760e11b81526001600160a01b038381169263ace1798e92610f54929091169060040161568b565b6020604051808303816000875af1158015610f73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f979190615c5d565b91505090565b7f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101f9190615bb5565b6001600160a01b0316336001600160a01b03161461104f5760405162461bcd60e51b8152600401610dd990615bd2565b600f805460ff19166001179055611064613660565b506110756301e13380612710615c76565b61108c676765c793fa10079d601b1b611388615c76565b6110969190615c35565b600b5542600d5560006006819055600a55565b8080156110ce57506110b96114c1565b6001600160a01b0316336001600160a01b0316145b806110f157506110dc611ed2565b6001600160a01b0316336001600160a01b0316145b61112c5760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610dd9565b600f80549115156101000261ff0019909216919091179055565b6001600160a01b038116600090815262020022602052604081206003015460ff1660048111156111785761117861586b565b92915050565b6111866136c4565b6001600160a01b03811660009081526202002260205260409020546111aa82613736565b6111b5826003613785565b6111c28282601e54613a31565b816001600160a01b0316600080516020615f66833981519152600080600060036040516111f29493929190615c8d565b60405180910390a25050565b6000676765c793fa10079d601b1b6301e13380600b546127106112219190615c76565b61122b9190615c76565b6112359190615c35565b905090565b6000611235601054613ac8565b60008061125383612277565b5090959194509092505050565b600f5460ff16156112b05760405162461bcd60e51b815260206004820152601a60248201527910d85b9b9bdd0818da185b99d94818599d195c881cdd5b9cd95d60321b6044820152606401610dd9565b6714d1120d7b16000081111580156112d05750670f43fc2c04ee00008110155b61131c5760405162461bcd60e51b815260206004820152601d60248201527f4d43522063616e6e6f74206265203e20434352206f72203c20313130250000006044820152606401610dd9565b6005541561135c5761132c611ed2565b6001600160a01b0316336001600160a01b03161461135c5760405162461bcd60e51b8152600401610dd990615bd2565b670d8f91d067414d88881015801561137c5750670de07829b2adec288811155b61138557600080fd5b85871115801561139d5750670de0b6b3a76400008611155b6113a657600080fd5b8385111580156113be5750670de0b6b3a76400008411155b6113c757600080fd5b6113cf613ae3565b5060058890556006879055600786905560088590556009849055600a82905560006114006301e13380612710615c76565b61141585676765c793fa10079d601b1b615c76565b61141f9190615c35565b9050600b54811461143d57611432613660565b5042600d55600b8190555b5060045550505050505050565b6002546001600160a01b03161561146057600080fd5b600080546001600160a01b039485166001600160a01b03199182161790915560028054938516938216939093179092556001805491909316911617905542600e819055600f805460ff19169055676765c793fa10079d601b1b600c55600d55565b60007f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015611521573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112359190615bb5565b6000611178611552611b2f565b83613b24565b600f546000908190610100900460ff16156115855760405162461bcd60e51b8152600401610dd990615cba565b61158d6134ea565b600f5460ff16156115df5760405162461bcd60e51b815260206004820152601c60248201527b43616e6e6f74206f70656e207768696c652073756e73657474696e6760201b6044820152606401610dd9565b601a546001600160a01b038a16600090815262020022602052604090206001600382015460ff1660048111156116175761161761586b565b036116635760405162461bcd60e51b815260206004820152601c60248201527b426f72726f7765724f70733a2054726f76652069732061637469766560201b6044820152606401610dd9565b60038101805460ff1916600190811790915581018a90558881556000611687613660565b6004830181905590506116998c613b43565b6116a282613bbe565b6002546040516346f7cf8760e01b81529196506001600160a01b0316906346f7cf87906116d9908f908d908d908d90600401615ce5565b600060405180830381600087803b1580156116f357600080fd5b505af1158015611707573d6000803e3d6000fd5b50505050620200258c9080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b031602179055506001620200258054905061176a9190615c0c565b600383018054610100600160881b0319166101006001600160801b03841602179055935061179a8c600085613c3d565b856117a9576117a98c8b613c55565b8a6019546117b79190615d10565b601955601a546000906117cb908c90615d10565b9050600a54601d54826117de9190615d10565b11156117fc5760405162461bcd60e51b8152600401610dd990615d23565b80601a819055508c6001600160a01b0316600080516020615f668339815191528c8e8960006040516118319493929190615c8d565b60405180910390a25050505097509795505050505050565b6000336001600160a01b037f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c161461188057600080fd5b60035461ffff16156118c75760405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e48185cdcda59db995960821b6044820152606401610dd9565b816002811461190d5760405162461bcd60e51b8152602060048201526012602482015271125b98dbdc9c9958dd0812510818dbdd5b9d60721b6044820152606401610dd9565b60405180604001604052808585600081811061192b5761192b615d5a565b9050602002013561ffff1681526020018585600181811061194e5761194e615d5a565b61ffff6020918202939093013583169093525082516003805494909301518216620100000263ffffffff1990941691161791909117905561199262093a8042615c35565b61199d906001615d10565b6119aa9062093a80615c76565b601f805463ffffffff92909216600160a01b0263ffffffff60a01b199092169190911790555060019392505050565b7f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5b9190615bb5565b6001600160a01b0316336001600160a01b031614611a8b5760405162461bcd60e51b8152600401610dd990615bd2565b6127108161ffff161115611acd5760405162461bcd60e51b8152602060048201526009602482015268546f6f206c6172676560b81b6044820152606401610dd9565b601f805461ffff60c01b1916600160c01b61ffff8416021790556040517fff345a981533a925d09cff73ce75383d5eba312951c0f20f8d20381a4da5cb6990611b179083906159c4565b60405180910390a150565b60006111786115526134dd565b6000611235611b3c613f03565b613f53565b611b496136c4565b611b51613f6e565b565b7f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd59190615bb5565b6001600160a01b0316336001600160a01b031614611c055760405162461bcd60e51b8152600401610dd990615bd2565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b611c2f6136c4565b6001600160a01b038216600090815262020023602052604081208054839290611c59908490615d10565b90915550505050565b601a5460009081611c71613f85565b9150508015611ca2576000611c928383676765c793fa10079d601b1b613ff2565b9050611c9e8184615d10565b9250505b601d54611caf9083615d10565b9250505090565b601b5480611cfb5760405162461bcd60e51b8152602060048201526012602482015271139bdd1a1a5b99c81d1bc818dbdb1b1958dd60721b6044820152606401610dd9565b7f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb286001600160a01b03166340c10f197f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b031663b3f006746040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dac9190615bb5565b836040518363ffffffff1660e01b8152600401611dca929190615d70565b600060405180830381600087803b158015611de457600080fd5b505af1158015611df8573d6000803e3d6000fd5b50506000601b55505050565b33600090815262020023602052604090205480611e635760405162461bcd60e51b815260206004820181905260248201527f4e6f20636f6c6c61746572616c20617661696c61626c6520746f20636c61696d6044820152606401610dd9565b336000908152620200236020526040812055600154611e8c906001600160a01b031683836140a0565b5050565b600062093a8061122b7f0000000000000000000000000000000000000000000000000000000064d4288042615c0c565b6000601c546019546112359190615d10565b60007f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611521573d6000803e3d6000fd5b6000806000611f3f6134ea565b8880611f4857508b5b15611fc857600f54610100900460ff1615611f755760405162461bcd60e51b8152600401610dd990615cba565b600f5460ff1615611fc85760405162461bcd60e51b815260206004820181905260248201527f43616e6e6f7420696e637265617365207768696c652073756e73657474696e676044820152606401610dd9565b6001600160a01b038516600090815262020022602052604090206001600382015460ff166004811115611ffd57611ffd61586b565b1461201a5760405162461bcd60e51b8152600401610dd990615d89565b80548c1561206d578d15612053576120328c82615d10565b90508e61204357612043878d613c55565b61204e868d8f6140f6565b612069565b61205d8c82615c0c565b9050612069868e6141c2565b8082555b60018201548a156120be578b156120a0576120888b82615d10565b90508a6019546120989190615d10565b6019556120b6565b6120aa8b82615c0c565b90506120b6878c614257565b600183018190555b60006120ca82846142bf565b9050600260009054906101000a90046001600160a01b03166001600160a01b0316632be212608a838e8e6040518563ffffffff1660e01b81526004016121139493929190615ce5565b600060405180830381600087803b15801561212d57600080fd5b505af1158015612141573d6000803e3d6000fd5b50505050600061215085613bbe565b9050896001600160a01b0316600080516020615f6683398151915285858460026040516121809493929190615c8d565b60405180910390a2919650919450925050509a509a509a975050505050505050565b6121aa615610565b620100228261ffff81106121c0576121c0615d5a565b6040805160e0810191829052929190910190600790826000855b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116121da575094979650505050505050565b600080600061222f84611247565b91509150600061223f83836142bf565b95945050505050565b60006122526134ea565b600061225c613ae3565b905061227061226a82613f53565b84613b24565b9392505050565b6001600160a01b03811660009081526202002260205260408120805460018201549092909181906122a786612ebe565b600483015490945090925080156122de5760006122c2613f85565b509050816122d08289615c76565b6122da9190615c35565b9650505b6122e88487615d10565b95506122f48386615d10565b945050509193509193565b6000600260009054906101000a90046001600160a01b0316905061236f604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081525090565b600654831015801561238357506007548311155b6123c65760405162461bcd60e51b81526020600482015260146024820152734d61782066656520302e352520746f203130302560601b6044820152606401610dd9565b7f0000000000000000000000000000000000000000000000000000000000000000600e546123f49190615d10565b4210156124365760405162461bcd60e51b815260206004820152601060248201526f1093d3d514d514905417d411549253d160821b6044820152606401610dd9565b61243e610e8b565b8160c001818152505060006004549050807f00000000000000000000000072c590349535ad52e6953744cb2a36b4095427196001600160a01b031663b620115d6040518163ffffffff1660e01b81526004016020604051808303816000875af11580156124af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d39190615c5d565b10156125205760405162461bcd60e51b815260206004820152601c60248201527b21b0b73737ba103932b232b2b6903bb432b7102a21a9101e1026a1a960211b6044820152606401610dd9565b60008a116125705760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610dd9565b6040516370a0823160e01b81528a906001600160a01b037f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2816906370a08231906125be90339060040161568b565b602060405180830381865afa1580156125db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ff9190615c5d565b10156126445760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610dd9565b61264c613f6e565b612654611c62565b60e083015289825260c08201516000906126729085908c90856142f5565b1561267e575088612780565b836001600160a01b0316634d6228316040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e09190615bb5565b90505b6001600160a01b03811615801590612707575081612705828560c001516130cd565b105b1561278057604051632dc9c0eb60e21b81526001600160a01b0385169063b72703ac9061273890849060040161568b565b602060405180830381865afa158015612755573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127799190615bb5565b90506126e3565b85158061278d5750606486115b1561279757606495505b856001600160401b038111156127af576127af615dc0565b60405190808252806020026020018201604052801561280d57816020015b6127fa604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b8152602001906001900390816127cd5790505b5061012084015260006101008401525b6001600160a01b038116158015906128355750825115155b80156128415750600086115b156129a9578561285081615dd6565b9650506000846001600160a01b031663b72703ac836040518263ffffffff1660e01b8152600401612881919061568b565b602060405180830381865afa15801561289e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c29190615bb5565b90506128cd82613552565b505060006128e8868487600001518860c001518f8f8f614433565b90508060400151156128fb5750506129a9565b6040518060600160405280846001600160a01b031681526020018260000151815260200182602001518152508561012001518661010001805180919061294090615ded565b90528151811061295257612952615d5a565b6020026020010181905250806000015185602001516129719190615d10565b602080870191909152810151604086015161298c9190615d10565b60408601528051855161299f9190615c0c565b855250905061281d565b60008360400151116129fb5760405162461bcd60e51b815260206004820152601b60248201527a155b98589b19481d1bc81c995919595b48185b9e48185b5bdd5b9d602a1b6044820152606401610dd9565b612a1283604001518460c001518560e00151614748565b50600f5460ff16612a3757612a32612a2861123a565b84604001516147ca565b612a3a565b60005b606084018190526040840151612a5191908761483b565b6060830151601f5460009161271091612a759190600160c01b900461ffff16615c76565b612a7f9190615c35565b6101008501519091508115612b165760005b81811015612b145760008661012001518281518110612ab257612ab2615d5a565b602002602001015190508660400151816040015185612ad19190615c76565b612adb9190615c35565b81516001600160a01b0316600090815262020023602052604081208054909190612b06908490615d10565b909155505050600101612a91565b505b601f54612710600160c01b90910461ffff161015612bcf576000828660600151612b409190615c0c565b9050612bcd7f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b031663b3f006746040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc79190615bb5565b82614257565b505b84606001518560400151612be39190615c0c565b8560800181815250507f43a3f4082a4dbc33d78e317d2497d3a730bc7fc3574159dcea1056e62e5d9ad88d866020015187604001518860600151604051612c2d9493929190615a0a565b60405180910390a16020850151604051632770a7eb60e21b81526001600160a01b037f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb281691639dc29fac91612c86913391600401615d70565b600060405180830381600087803b158015612ca057600080fd5b505af1158015612cb4573d6000803e3d6000fd5b5050506020860151601a54612cc99250615c0c565b601a556080850151612cdc903390614257565b612ce46148ac565b6020546001600160a01b031615612d7457610120850180518290526020549051604051637cd347f560e11b81526001600160a01b039092169163f9a68fea91612d2f91600401615e06565b6020604051808303816000875af1158015612d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d729190615e68565b505b50505050505050505050505050565b6000611235612d90613f03565b613ac8565b612d9d6134ea565b60016001600160a01b038516600090815262020022602052604090206003015460ff166004811115612dd157612dd161586b565b14612dee5760405162461bcd60e51b8152600401610dd990615d89565b612df784613736565b612e02846002613785565b620200255415612e225780601a54612e1a9190615c0c565b601a55612e28565b6000601a555b612e328383614257565b612e3a6148ac565b836001600160a01b0316600080516020615f6683398151915260008060006001604051612e6a9493929190615c8d565b60405180910390a250505050565b601a5460009081612e87613f85565b9150508015612eb8576000612ea88383676765c793fa10079d601b1b613ff2565b9050612eb48184615d10565b9250505b50919050565b6001600160a01b03811660009081526202002460209081526040808320815180830190925280548083526001909101549282019290925260155483928391612f069190615c0c565b905060008260200151601654612f1c9190615c0c565b9050612f288183615d10565b1580612f66575060016001600160a01b038716600090815262020022602052604090206003015460ff166004811115612f6357612f6361586b565b14155b15612f7957506000958695509350505050565b6001600160a01b0386166000908152620200226020526040902060020154670de0b6b3a7640000612faa8483615c76565b612fb49190615c35565b670de0b6b3a7640000612fc78484615c76565b612fd19190615c35565b9550955050505050915091565b600080612fea33614904565b90508015613087576040516335e97f1f60e11b81526001600160a01b037f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c1690636bd2fe3e9061304290339087908690600401615e85565b6020604051808303816000875af1158015613061573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130859190615e68565b505b6040518181526001600160a01b0384169033907f0aa4d283470c904c551d18bb894d37e17674920f3261a7f854be501e25f421b79060200160405180910390a392915050565b60008060006130db85611247565b9150915060006130ec8383876149e2565b9695505050505050565b6131066301e13380612710615c76565b61311d676765c793fa10079d601b1b611388615c76565b6131279190615c35565b81565b6000611178613137612d83565b836147ca565b600062020025828154811061315457613154615d5a565b6000918252602090912001546001600160a01b031692915050565b60238161ffff811061318057600080fd5b0154905081565b600060016001600160a01b038316600090815262020022602052604090206003015460ff1660048111156131bd576131bd61586b565b146131ca57506000919050565b506015546001600160a01b0390911660009081526202002460205260409020541090565b6131f66136c4565b61320083836141c2565b61320a8382614257565b505050565b6001600160a01b038116600090815260226020526040812054601f54600160a01b900463ffffffff16428111156132435750425b601f5460009061326090600160801b900463ffffffff1683615c0c565b601e5490915081156132b857601a5480156132b657601f54819061328d906001600160801b031685615c76565b61329f90670de0b6b3a7640000615c76565b6132a99190615c35565b6132b39083615d10565b91505b505b6001600160a01b0386166000908152602160205260409020548082111561332857670de0b6b3a76400006132ec8284615c0c565b6001600160a01b03891660009081526202002260205260409020546133119190615c76565b61331b9190615c35565b6133259086615d10565b94505b61333187614a13565b61333b9086615d10565b979650505050505050565b61334e6136c4565b6133588585614b47565b60195483156133735761336b8482615c0c565b601981905590505b601254601355601c546133868383615c0c565b6133909190615d10565b60148190556013546040517f51bf4c63ec3cba9d03d43238abbdd979dd91bd16d9895c74ceea9118c7baaf60926133ce928252602082015260400190565b60405180910390a1604051631062c15f60e11b81526001600160a01b037f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2816906320c582be90613446907f000000000000000000000000e0598d793baf7b4f49f4a003885e4180b28cab61908b908890600401615e85565b600060405180830381600087803b15801561346057600080fd5b505af1158015613474573d6000803e3d6000fd5b505050506134828783614257565b50505050505050565b6134936136c4565b611e8c8282614cc0565b6000336001600160a01b037f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c16146134d457600080fd5b61227083614904565b6000611235601054613f53565b336001600160a01b037f00000000000000000000000072c590349535ad52e6953744cb2a36b4095427191614611b515760405162461bcd60e51b815260206004820152600d60248201526c43616c6c6572206e6f7420424f60981b6044820152606401610dd9565b6001600160a01b0381166000908152620200226020526040812081906001600382015460ff1660048111156135895761358961586b565b0361365a576004810154601a5460006135a0613660565b8454600186015497509550905084818410156135d557836135c18388615c76565b6135cb9190615c35565b6004860183905595505b6015546001600160a01b0389166000908152620200246020526040902054101561363f576000806136058a612ebe565b9092509050613614828a615d10565b6001880181905598506136278189615d10565b97506136328a613b43565b61363c8183614cc0565b50505b85811461364a578585555b613655888285613c3d565b505050505b50915091565b600080600061366d613f85565b90925090508015612eb857601a5460006136938284676765c793fa10079d601b1b613ff2565b905061369f8183615d10565b601a55601b546136b0908290615d10565b601b555050600c82905542600d5550919050565b336001600160a01b037f0000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e21614611b515760405162461bcd60e51b81526020600482015260176024820152762737ba102634b8bab4b230ba34b7b71026b0b730b3b2b960491b6044820152606401610dd9565b6001600160a01b0381166000908152620200226020526040902060020154601254613762908290615c0c565b601255506001600160a01b03166000908152620200226020526040812060020155565b62020025546001600160a01b0383166000908152620200226020526040902060038101805484919060ff191660018360048111156137c5576137c561586b565b021790555060006001808301829055818355600483018290556002546001600160a01b038781168452620200246020526040842084815583019390935591909116908311801561387657506001816001600160a01b031663de8fa4316040518163ffffffff1660e01b8152600401602060405180830381865afa158015613850573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138749190615c5d565b115b1561398457600382015461010090046001600160801b031660006202002561389f600187615c0c565b815481106138af576138af615d5a565b6000918252602090912001546202002580546001600160a01b03909216925082916001600160801b0385169081106138e9576138e9615d5a565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790559183168082526202002283526040918290206003018054610100600160881b0319166101006001600160801b038816908102919091179091558251918252928101929092527f02b04ae5f7be9ca7c103293a2aa15f3c339d15d6eda53b721fef7b0e609c831a910160405180910390a150505b6202002580548061399757613997615ea9565b600082815260209020810160001990810180546001600160a01b0319169055019055604051631484968760e11b81526001600160a01b038216906329092d0e906139e590889060040161568b565b600060405180830381600087803b1580156139ff57600080fd5b505af1158015613a13573d6000803e3d6000fd5b50505060039092018054610100600160881b03191690555050505050565b6001600160a01b03831660009081526021602052604090205480821115613ac257670de0b6b3a7640000613a658284615c0c565b613a6f9085615c76565b613a799190615c35565b6001600160a01b03851660009081526022602052604081208054909190613aa1908490615d10565b90915550506001600160a01b03841660009081526021602052604090208290555b50505050565b600061117882600654613adb9190615d10565b600754614d1d565b600080613aee613f03565b6010819055604051818152909150600080516020615f868339815191529060200160405180910390a1613b1f614d33565b919050565b6000670de0b6b3a7640000613b398385615c76565b6122709190615c35565b60155460165460408051808201825283815260208082018481526001600160a01b0387166000908152620200248352849020925183555160019092019190915581518481529081018390527fc437f324d85e369394148dd9d62f98f534b382e01ed3dd2eb98138fb6d3ab49a910160405180910390a1505050565b600080613bce8360010154614d83565b60028401805490829055601254919250906000908390613bef908490615c0c565b613bf99190615d10565b60128190556040518181529091507f6bac5e0eb3c44eb03a60ab11ec3a2c051771616aecadbcfff2630aabae5203829060200160405180910390a150909392505050565b6000613c4882614db5565b9050613ac2848483613a31565b6000613c6a68056bc75e2d6310000083615c35565b9050600080613c77610e21565b9150915082620100228361ffff8110613c9257613c92615d5a565b018260078110613ca457613ca4615d5a565b600891828204019190066004028282829054906101000a900463ffffffff16613ccd9190615ebf565b82546101009290920a63ffffffff8181021990931691831602179091556001600160a01b0387166000908152620200216020908152604091829020825160608101845290548085168252600160201b8104851692820192909252600160401b90910490921690820181905290915082148015613d52575082816020015163ffffffff16145b15613d9b578051613d64908590615ebf565b6001600160a01b03871660009081526202002160205260409020805463ffffffff191663ffffffff92909216919091179055613efb565b805163ffffffff1615613e7b57600062010022826020015163ffffffff1661ffff8110613dca57613dca615d5a565b01826040015163ffffffff1660078110613de657613de6615d5a565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16826000015163ffffffff166023846020015163ffffffff1661ffff8110613e3157613e31615d5a565b0154613e3d9190615c76565b613e479190615c35565b6001600160a01b038816600090815260226020526040812080549293508392909190613e74908490615d10565b9091555050505b6040805160608101825263ffffffff808716825285811660208084019182528683168486019081526001600160a01b038c1660009081526202002190925294902092518354915194518316600160401b0263ffffffff60401b19958416600160201b026001600160401b0319909316919093161717929092169190911790555b505050505050565b600080603c60115442613f169190615c0c565b613f209190615c35565b90506000613f3060055483614e71565b9050670de0b6b3a764000081601054613f499190615c76565b611caf9190615c35565b600061117882600854613f669190615d10565b600954614d1d565b613f79601a54614db5565b50613f82613660565b50565b600d546000908190428103613fa0575050600c549160009150565b600b54600c5493508015613fec576000613fba8342615c0c565b9050613fc68282615c76565b9350613fde8585676765c793fa10079d601b1b613ff2565b613fe89086615d10565b9450505b50509091565b600080806000198587098587029250828110838203039150508060000361402c5783828161402257614022615c1f565b0492505050612270565b80841161403857600080fd5b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b61320a8363a9059cbb60e01b84846040516024016140bf929190615d70565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614f1c565b600082601a546141069190615d10565b9050600a54601d54826141199190615d10565b11156141375760405162461bcd60e51b8152600401610dd990615d23565b601a8190556040516340c10f1960e01b81526001600160a01b037f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2816906340c10f199061418a9087908690600401615d70565b600060405180830381600087803b1580156141a457600080fd5b505af11580156141b8573d6000803e3d6000fd5b5050505050505050565b604051632770a7eb60e21b81526001600160a01b037f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb281690639dc29fac906142109085908590600401615d70565b600060405180830381600087803b15801561422a57600080fd5b505af115801561423e573d6000803e3d6000fd5b5050505080601a546142509190615c0c565b601a555050565b8015611e8c578060195461426b9190615c0c565b6019556040517f342693d2465f6f44931e41128424a0227e0cbc69d1c3917a839e6de71696d44c906142a09084908490615d70565b60405180910390a1600154611e8c906001600160a01b031683836140a0565b600081156142ec57816142db68056bc75e2d6310000085615c76565b6142e59190615c35565b9050611178565b50600019611178565b60006001600160a01b03841615806143775750604051630bb7c8fd60e31b81526001600160a01b03861690635dbe47e89061433490879060040161568b565b602060405180830381865afa158015614351573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143759190615e68565b155b8061438a57508161438885856130cd565b105b156143975750600061442b565b60405163765e015960e01b81526000906001600160a01b0387169063765e0159906143c690889060040161568b565b602060405180830381865afa1580156143e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144079190615bb5565b90506001600160a01b038116158061442757508261442582866130cd565b105b9150505b949350505050565b614459604051806060016040528060008152602001600081526020016000151581525090565b6001600160a01b0387166000908152620200226020526040902080546144ab9088906144a6907f00000000000000000000000000000000000000000000000ad78ebc5ac620000090615c0c565b614d1d565b80835286906144c390670de0b6b3a764000090615c76565b6144cd9190615c35565b6020830152815181546000916144e291615c0c565b90506000836020015183600101546144fa9190615c0c565b90507f00000000000000000000000000000000000000000000000ad78ebc5ac6200000820361459f5761452c8a613736565b6145378a6004613785565b6145628a7f00000000000000000000000000000000000000000000000ad78ebc5ac620000083614fee565b896001600160a01b0316600080516020615f66833981519152600080600060046040516145929493929190615c8d565b60405180910390a261473a565b60006145ab82846142bf565b905060008187116145c5576145c08783615c0c565b6145cf565b6145cf8288615c0c565b90506601c6bf5263400081118061466e57507f00000000000000000000000072c590349535ad52e6953744cb2a36b4095427196001600160a01b031663969c24526040518163ffffffff1660e01b8152600401602060405180830381865afa15801561463f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146639190615c5d565b61466c856150ec565b105b15614685575050600160408501525061333b915050565b5060405163015f109360e51b81526001600160a01b038d1690632be21260906146b8908e9085908d908d90600401615ce5565b600060405180830381600087803b1580156146d257600080fd5b505af11580156146e6573d6000803e3d6000fd5b50505083855550600184018290556146fd84613bbe565b508a6001600160a01b0316600080516020615f668339815191528484876002015460046040516147309493929190615c8d565b60405180910390a2505b505050979650505050505050565b600080614753613f03565b90506000836147628688615c76565b61476c9190615c35565b9050600061477b600283615c35565b6147859084615d10565b905061479981670de0b6b3a7640000614d1d565b6010819055604051818152909150600080516020615f868339815191529060200160405180910390a16130ec614d33565b600080670de0b6b3a76400006147e08486615c76565b6147ea9190615c35565b90508281106122705760405162461bcd60e51b815260206004820152601f60248201527f46656520657863656564732072657475726e656420636f6c6c61746572616c006044820152606401610dd9565b600082614850670de0b6b3a764000086615c76565b61485a9190615c35565b905081811115613ac25760405162461bcd60e51b815260206004820152601d60248201527f4665652065786365656465642070726f7669646564206d6178696d756d0000006044820152606401610dd9565b6202002554600003611b5157676765c793fa10079d601b1b600c5542600d55600060128190556013819055601481905560158190556016819055601781905560188190556019819055601a819055601c819055601d55565b60035460009061ffff1661494f5760405162461bcd60e51b815260206004820152601260248201527152657761726473206e6f742061637469766560701b6044820152606401610dd9565b61495882613552565b50506001600160a01b0382166000908152602260205260409020548015614993576001600160a01b0383166000908152602260205260408120555b600061499e84614a13565b905080156149db576149b08183615d10565b6001600160a01b0385166000908152620200216020526040902080546001600160601b031916905591505b5092915050565b60008215614a0a576000836149f78487615c76565b614a019190615c35565b91506122709050565b50600019612270565b6001600160a01b038116600090815262020021602090815260408083208151606081018352905463ffffffff808216808452600160201b8304821695840195909552600160401b90910416918101919091529015612eb857600080614a76610e21565b9150915080836040015163ffffffff16141580614a9d575081836020015163ffffffff1614155b15614b3f5762010022836020015163ffffffff1661ffff8110614ac257614ac2615d5a565b01836040015163ffffffff1660078110614ade57614ade615d5a565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16836000015163ffffffff166023856020015163ffffffff1661ffff8110614b2957614b29615d5a565b0154614b359190615c76565b61223f9190615c35565b505050919050565b81600003614b53575050565b601754600090614b6b670de0b6b3a764000084615c76565b614b759190615d10565b90506000601854670de0b6b3a764000085614b909190615c76565b614b9a9190615d10565b6012549091506000614bac8285615c35565b90506000614bba8385615c35565b9050614bc68383615c76565b614bd09086615c0c565b601755614bdd8382615c76565b614be79085615c0c565b601855601554600090614bfb908490615d10565b9050600082601654614c0d9190615d10565b6015839055601681905560408051848152602081018390529192507f9f8bc8ab0daf5bceef75ecfd2085d1fcc6548c657ea970d9a23a60610d0737e3910160405180910390a188601a6000828254614c659190615c0c565b9250508190555088601d6000828254614c7e9190615d10565b9250508190555087601c6000828254614c979190615d10565b925050819055508760196000828254614cb09190615c0c565b9091555050505050505050505050565b81601d6000828254614cd29190615c0c565b9250508190555081601a6000828254614ceb9190615d10565b9250508190555080601c6000828254614d049190615c0c565b925050819055508060196000828254611c599190615d10565b6000818310614d2c5781612270565b5090919050565b600060115442614d439190615c0c565b9050603c8110613f82574260118190556040519081527f860f8d2f0c74dd487e89e2883e3b25b8159ce1e1b3433a291cba7b82c508f3bc90602001611b17565b6014546000908190808203614d9a578391506149db565b60135480614daa57614daa615edc565b81614b358287615c76565b601f54600090600160a01b900463ffffffff168042811115614dd45750425b601f54600090614df190600160801b900463ffffffff1683615c0c565b601e54945090508015614e6857601f805463ffffffff60801b1916600160801b63ffffffff8516021790558415614e6857601f548590614e3a906001600160801b031683615c76565b614e4c90670de0b6b3a7640000615c76565b614e569190615c35565b614e609085615d10565b601e81905593505b614b3f83615118565b6000631f540500821115614e8757631f54050091505b81600003614e9e5750670de0b6b3a7640000611178565b670de0b6b3a764000083835b6001811115614f1257614ebe600282615c49565b600003614ee357614ecf82836154c6565b9150614edc600282615c35565b9050614eaa565b614eed82846154c6565b9250614ef982836154c6565b91506002614f08600183615c0c565b614edc9190615c35565b6130ec82846154c6565b6000614f71826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166154fd9092919063ffffffff16565b80519091501561320a5780806020019051810190614f8f9190615e68565b61320a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610dd9565b604051632770a7eb60e21b81526001600160a01b037f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb281690639dc29fac9061505c907f000000000000000000000000e0598d793baf7b4f49f4a003885e4180b28cab61908690600401615d70565b600060405180830381600087803b15801561507657600080fd5b505af115801561508a573d6000803e3d6000fd5b5050505081601a5461509c9190615c0c565b601a556001600160a01b0383166000908152620200236020526040812080548392906150c9908490615d10565b9250508190555080601960008282546150e29190615c0c565b9091555050505050565b60006111787f00000000000000000000000000000000000000000000000ad78ebc5ac620000083615c0c565b6040805180820190915260035461ffff80821680845262010000909204166020830152600003615146575050565b6000615150611e90565b905062093a806151807f0000000000000000000000000000000000000000000000000000000064d4288085615c0c565b61518a9190615c35565b81101561519657505050565b6000600162093a806151c87f0000000000000000000000000000000000000000000000000000000064d4288087615c0c565b6151d29190615c35565b6151dc9190615c0c565b835160405163378cbf7560e01b81529192506000916001600160a01b037f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c169163378cbf759161522f91906004016159c4565b6020604051808303816000875af115801561524e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152729190615c5d565b9050844210156152af5760006152884287615c0c565b601f549091506152a1906001600160801b031682615c76565b6152ab9083615d10565b9150505b6152bc62093a8082615c35565b601f805463ffffffff42908116600160801b026001600160a01b03199092166001600160801b0394909416939093171790556152fc9062093a8090615d10565b601f805463ffffffff92909216600160a01b0263ffffffff60a01b19909216919091179055602084015160405163378cbf7560e01b81526001600160a01b037f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c169163378cbf759161537191906004016159c4565b6020604051808303816000875af1158015615390573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906153b49190615c5d565b9050600060238361ffff81106153cc576153cc615d5a565b01549050801561549d576000620100228461ffff81106153ee576153ee615d5a565b6040805160e0810191829052929190910190600790826000855b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116154085790505050505050905060005b600781101561549a5781816007811061546957615469615d5a565b602002015163ffffffff16600003615488576154858385615d10565b93505b8061549281615ded565b91505061544e565b50505b6154a8600783615c35565b60238561ffff81106154bc576154bc615d5a565b0155505050505050565b6000806154d38385615c76565b9050670de0b6b3a76400006154e9600282615c35565b6154f39083615d10565b61442b9190615c35565b606061442b848460008585600080866001600160a01b031685876040516155249190615f16565b60006040518083038185875af1925050503d8060008114615561576040519150601f19603f3d011682016040523d82523d6000602084013e615566565b606091505b509150915061333b87838387606083156155e15782516000036155da576001600160a01b0385163b6155da5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dd9565b508161442b565b61442b83838151156155f65781518083602001fd5b8060405162461bcd60e51b8152600401610dd99190615f32565b6040518060e001604052806007906020820280368337509192915050565b6001600160a01b0381168114613f8257600080fd5b60006020828403121561565557600080fd5b81356122708161562e565b8015158114613f8257600080fd5b60006020828403121561568057600080fd5b813561227081615660565b6001600160a01b0391909116815260200190565b600080600080600080600080610100898b0312156156bc57600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b60008060006060848603121561570957600080fd5b83356157148161562e565b925060208401356157248161562e565b915060408401356157348161562e565b809150509250925092565b60006020828403121561575157600080fd5b5035919050565b600080600080600080600060e0888a03121561577357600080fd5b873561577e8161562e565b965060208801359550604088013594506060880135935060808801356157a38161562e565b925060a08801356157b38161562e565b915060c08801356157c381615660565b8091505092959891949750929550565b600080602083850312156157e657600080fd5b82356001600160401b03808211156157fd57600080fd5b818501915085601f83011261581157600080fd5b81358181111561582057600080fd5b8660208260051b850101111561583557600080fd5b60209290920196919550909350505050565b60006020828403121561585957600080fd5b813561ffff8116811461227057600080fd5b634e487b7160e01b600052602160045260246000fd5b60058110613f8257634e487b7160e01b600052602160045260246000fd5b868152602081018690526040810185905260c081016158bd85615881565b60608201949094526001600160801b0392909216608083015260a0909101529392505050565b600080604083850312156158f657600080fd5b82356159018161562e565b946020939093013593505050565b6000806000806000806000806000806101408b8d03121561592f57600080fd5b8a3561593a81615660565b995060208b013561594a81615660565b985060408b0135975060608b0135965060808b013561596881615660565b955060a08b0135945060c08b013561597f8161562e565b935060e08b013561598f8161562e565b92506101008b01356159a08161562e565b91506101208b01356159b18161562e565b809150509295989b9194979a5092959850565b61ffff91909116815260200190565b60e08101818360005b6007811015615a0157815163ffffffff168352602092830192909101906001016159dc565b50505092915050565b93845260208401929092526040830152606082015260800190565b600080600080600080600060e0888a031215615a4057600080fd5b873596506020880135615a528161562e565b95506040880135615a628161562e565b94506060880135615a728161562e565b9699959850939660808101359560a0820135955060c0909101359350915050565b60008060008060808587031215615aa957600080fd5b8435615ab48161562e565b93506020850135615ac48161562e565b93969395505050506040820135916060013590565b600080600060608486031215615aee57600080fd5b8335615af98161562e565b95602085013595506040909401359392505050565b60008060008060008060c08789031215615b2757600080fd5b8635615b328161562e565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b60008060408385031215615b6d57600080fd5b50508035926020909101359150565b60008060408385031215615b8f57600080fd5b8235615b9a8161562e565b91506020830135615baa8161562e565b809150509250929050565b600060208284031215615bc757600080fd5b81516122708161562e565b6020808252600a908201526927b7363c9037bbb732b960b11b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561117857611178615bf6565b634e487b7160e01b600052601260045260246000fd5b600082615c4457615c44615c1f565b500490565b600082615c5857615c58615c1f565b500690565b600060208284031215615c6f57600080fd5b5051919050565b808202811582820484141761117857611178615bf6565b848152602081018490526040810183905260808101615cab83615881565b82606083015295945050505050565b60208082526011908201527010dbdb1b185d195c985b0814185d5cd959607a1b604082015260600190565b6001600160a01b03948516815260208101939093529083166040830152909116606082015260800190565b8082018082111561117857611178615bf6565b6020808252601d908201527f436f6c6c61746572616c2064656274206c696d69742072656163686564000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03929092168252602082015260400190565b6020808252601e908201527f54726f766520636c6f736564206f7220646f6573206e6f742065786973740000604082015260600190565b634e487b7160e01b600052604160045260246000fd5b600081615de557615de5615bf6565b506000190190565b600060018201615dff57615dff615bf6565b5060010190565b602080825282518282018190526000919060409081850190868401855b82811015615e5b57815180516001600160a01b0316855286810151878601528501518585015260609093019290850190600101615e23565b5091979650505050505050565b600060208284031215615e7a57600080fd5b815161227081615660565b6001600160a01b039384168152919092166020820152604081019190915260600190565b634e487b7160e01b600052603160045260246000fd5b63ffffffff8181168382160190808211156149db576149db615bf6565b634e487b7160e01b600052600160045260246000fd5b60005b83811015615f0d578181015183820152602001615ef5565b50506000910152565b60008251615f28818460208701615ef2565b9190910192915050565b6020815260008251806020840152615f51816040850160208701615ef2565b601f01601f1916919091016040019291505056fec3770d654ed33aeea6bf11ac8ef05d02a6a04ed4686dd2f624d853bbec43cc8bc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600ca164736f6c6343000813000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf8000000000000000000000000e0598d793baf7b4f49f4a003885e4180b28cab610000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2800000000000000000000000072c590349535ad52e6953744cb2a36b40954271900000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c0000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e200000000000000000000000000000000000000000000000ad78ebc5ac62000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _prismaCore (address): 0x5d17eA085F2FF5da3e6979D5d26F1dBaB664ccf8
Arg [1] : _gasPoolAddress (address): 0xE0598D793bAf7b4f49F4a003885E4180B28caB61
Arg [2] : _debtTokenAddress (address): 0x4591DBfF62656E7859Afe5e45f6f47D3669fBB28
Arg [3] : _borrowerOperationsAddress (address): 0x72c590349535AD52e6953744cb2A36B409542719
Arg [4] : _vault (address): 0x06bDF212C290473dCACea9793890C5024c7Eb02c
Arg [5] : _liquidationManager (address): 0x5de309dfd7f94e9e2A18Cb6bA61CA305aBF8e9E2
Arg [6] : _gasCompensation (uint256): 200000000000000000000
Arg [7] : _bootstrapPeriod (uint256): 0
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf8
Arg [1] : 000000000000000000000000e0598d793baf7b4f49f4a003885e4180b28cab61
Arg [2] : 0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb28
Arg [3] : 00000000000000000000000072c590349535ad52e6953744cb2a36b409542719
Arg [4] : 00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c
Arg [5] : 0000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e2
Arg [6] : 00000000000000000000000000000000000000000000000ad78ebc5ac6200000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 33 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.