More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 6,126 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw From SP | 21829254 | 5 days ago | IN | 0 ETH | 0.00011588 | ||||
Provide To SP | 21805932 | 8 days ago | IN | 0 ETH | 0.00021008 | ||||
Provide To SP | 21777945 | 12 days ago | IN | 0 ETH | 0.0002877 | ||||
Provide To SP | 21757833 | 15 days ago | IN | 0 ETH | 0.00065056 | ||||
Withdraw From SP | 21754398 | 15 days ago | IN | 0 ETH | 0.00037576 | ||||
Withdraw From SP | 21727969 | 19 days ago | IN | 0 ETH | 0.00033187 | ||||
Provide To SP | 21686651 | 25 days ago | IN | 0 ETH | 0.00170778 | ||||
Withdraw From SP | 21672397 | 27 days ago | IN | 0 ETH | 0.00239579 | ||||
Provide To SP | 21652754 | 29 days ago | IN | 0 ETH | 0.00688543 | ||||
Withdraw From SP | 21624118 | 33 days ago | IN | 0 ETH | 0.0017955 | ||||
Withdraw From SP | 21617988 | 34 days ago | IN | 0 ETH | 0.00104491 | ||||
Withdraw From SP | 21594034 | 38 days ago | IN | 0 ETH | 0.00070334 | ||||
Withdraw From SP | 21593812 | 38 days ago | IN | 0 ETH | 0.00084571 | ||||
Withdraw From SP | 21592888 | 38 days ago | IN | 0 ETH | 0.00073247 | ||||
Provide To SP | 21591944 | 38 days ago | IN | 0 ETH | 0.00076199 | ||||
Withdraw From SP | 21587910 | 38 days ago | IN | 0 ETH | 0.00161238 | ||||
Provide To SP | 21587009 | 39 days ago | IN | 0 ETH | 0.00139231 | ||||
Provide To SP | 21579718 | 40 days ago | IN | 0 ETH | 0.00124866 | ||||
Provide To SP | 21578675 | 40 days ago | IN | 0 ETH | 0.00177006 | ||||
Withdraw From SP | 21574293 | 40 days ago | IN | 0 ETH | 0.00221547 | ||||
Claim Collateral... | 21569227 | 41 days ago | IN | 0 ETH | 0.00125 | ||||
Withdraw From SP | 21565766 | 42 days ago | IN | 0 ETH | 0.00124205 | ||||
Claim Reward | 21563754 | 42 days ago | IN | 0 ETH | 0.00135088 | ||||
Provide To SP | 21562875 | 42 days ago | IN | 0 ETH | 0.00082297 | ||||
Withdraw From SP | 21543877 | 45 days ago | IN | 0 ETH | 0.00127135 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
StabilityPool
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 "SafeERC20.sol"; import "IERC20.sol"; import "PrismaOwnable.sol"; import "SystemStart.sol"; import "PrismaMath.sol"; import "IDebtToken.sol"; import "IVault.sol"; /** @title Prisma Stability Pool @notice Based on Liquity's `StabilityPool` https://github.com/liquity/dev/blob/main/packages/contracts/contracts/StabilityPool.sol Prisma's implementation is modified to support multiple collaterals. Deposits into the stability pool may be used to liquidate any supported collateral type. */ contract StabilityPool is PrismaOwnable, SystemStart { using SafeERC20 for IERC20; uint256 public constant DECIMAL_PRECISION = 1e18; uint128 public constant SUNSET_DURATION = 180 days; uint256 constant REWARD_DURATION = 1 weeks; uint256 public constant emissionId = 0; IDebtToken public immutable debtToken; IPrismaVault public immutable vault; address public immutable factory; address public immutable liquidationManager; uint128 public rewardRate; uint32 public lastUpdate; uint32 public periodFinish; mapping(IERC20 collateral => uint256 index) public indexByCollateral; IERC20[] public collateralTokens; // Tracker for Debt held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset. uint256 internal totalDebtTokenDeposits; mapping(address => AccountDeposit) public accountDeposits; // depositor address -> initial deposit mapping(address => Snapshots) public depositSnapshots; // depositor address -> snapshots struct // index values are mapped against the values within `collateralTokens` mapping(address => uint256[256]) public depositSums; // depositor address -> sums mapping(address depositor => uint80[256] gains) public collateralGainsByDepositor; mapping(address depositor => uint256 rewards) private storedPendingReward; /* Product 'P': Running product by which to multiply an initial deposit, in order to find the current compounded deposit, * after a series of liquidations have occurred, each of which cancel some debt with the deposit. * * During its lifetime, a deposit's value evolves from d_t to d_t * P / P_t , where P_t * is the snapshot of P taken at the instant the deposit was made. 18-digit decimal. */ uint256 public P = DECIMAL_PRECISION; uint256 public constant SCALE_FACTOR = 1e9; // Each time the scale of P shifts by SCALE_FACTOR, the scale is incremented by 1 uint128 public currentScale; // With each offset that fully empties the Pool, the epoch is incremented by 1 uint128 public currentEpoch; /* collateral Gain sum 'S': During its lifetime, each deposit d_t earns a collateral gain of ( d_t * [S - S_t] )/P_t, where S_t * is the depositor's snapshot of S taken at the time t when the deposit was made. * * The 'S' sums are stored in a nested mapping (epoch => scale => sum): * * - The inner mapping records the sum S at different scales * - The outer mapping records the (scale => sum) mappings, for different epochs. */ // index values are mapped against the values within `collateralTokens` mapping(uint128 => mapping(uint128 => uint256[256])) public epochToScaleToSums; /* * Similarly, the sum 'G' is used to calculate Prisma gains. During it's lifetime, each deposit d_t earns a Prisma gain of * ( d_t * [G - G_t] )/P_t, where G_t is the depositor's snapshot of G taken at time t when the deposit was made. * * Prisma reward events occur are triggered by depositor operations (new deposit, topup, withdrawal), and liquidations. * In each case, the Prisma reward is issued (i.e. G is updated), before other state changes are made. */ mapping(uint128 => mapping(uint128 => uint256)) public epochToScaleToG; // Error tracker for the error correction in the Prisma issuance calculation uint256 public lastPrismaError; // Error trackers for the error correction in the offset calculation uint256 public lastCollateralError_Offset; uint256 public lastDebtLossError_Offset; mapping(uint16 => SunsetIndex) _sunsetIndexes; Queue queue; struct AccountDeposit { uint128 amount; uint128 timestamp; // timestamp of the last deposit } struct Snapshots { uint256 P; uint256 G; uint128 scale; uint128 epoch; } struct SunsetIndex { uint128 idx; uint128 expiry; } struct Queue { uint16 firstSunsetIndexKey; uint16 nextSunsetIndexKey; } event StabilityPoolDebtBalanceUpdated(uint256 _newBalance); event P_Updated(uint256 _P); event S_Updated(uint256 idx, uint256 _S, uint128 _epoch, uint128 _scale); event G_Updated(uint256 _G, uint128 _epoch, uint128 _scale); event EpochUpdated(uint128 _currentEpoch); event ScaleUpdated(uint128 _currentScale); event DepositSnapshotUpdated(address indexed _depositor, uint256 _P, uint256 _G); event UserDepositChanged(address indexed _depositor, uint256 _newDeposit); event CollateralGainWithdrawn(address indexed _depositor, uint256[] _collateral); event CollateralOverwritten(IERC20 oldCollateral, IERC20 newCollateral); event RewardClaimed(address indexed account, address indexed recipient, uint256 claimed); constructor( address _prismaCore, IDebtToken _debtTokenAddress, IPrismaVault _vault, address _factory, address _liquidationManager ) PrismaOwnable(_prismaCore) SystemStart(_prismaCore) { debtToken = _debtTokenAddress; vault = _vault; factory = _factory; liquidationManager = _liquidationManager; periodFinish = uint32(block.timestamp - 1); } function enableCollateral(IERC20 _collateral) external { require(msg.sender == factory, "Not factory"); uint256 length = collateralTokens.length; bool collateralEnabled; for (uint256 i = 0; i < length; i++) { if (collateralTokens[i] == _collateral) { collateralEnabled = true; break; } } if (!collateralEnabled) { Queue memory queueCached = queue; if (queueCached.nextSunsetIndexKey > queueCached.firstSunsetIndexKey) { SunsetIndex memory sIdx = _sunsetIndexes[queueCached.firstSunsetIndexKey]; if (sIdx.expiry < block.timestamp) { delete _sunsetIndexes[queue.firstSunsetIndexKey++]; _overwriteCollateral(_collateral, sIdx.idx); return; } } collateralTokens.push(_collateral); indexByCollateral[_collateral] = collateralTokens.length; } else { // revert if the factory is trying to deploy a new TM with a sunset collateral require(indexByCollateral[_collateral] > 0, "Collateral is sunsetting"); } } function _overwriteCollateral(IERC20 _newCollateral, uint256 idx) internal { require(indexByCollateral[_newCollateral] == 0, "Collateral must be sunset"); uint256 length = collateralTokens.length; require(idx < length, "Index too large"); uint256 externalLoopEnd = currentEpoch; uint256 internalLoopEnd = currentScale; for (uint128 i; i <= externalLoopEnd; ) { for (uint128 j; j <= internalLoopEnd; ) { epochToScaleToSums[i][j][idx] = 0; unchecked { ++j; } } unchecked { ++i; } } indexByCollateral[_newCollateral] = idx + 1; emit CollateralOverwritten(collateralTokens[idx], _newCollateral); collateralTokens[idx] = _newCollateral; } /** * @notice Starts sunsetting a collateral * During sunsetting liquidated collateral handoff to the SP will revert @dev IMPORTANT: When sunsetting a collateral, `TroveManager.startSunset` should be called on all TM linked to that collateral @param collateral Collateral to sunset */ function startCollateralSunset(IERC20 collateral) external onlyOwner { require(indexByCollateral[collateral] > 0, "Collateral already sunsetting"); _sunsetIndexes[queue.nextSunsetIndexKey++] = SunsetIndex( uint128(indexByCollateral[collateral] - 1), uint128(block.timestamp + SUNSET_DURATION) ); delete indexByCollateral[collateral]; //This will prevent calls to the SP in case of liquidations } function getTotalDebtTokenDeposits() external view returns (uint256) { return totalDebtTokenDeposits; } // --- External Depositor Functions --- /* provideToSP(): * * - Triggers a Prisma issuance, based on time passed since the last issuance. The Prisma issuance is shared between *all* depositors and front ends * - Tags the deposit with the provided front end tag param, if it's a new deposit * - Sends depositor's accumulated gains (Prisma, collateral) to depositor * - Sends the tagged front end's accumulated Prisma gains to the tagged front end * - Increases deposit and tagged front end's stake, and takes new snapshots for each. */ function provideToSP(uint256 _amount) external { require(!PRISMA_CORE.paused(), "Deposits are paused"); require(_amount > 0, "StabilityPool: Amount must be non-zero"); _triggerRewardIssuance(); _accrueDepositorCollateralGain(msg.sender); uint256 compoundedDebtDeposit = getCompoundedDebtDeposit(msg.sender); _accrueRewards(msg.sender); debtToken.sendToSP(msg.sender, _amount); uint256 newTotalDebtTokenDeposits = totalDebtTokenDeposits + _amount; totalDebtTokenDeposits = newTotalDebtTokenDeposits; emit StabilityPoolDebtBalanceUpdated(newTotalDebtTokenDeposits); uint256 newDeposit = compoundedDebtDeposit + _amount; accountDeposits[msg.sender] = AccountDeposit({ amount: uint128(newDeposit), timestamp: uint128(block.timestamp) }); _updateSnapshots(msg.sender, newDeposit); emit UserDepositChanged(msg.sender, newDeposit); } /* withdrawFromSP(): * * - Triggers a Prisma issuance, based on time passed since the last issuance. The Prisma issuance is shared between *all* depositors and front ends * - Removes the deposit's front end tag if it is a full withdrawal * - Sends all depositor's accumulated gains (Prisma, collateral) to depositor * - Sends the tagged front end's accumulated Prisma gains to the tagged front end * - Decreases deposit and tagged front end's stake, and takes new snapshots for each. * * If _amount > userDeposit, the user withdraws all of their compounded deposit. */ function withdrawFromSP(uint256 _amount) external { uint256 initialDeposit = accountDeposits[msg.sender].amount; uint128 depositTimestamp = accountDeposits[msg.sender].timestamp; require(initialDeposit > 0, "StabilityPool: User must have a non-zero deposit"); require(depositTimestamp < block.timestamp, "!Deposit and withdraw same block"); _triggerRewardIssuance(); _accrueDepositorCollateralGain(msg.sender); uint256 compoundedDebtDeposit = getCompoundedDebtDeposit(msg.sender); uint256 debtToWithdraw = PrismaMath._min(_amount, compoundedDebtDeposit); _accrueRewards(msg.sender); if (debtToWithdraw > 0) { debtToken.returnFromPool(address(this), msg.sender, debtToWithdraw); _decreaseDebt(debtToWithdraw); } // Update deposit uint256 newDeposit = compoundedDebtDeposit - debtToWithdraw; accountDeposits[msg.sender] = AccountDeposit({ amount: uint128(newDeposit), timestamp: depositTimestamp }); _updateSnapshots(msg.sender, newDeposit); emit UserDepositChanged(msg.sender, newDeposit); } // --- Prisma issuance functions --- function _triggerRewardIssuance() internal { _updateG(_vestedEmissions()); uint256 _periodFinish = periodFinish; uint256 lastUpdateWeek = (_periodFinish - startTime) / 1 weeks; // If the last claim was a week earlier we reclaim if (getWeek() >= lastUpdateWeek) { uint256 amount = vault.allocateNewEmissions(emissionId); if (amount > 0) { // If the previous period is not finished we combine new and pending old rewards if (block.timestamp < _periodFinish) { uint256 remaining = _periodFinish - block.timestamp; amount += remaining * rewardRate; } rewardRate = uint128(amount / REWARD_DURATION); periodFinish = uint32(block.timestamp + REWARD_DURATION); } } lastUpdate = uint32(block.timestamp); } function _vestedEmissions() internal view returns (uint256) { uint256 updated = periodFinish; // Period is not ended we max at current timestamp if (updated > block.timestamp) updated = block.timestamp; // if the last update was after the current update time it means all rewards have been vested already uint256 lastUpdateCached = lastUpdate; if (lastUpdateCached >= updated) return 0; //Nothing to claim uint256 duration = updated - lastUpdateCached; return duration * rewardRate; } function _updateG(uint256 _prismaIssuance) internal { uint256 totalDebt = totalDebtTokenDeposits; // cached to save an SLOAD /* * When total deposits is 0, G is not updated. In this case, the Prisma issued can not be obtained by later * depositors - it is missed out on, and remains in the balanceof the Treasury contract. * */ if (totalDebt == 0 || _prismaIssuance == 0) { return; } uint256 prismaPerUnitStaked; prismaPerUnitStaked = _computePrismaPerUnitStaked(_prismaIssuance, totalDebt); uint128 currentEpochCached = currentEpoch; uint128 currentScaleCached = currentScale; uint256 marginalPrismaGain = prismaPerUnitStaked * P; uint256 newG = epochToScaleToG[currentEpochCached][currentScaleCached] + marginalPrismaGain; epochToScaleToG[currentEpochCached][currentScaleCached] = newG; emit G_Updated(newG, currentEpochCached, currentScaleCached); } function _computePrismaPerUnitStaked( uint256 _prismaIssuance, uint256 _totalDebtTokenDeposits ) internal returns (uint256) { /* * Calculate the Prisma-per-unit staked. Division uses a "feedback" error correction, to keep the * cumulative error low in the running total G: * * 1) Form a numerator which compensates for the floor division error that occurred the last time this * function was called. * 2) Calculate "per-unit-staked" ratio. * 3) Multiply the ratio back by its denominator, to reveal the current floor division error. * 4) Store this error 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 prismaNumerator = (_prismaIssuance * DECIMAL_PRECISION) + lastPrismaError; uint256 prismaPerUnitStaked = prismaNumerator / _totalDebtTokenDeposits; lastPrismaError = prismaNumerator - (prismaPerUnitStaked * _totalDebtTokenDeposits); return prismaPerUnitStaked; } // --- Liquidation functions --- /* * Cancels out the specified debt against the Debt contained in the Stability Pool (as far as possible) */ function offset(IERC20 collateral, uint256 _debtToOffset, uint256 _collToAdd) external virtual { _offset(collateral, _debtToOffset, _collToAdd); } function _offset(IERC20 collateral, uint256 _debtToOffset, uint256 _collToAdd) internal { require(msg.sender == liquidationManager, "StabilityPool: Caller is not Liquidation Manager"); uint256 idx = indexByCollateral[collateral]; idx -= 1; uint256 totalDebt = totalDebtTokenDeposits; // cached to save an SLOAD if (totalDebt == 0 || _debtToOffset == 0) { return; } _triggerRewardIssuance(); (uint256 collateralGainPerUnitStaked, uint256 debtLossPerUnitStaked) = _computeRewardsPerUnitStaked( _collToAdd, _debtToOffset, totalDebt ); _updateRewardSumAndProduct(collateralGainPerUnitStaked, debtLossPerUnitStaked, idx); // updates S and P // Cancel the liquidated Debt debt with the Debt in the stability pool _decreaseDebt(_debtToOffset); } // --- Offset helper functions --- function _computeRewardsPerUnitStaked( uint256 _collToAdd, uint256 _debtToOffset, uint256 _totalDebtTokenDeposits ) internal returns (uint256 collateralGainPerUnitStaked, uint256 debtLossPerUnitStaked) { /* * Compute the Debt and collateral rewards. Uses a "feedback" error correction, to keep * the cumulative error in the P and S state variables low: * * 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 = (_collToAdd * DECIMAL_PRECISION) + lastCollateralError_Offset; if (_debtToOffset == _totalDebtTokenDeposits) { debtLossPerUnitStaked = DECIMAL_PRECISION; // When the Pool depletes to 0, so does each deposit lastDebtLossError_Offset = 0; } else { uint256 debtLossNumerator = (_debtToOffset * DECIMAL_PRECISION) - lastDebtLossError_Offset; /* * Add 1 to make error in quotient positive. We want "slightly too much" Debt loss, * which ensures the error in any given compoundedDebtDeposit favors the Stability Pool. */ debtLossPerUnitStaked = (debtLossNumerator / _totalDebtTokenDeposits) + 1; lastDebtLossError_Offset = (debtLossPerUnitStaked * _totalDebtTokenDeposits) - debtLossNumerator; } collateralGainPerUnitStaked = collateralNumerator / _totalDebtTokenDeposits; lastCollateralError_Offset = collateralNumerator - (collateralGainPerUnitStaked * _totalDebtTokenDeposits); return (collateralGainPerUnitStaked, debtLossPerUnitStaked); } // Update the Stability Pool reward sum S and product P function _updateRewardSumAndProduct( uint256 _collateralGainPerUnitStaked, uint256 _debtLossPerUnitStaked, uint256 idx ) internal { uint256 currentP = P; uint256 newP; /* * The newProductFactor is the factor by which to change all deposits, due to the depletion of Stability Pool Debt in the liquidation. * We make the product factor 0 if there was a pool-emptying. Otherwise, it is (1 - DebtLossPerUnitStaked) */ uint256 newProductFactor = uint256(DECIMAL_PRECISION) - _debtLossPerUnitStaked; uint128 currentScaleCached = currentScale; uint128 currentEpochCached = currentEpoch; uint256 currentS = epochToScaleToSums[currentEpochCached][currentScaleCached][idx]; /* * Calculate the new S first, before we update P. * The collateral gain for any given depositor from a liquidation depends on the value of their deposit * (and the value of totalDeposits) prior to the Stability being depleted by the debt in the liquidation. * * Since S corresponds to collateral gain, and P to deposit loss, we update S first. */ uint256 marginalCollateralGain = _collateralGainPerUnitStaked * currentP; uint256 newS = currentS + marginalCollateralGain; epochToScaleToSums[currentEpochCached][currentScaleCached][idx] = newS; emit S_Updated(idx, newS, currentEpochCached, currentScaleCached); // If the Stability Pool was emptied, increment the epoch, and reset the scale and product P if (newProductFactor == 0) { currentEpoch = currentEpochCached + 1; emit EpochUpdated(currentEpoch); currentScale = 0; emit ScaleUpdated(currentScale); newP = DECIMAL_PRECISION; // If multiplying P by a non-zero product factor would reduce P below the scale boundary, increment the scale } else if ((currentP * newProductFactor) / DECIMAL_PRECISION < SCALE_FACTOR) { newP = (currentP * newProductFactor * SCALE_FACTOR) / DECIMAL_PRECISION; currentScale = currentScaleCached + 1; emit ScaleUpdated(currentScale); } else { newP = (currentP * newProductFactor) / DECIMAL_PRECISION; } require(newP > 0, "NewP"); P = newP; emit P_Updated(newP); } function _decreaseDebt(uint256 _amount) internal { uint256 newTotalDebtTokenDeposits = totalDebtTokenDeposits - _amount; totalDebtTokenDeposits = newTotalDebtTokenDeposits; emit StabilityPoolDebtBalanceUpdated(newTotalDebtTokenDeposits); } // --- Reward calculator functions for depositor and front end --- /* Calculates the collateral gain earned by the deposit since its last snapshots were taken. * Given by the formula: E = d0 * (S - S(0))/P(0) * where S(0) and P(0) are the depositor's snapshots of the sum S and product P, respectively. * d0 is the last recorded deposit value. */ function getDepositorCollateralGain(address _depositor) external view returns (uint256[] memory collateralGains) { collateralGains = new uint256[](collateralTokens.length); uint256 P_Snapshot = depositSnapshots[_depositor].P; if (P_Snapshot == 0) return collateralGains; uint80[256] storage depositorGains = collateralGainsByDepositor[_depositor]; uint256 initialDeposit = accountDeposits[_depositor].amount; uint128 epochSnapshot = depositSnapshots[_depositor].epoch; uint128 scaleSnapshot = depositSnapshots[_depositor].scale; uint256[256] storage sums = epochToScaleToSums[epochSnapshot][scaleSnapshot]; uint256[256] storage nextSums = epochToScaleToSums[epochSnapshot][scaleSnapshot + 1]; uint256[256] storage depSums = depositSums[_depositor]; for (uint256 i = 0; i < collateralGains.length; i++) { collateralGains[i] = depositorGains[i]; if (sums[i] == 0) continue; // Collateral was overwritten or not gains uint256 firstPortion = sums[i] - depSums[i]; uint256 secondPortion = nextSums[i] / SCALE_FACTOR; collateralGains[i] += (initialDeposit * (firstPortion + secondPortion)) / P_Snapshot / DECIMAL_PRECISION; } return collateralGains; } function _accrueDepositorCollateralGain(address _depositor) private returns (bool hasGains) { uint80[256] storage depositorGains = collateralGainsByDepositor[_depositor]; uint256 collaterals = collateralTokens.length; uint256 initialDeposit = accountDeposits[_depositor].amount; hasGains = false; if (initialDeposit == 0) { return hasGains; } uint128 epochSnapshot = depositSnapshots[_depositor].epoch; uint128 scaleSnapshot = depositSnapshots[_depositor].scale; uint256 P_Snapshot = depositSnapshots[_depositor].P; uint256[256] storage sums = epochToScaleToSums[epochSnapshot][scaleSnapshot]; uint256[256] storage nextSums = epochToScaleToSums[epochSnapshot][scaleSnapshot + 1]; uint256[256] storage depSums = depositSums[_depositor]; for (uint256 i = 0; i < collaterals; i++) { if (sums[i] == 0) continue; // Collateral was overwritten or not gains hasGains = true; uint256 firstPortion = sums[i] - depSums[i]; uint256 secondPortion = nextSums[i] / SCALE_FACTOR; depositorGains[i] += uint80( (initialDeposit * (firstPortion + secondPortion)) / P_Snapshot / DECIMAL_PRECISION ); } return (hasGains); } /* * Calculate the Prisma gain earned by a deposit since its last snapshots were taken. * Given by the formula: Prisma = d0 * (G - G(0))/P(0) * where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively. * d0 is the last recorded deposit value. */ function claimableReward(address _depositor) external view returns (uint256) { uint256 totalDebt = totalDebtTokenDeposits; uint256 initialDeposit = accountDeposits[_depositor].amount; if (totalDebt == 0 || initialDeposit == 0) { return 0; } uint256 prismaNumerator = (_vestedEmissions() * DECIMAL_PRECISION) + lastPrismaError; uint256 prismaPerUnitStaked = prismaNumerator / totalDebt; uint256 marginalPrismaGain = prismaPerUnitStaked * P; Snapshots memory snapshots = depositSnapshots[_depositor]; uint128 epochSnapshot = snapshots.epoch; uint128 scaleSnapshot = snapshots.scale; uint256 firstPortion; uint256 secondPortion; if (scaleSnapshot == currentScale) { firstPortion = epochToScaleToG[epochSnapshot][scaleSnapshot] - snapshots.G + marginalPrismaGain; secondPortion = epochToScaleToG[epochSnapshot][scaleSnapshot + 1] / SCALE_FACTOR; } else { firstPortion = epochToScaleToG[epochSnapshot][scaleSnapshot] - snapshots.G; secondPortion = (epochToScaleToG[epochSnapshot][scaleSnapshot + 1] + marginalPrismaGain) / SCALE_FACTOR; } return (initialDeposit * (firstPortion + secondPortion)) / snapshots.P / DECIMAL_PRECISION; } function _claimableReward(address _depositor) private view returns (uint256) { uint256 initialDeposit = accountDeposits[_depositor].amount; if (initialDeposit == 0) { return 0; } Snapshots memory snapshots = depositSnapshots[_depositor]; return _getPrismaGainFromSnapshots(initialDeposit, snapshots); } function _getPrismaGainFromSnapshots( uint256 initialStake, Snapshots memory snapshots ) internal view returns (uint256) { /* * Grab the sum 'G' from the epoch at which the stake was made. The Prisma gain may span up to one scale change. * If it does, the second portion of the Prisma gain is scaled by 1e9. * If the gain spans no scale change, the second portion will be 0. */ uint128 epochSnapshot = snapshots.epoch; uint128 scaleSnapshot = snapshots.scale; uint256 G_Snapshot = snapshots.G; uint256 P_Snapshot = snapshots.P; uint256 firstPortion = epochToScaleToG[epochSnapshot][scaleSnapshot] - G_Snapshot; uint256 secondPortion = epochToScaleToG[epochSnapshot][scaleSnapshot + 1] / SCALE_FACTOR; uint256 prismaGain = (initialStake * (firstPortion + secondPortion)) / P_Snapshot / DECIMAL_PRECISION; return prismaGain; } // --- Compounded deposit and compounded front end stake --- /* * Return the user's compounded deposit. Given by the formula: d = d0 * P/P(0) * where P(0) is the depositor's snapshot of the product P, taken when they last updated their deposit. */ function getCompoundedDebtDeposit(address _depositor) public view returns (uint256) { uint256 initialDeposit = accountDeposits[_depositor].amount; if (initialDeposit == 0) { return 0; } Snapshots memory snapshots = depositSnapshots[_depositor]; uint256 compoundedDeposit = _getCompoundedStakeFromSnapshots(initialDeposit, snapshots); return compoundedDeposit; } // Internal function, used to calculcate compounded deposits and compounded front end stakes. function _getCompoundedStakeFromSnapshots( uint256 initialStake, Snapshots memory snapshots ) internal view returns (uint256) { uint256 snapshot_P = snapshots.P; uint128 scaleSnapshot = snapshots.scale; uint128 epochSnapshot = snapshots.epoch; // If stake was made before a pool-emptying event, then it has been fully cancelled with debt -- so, return 0 if (epochSnapshot < currentEpoch) { return 0; } uint256 compoundedStake; uint128 scaleDiff = currentScale - scaleSnapshot; /* Compute the compounded stake. If a scale change in P was made during the stake's lifetime, * account for it. If more than one scale change was made, then the stake has decreased by a factor of * at least 1e-9 -- so return 0. */ if (scaleDiff == 0) { compoundedStake = (initialStake * P) / snapshot_P; } else if (scaleDiff == 1) { compoundedStake = (initialStake * P) / snapshot_P / SCALE_FACTOR; } else { // if scaleDiff >= 2 compoundedStake = 0; } /* * If compounded deposit is less than a billionth of the initial deposit, return 0. * * NOTE: originally, this line was in place to stop rounding errors making the deposit too large. However, the error * corrections should ensure the error in P "favors the Pool", i.e. any given compounded deposit should slightly less * than it's theoretical value. * * Thus it's unclear whether this line is still really needed. */ if (compoundedStake < initialStake / 1e9) { return 0; } return compoundedStake; } // --- Sender functions for Debt deposit, collateral gains and Prisma gains --- function claimCollateralGains(address recipient, uint256[] calldata collateralIndexes) external virtual { _claimCollateralGains(recipient, collateralIndexes); } function _claimCollateralGains(address recipient, uint256[] calldata collateralIndexes) internal { uint256 loopEnd = collateralIndexes.length; uint256[] memory collateralGains = new uint256[](collateralTokens.length); uint80[256] storage depositorGains = collateralGainsByDepositor[msg.sender]; for (uint256 i; i < loopEnd; ) { uint256 collateralIndex = collateralIndexes[i]; uint256 gains = depositorGains[collateralIndex]; if (gains > 0) { collateralGains[collateralIndex] = gains; depositorGains[collateralIndex] = 0; collateralTokens[collateralIndex].safeTransfer(recipient, gains); } unchecked { ++i; } } emit CollateralGainWithdrawn(msg.sender, collateralGains); } // --- Stability Pool Deposit Functionality --- function _updateSnapshots(address _depositor, uint256 _newValue) internal { uint256 length; if (_newValue == 0) { delete depositSnapshots[_depositor]; length = collateralTokens.length; for (uint256 i = 0; i < length; i++) { depositSums[_depositor][i] = 0; } emit DepositSnapshotUpdated(_depositor, 0, 0); return; } uint128 currentScaleCached = currentScale; uint128 currentEpochCached = currentEpoch; uint256 currentP = P; // Get S and G for the current epoch and current scale uint256[256] storage currentS = epochToScaleToSums[currentEpochCached][currentScaleCached]; uint256 currentG = epochToScaleToG[currentEpochCached][currentScaleCached]; // Record new snapshots of the latest running product P, sum S, and sum G, for the depositor depositSnapshots[_depositor].P = currentP; depositSnapshots[_depositor].G = currentG; depositSnapshots[_depositor].scale = currentScaleCached; depositSnapshots[_depositor].epoch = currentEpochCached; length = collateralTokens.length; for (uint256 i = 0; i < length; i++) { depositSums[_depositor][i] = currentS[i]; } emit DepositSnapshotUpdated(_depositor, currentP, currentG); } //This assumes the snapshot gets updated in the caller function _accrueRewards(address _depositor) internal { uint256 amount = _claimableReward(_depositor); storedPendingReward[_depositor] = storedPendingReward[_depositor] + amount; } function claimReward(address recipient) external returns (uint256 amount) { amount = _claimReward(msg.sender); if (amount > 0) { vault.transferAllocatedTokens(msg.sender, recipient, amount); } emit RewardClaimed(msg.sender, recipient, amount); return amount; } function vaultClaimReward(address claimant, address) external returns (uint256 amount) { require(msg.sender == address(vault)); return _claimReward(claimant); } function _claimReward(address account) internal returns (uint256 amount) { uint256 initialDeposit = accountDeposits[account].amount; if (initialDeposit > 0) { uint128 depositTimestamp = accountDeposits[account].timestamp; _triggerRewardIssuance(); bool hasGains = _accrueDepositorCollateralGain(account); uint256 compoundedDebtDeposit = getCompoundedDebtDeposit(account); uint256 debtLoss = initialDeposit - compoundedDebtDeposit; amount = _claimableReward(account); // we update only if the snapshot has changed if (debtLoss > 0 || hasGains || amount > 0) { // Update deposit uint256 newDeposit = compoundedDebtDeposit; accountDeposits[account] = AccountDeposit({ amount: uint128(newDeposit), timestamp: depositTimestamp }); _updateSnapshots(account, newDeposit); } } uint256 pending = storedPendingReward[account]; if (pending > 0) { amount += pending; storedPendingReward[account] = 0; } return amount; } }
// 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 "draft-IERC20Permit.sol"; import "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.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) (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 pragma solidity 0.8.19; import "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.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.19; import "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.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.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 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", "optimizer": { "enabled": true, "runs": 200 }, "libraries": { "StabilityPool.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_prismaCore","type":"address"},{"internalType":"contract IDebtToken","name":"_debtTokenAddress","type":"address"},{"internalType":"contract IPrismaVault","name":"_vault","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_liquidationManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_depositor","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"_collateral","type":"uint256[]"}],"name":"CollateralGainWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IERC20","name":"oldCollateral","type":"address"},{"indexed":false,"internalType":"contract IERC20","name":"newCollateral","type":"address"}],"name":"CollateralOverwritten","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"_P","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_G","type":"uint256"}],"name":"DepositSnapshotUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"_currentEpoch","type":"uint128"}],"name":"EpochUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_G","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"_epoch","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"_scale","type":"uint128"}],"name":"G_Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_P","type":"uint256"}],"name":"P_Updated","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":"idx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_S","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"_epoch","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"_scale","type":"uint128"}],"name":"S_Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"_currentScale","type":"uint128"}],"name":"ScaleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newBalance","type":"uint256"}],"name":"StabilityPoolDebtBalanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"_newDeposit","type":"uint256"}],"name":"UserDepositChanged","type":"event"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"P","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":"SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUNSET_DURATION","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accountDeposits","outputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint128","name":"timestamp","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"collateralIndexes","type":"uint256[]"}],"name":"claimCollateralGains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"claimReward","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"claimableReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"collateralGainsByDepositor","outputs":[{"internalType":"uint80","name":"gains","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"collateralTokens","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentScale","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtToken","outputs":[{"internalType":"contract IDebtToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"depositSnapshots","outputs":[{"internalType":"uint256","name":"P","type":"uint256"},{"internalType":"uint256","name":"G","type":"uint256"},{"internalType":"uint128","name":"scale","type":"uint128"},{"internalType":"uint128","name":"epoch","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"depositSums","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emissionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_collateral","type":"address"}],"name":"enableCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"}],"name":"epochToScaleToG","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"epochToScaleToSums","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"getCompoundedDebtDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"getDepositorCollateralGain","outputs":[{"internalType":"uint256[]","name":"collateralGains","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDebtTokenDeposits","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":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"collateral","type":"address"}],"name":"indexByCollateral","outputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastCollateralError_Offset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastDebtLossError_Offset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPrismaError","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":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"_debtToOffset","type":"uint256"},{"internalType":"uint256","name":"_collToAdd","type":"uint256"}],"name":"offset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"provideToSP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"collateral","type":"address"}],"name":"startCollateralSunset","outputs":[],"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":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFromSP","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610140604052670de0b6b3a76400006009553480156200001e57600080fd5b50604051620036e4380380620036e483398101604081905262000041916200012a565b6001600160a01b0385166080819052604080516378e9792560e01b815290518792916378e979259160048083019260209291908290030181865afa1580156200008e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b49190620001aa565b60a052506001600160a01b0380851660c05283811660e05282811661010052811661012052620000e6600142620001c4565b600060146101000a81548163ffffffff021916908363ffffffff1602179055505050505050620001ec565b6001600160a01b03811681146200012757600080fd5b50565b600080600080600060a086880312156200014357600080fd5b8551620001508162000111565b6020870151909550620001638162000111565b6040870151909450620001768162000111565b6060870151909350620001898162000111565b60808701519092506200019c8162000111565b809150509295509295909350565b600060208284031215620001bd57600080fd5b5051919050565b81810381811115620001e657634e487b7160e01b600052601160045260246000fd5b92915050565b60805160a05160c05160e05161010051610120516134546200029060003960008181610311015261256301526000818161057101526106d60152600081816106830152818161149d015281816118b20152611b7901526000818161065c01528181610d0f01526112810152600081816113cf0152611b21015260008181610598015281816109b0015281816110890152818161111b015261140201526134546000f3fe608060405234801561001057600080fd5b50600436106102525760003560e01c806386da082411610146578063ce4b5bbe116100c3578063e666673311610087578063e666673314610607578063e95034251461061a578063ebe2b12b1461062d578063f058203814610644578063f8d8989814610657578063fbfa77cf1461067e57600080fd5b8063ce4b5bbe146105ba578063d279c191146105c5578063d5f195fe146105d8578063d7936b7e146105eb578063db03fdaa146105f457600080fd5b8063a4e59ac81161010a578063a4e59ac814610523578063a7528a0314610536578063c046371114610540578063c45a01551461056c578063cc9641a81461059357600080fd5b806386da082414610489578063874d6d81146104fb5780638b8fbd92146105035780638da5cb5b1461050c578063a20baee61461051457600080fd5b8063452a9320116101d457806378c77a241161019857806378c77a24146103db5780637b0a47ee146103ee57806381bafb311461040157806382e0a5741461040a578063835dada01461043557600080fd5b8063452a932014610366578063476363711461036e5780635383dfcb146103765780635e3078ec1461039657806376671808146103a957600080fd5b8063172c48c71161021b578063172c48c7146102ce57806319f27b3b146102f95780631ef3a04c1461030c5780632e54bf9514610333578063307d36121461034657600080fd5b8062ba85b51461025757806309e2acb0146102735780630d9a6b351461028657806311be0de51461028e5780631500d2c3146102a3575b600080fd5b610260600e5481565b6040519081526020015b60405180910390f35b610260610281366004612fe3565b6106a5565b600354610260565b6102a161029c36600461300f565b6106cb565b005b6102b66102b1366004612fe3565b610941565b6040516001600160501b03909116815260200161026a565b6102e16102dc366004613033565b610984565b6040516001600160a01b03909116815260200161026a565b6102a161030736600461300f565b6109ae565b6102e17f000000000000000000000000000000000000000000000000000000000000000081565b6102a1610341366004613033565b610bcf565b61035961035436600461300f565b610e13565b60405161026a919061304c565b6102e1611085565b610260600081565b61026061038436600461300f565b60016020526000908152604090205481565b6102a16103a4366004613090565b61110e565b600a546103c390600160801b90046001600160801b031681565b6040516001600160801b03909116815260200161026a565b6102a16103e9366004613033565b611119565b6000546103c3906001600160801b031681565b610260600f5481565b610260610418366004613134565b600c60209081526000928352604080842090915290825290205481565b61046961044336600461300f565b6004602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b0393841681529290911660208301520161026a565b6104cc61049736600461300f565b6005602052600090815260409020805460018201546002909201549091906001600160801b0380821691600160801b90041684565b6040805194855260208501939093526001600160801b039182169284019290925216606082015260800161026a565b6102606113c4565b61026060095481565b6102e16113fe565b610260670de0b6b3a764000081565b600a546103c3906001600160801b031681565b6103c362ed4e0081565b60005461055790600160801b900463ffffffff1681565b60405163ffffffff909116815260200161026a565b6102e17f000000000000000000000000000000000000000000000000000000000000000081565b6102e17f000000000000000000000000000000000000000000000000000000000000000081565b610260633b9aca0081565b6102606105d336600461300f565b61145e565b6102606105e636600461300f565b611551565b610260600d5481565b610260610602366004613167565b6115ed565b6102a16106153660046131a3565b611620565b61026061062836600461300f565b61162b565b60005461055790600160a01b900463ffffffff1681565b6102606106523660046131d8565b6118a5565b6102e17f000000000000000000000000000000000000000000000000000000000000000081565b6102e17f000000000000000000000000000000000000000000000000000000000000000081565b60066020528160005260406000208161010081106106c257600080fd5b01549150829050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107365760405162461bcd60e51b815260206004820152600b60248201526a4e6f7420666163746f727960a81b60448201526064015b60405180910390fd5b6002546000805b8281101561079757836001600160a01b03166002828154811061076257610762613211565b6000918252602090912001546001600160a01b0316036107855760019150610797565b8061078f8161323d565b91505061073d565b50806108d7576040805180820190915260115461ffff808216808452620100009092041660208301819052111561087357805161ffff166000908152601060209081526040918290208251808401909352546001600160801b038082168452600160801b90910416908201819052421115610871576011805460109160009161ffff16908261082583613256565b82546101009290920a61ffff8181021990931691831602179091551681526020810191909152604001600090812055805161086a9086906001600160801b03166118ee565b5050505050565b505b5060028054600180820183557f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180546001600160a01b0319166001600160a01b03871690811790915591546000928352602091909152604090912055505050565b6001600160a01b03831660009081526001602052604090205461093c5760405162461bcd60e51b815260206004820152601860248201527f436f6c6c61746572616c2069732073756e73657474696e670000000000000000604482015260640161072d565b505050565b600760205281600052604060002081610100811061095e57600080fd5b60039182820401919006600a02915091509054906101000a90046001600160501b031681565b6002818154811061099457600080fd5b6000918252602090912001546001600160a01b0316905081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a309190613277565b6001600160a01b0316336001600160a01b031614610a7d5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015260640161072d565b6001600160a01b038116600090815260016020526040902054610ae25760405162461bcd60e51b815260206004820152601d60248201527f436f6c6c61746572616c20616c72656164792073756e73657474696e67000000604482015260640161072d565b60405180604001604052806001806000856001600160a01b03166001600160a01b0316815260200190815260200160002054610b1e9190613294565b6001600160801b03168152602001610b3962ed4e00426132a7565b6001600160801b031690526011805460109160009162010000900461ffff16906002610b6483613256565b825461ffff9182166101009390930a928302928202191691909117909155168152602080820192909252604090810160009081208451948401516001600160801b03908116600160801b029516949094179093556001600160a01b0390931682526001905290812055565b336000908152600460205260409020546001600160801b0380821691600160801b90041681610c595760405162461bcd60e51b815260206004820152603060248201527f53746162696c697479506f6f6c3a2055736572206d757374206861766520612060448201526f1b9bdb8b5e995c9bc819195c1bdcda5d60821b606482015260840161072d565b42816001600160801b031610610cb15760405162461bcd60e51b815260206004820181905260248201527f214465706f73697420616e642077697468647261772073616d6520626c6f636b604482015260640161072d565b610cb9611af6565b610cc233611cb0565b506000610cce33611551565b90506000610cdc8583611ecc565b9050610ce733611ee2565b8015610d7c57604051631062c15f60e11b8152306004820152336024820152604481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906320c582be90606401600060405180830381600087803b158015610d5b57600080fd5b505af1158015610d6f573d6000803e3d6000fd5b50505050610d7c81611f34565b6000610d888284613294565b6040805180820182526001600160801b03808416825287811660208084019182523360008181526004909252949020925190518216600160801b029116179055909150610dd59082611f83565b60405181815233907fbce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c9906020015b60405180910390a2505050505050565b60025460609067ffffffffffffffff811115610e3157610e316132ba565b604051908082528060200260200182016040528015610e5a578160200160208202803683370190505b506001600160a01b038316600090815260056020526040812054919250819003610e845750919050565b6001600160a01b0383166000908152600760209081526040808320600483528184205460058452828520600201546001600160801b03600160801b82048116808852600b808852868920938316808a52848952968920828a5297529396921694929392919081610ef58560016132d0565b6001600160801b03168152602080820192909252604090810160009081206001600160a01b038d16825260069093529081209192505b89518110156110775787816101008110610f4757610f47613211565b60039182820401919006600a029054906101000a90046001600160501b03166001600160501b03168a8281518110610f8157610f81613211565b60200260200101818152505083816101008110610fa057610fa0613211565b01541561106557600082826101008110610fbc57610fbc613211565b015485836101008110610fd157610fd1613211565b0154610fdd9190613294565b90506000633b9aca0085846101008110610ff957610ff9613211565b015461100591906132f7565b9050670de0b6b3a76400008b61101b83856132a7565b611025908c613319565b61102f91906132f7565b61103991906132f7565b8c848151811061104b5761104b613211565b6020026020010181815161105f91906132a7565b90525050505b8061106f8161323d565b915050610f2b565b505050505050505050919050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111099190613277565b905090565b61093c838383612173565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119b9190613330565b156111de5760405162461bcd60e51b815260206004820152601360248201527211195c1bdcda5d1cc8185c99481c185d5cd959606a1b604482015260640161072d565b6000811161123d5760405162461bcd60e51b815260206004820152602660248201527f53746162696c697479506f6f6c3a20416d6f756e74206d757374206265206e6f6044820152656e2d7a65726f60d01b606482015260840161072d565b611245611af6565b61124e33611cb0565b50600061125a33611551565b905061126533611ee2565b60405163e75b3ae760e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e75b3ae790604401600060405180830381600087803b1580156112cd57600080fd5b505af11580156112e1573d6000803e3d6000fd5b505050506000826003546112f591906132a7565b60038190556040518181529091507f5c1eb83edfbe7709b9a63e8c7e294df8731e15bc212a85bf6e95cb906600bcbb9060200160405180910390a1600061133c84846132a7565b6040805180820182526001600160801b03808416825242811660208084019182523360008181526004909252949020925190518216600160801b0291161790559091506113899082611f83565b60405181815233907fbce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c99060200160405180910390a250505050565b600062093a806113f47f000000000000000000000000000000000000000000000000000000000000000042613294565b61110991906132f7565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e5573d6000803e3d6000fd5b600061146933612318565b9050801561150c576040516335e97f1f60e11b81523360048201526001600160a01b038381166024830152604482018390527f00000000000000000000000000000000000000000000000000000000000000001690636bd2fe3e906064016020604051808303816000875af11580156114e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150a9190613330565b505b6040518181526001600160a01b0383169033907f0aa4d283470c904c551d18bb894d37e17674920f3261a7f854be501e25f421b79060200160405180910390a3919050565b6001600160a01b0381166000908152600460205260408120546001600160801b03168082036115835750600092915050565b6001600160a01b0383166000908152600560209081526040808320815160808101835281548152600182015493810193909352600201546001600160801b0380821692840192909252600160801b9004166060820152906115e4838361246b565b95945050505050565b600b60205282600052604060002060205281600052604060002081610100811061161657600080fd5b0154925083915050565b61093c838383612558565b6003546001600160a01b0382166000908152600460205260408120549091906001600160801b031681158061165e575080155b1561166d575060009392505050565b6000600d54670de0b6b3a7640000611683612664565b61168d9190613319565b61169791906132a7565b905060006116a584836132f7565b90506000600954826116b79190613319565b6001600160a01b0388166000908152600560209081526040808320815160808101835281548152600182015493810193909352600201546001600160801b03808216928401839052600160801b909104811660608401819052600a5495965092949293919282911683036117c5576020808601516001600160801b038087166000908152600c8452604080822092881682529190935290912054879161175c91613294565b61176691906132a7565b6001600160801b0385166000908152600c60205260408120919350633b9aca0091906117938660016132d0565b6001600160801b03166001600160801b03168152602001908152602001600020546117be91906132f7565b9050611861565b6020808601516001600160801b038087166000908152600c84526040808220928816825291909352909120546117fb9190613294565b6001600160801b0385166000908152600c60205260408120919350633b9aca009188916118298760016132d0565b6001600160801b03166001600160801b031681526020019081526020016000205461185491906132a7565b61185e91906132f7565b90505b8451670de0b6b3a76400009061187783856132a7565b611881908c613319565b61188b91906132f7565b61189591906132f7565b9c9b505050505050505050505050565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146118dc57600080fd5b6118e583612318565b90505b92915050565b6001600160a01b038216600090815260016020526040902054156119545760405162461bcd60e51b815260206004820152601960248201527f436f6c6c61746572616c206d7573742062652073756e73657400000000000000604482015260640161072d565b6002548082106119985760405162461bcd60e51b815260206004820152600f60248201526e496e64657820746f6f206c6172676560881b604482015260640161072d565b600a546001600160801b03600160801b82048116911660005b82816001600160801b031611611a205760005b82816001600160801b031611611a17576001600160801b038083166000908152600b602090815260408083209385168352929052908120876101008110611a0d57611a0d613211565b01556001016119c4565b506001016119b1565b50611a2c8460016132a7565b6001600160a01b038616600090815260016020526040902055600280547f9e147d339c63698deb55c3d0d44ed3eba29bac2a068a88c4bc5bde17d6331e19919086908110611a7c57611a7c613211565b60009182526020918290200154604080516001600160a01b039283168152918916928201929092520160405180910390a18460028581548110611ac157611ac1613211565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505050505050565b611b06611b01612664565b6126cd565b60008054600160a01b900463ffffffff169062093a80611b467f000000000000000000000000000000000000000000000000000000000000000084613294565b611b5091906132f7565b905080611b5b6113c4565b10611c8e5760405163378cbf7560e01b8152600060048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063378cbf75906024016020604051808303816000875af1158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee9190613352565b90508015611c8c5782421015611c31576000611c0a4285613294565b600054909150611c23906001600160801b031682613319565b611c2d90836132a7565b9150505b611c3e62093a80826132f7565b600080546001600160801b0319166001600160801b0392909216919091179055611c6b62093a80426132a7565b600060146101000a81548163ffffffff021916908363ffffffff1602179055505b505b50506000805463ffffffff60801b1916600160801b4263ffffffff1602179055565b6001600160a01b03811660009081526007602090815260408083206002546004909352908320549091906001600160801b0316808403611cf257505050919050565b6001600160a01b0385166000908152600560209081526040808320600281015490546001600160801b03600160801b83048116808752600b80875285882092909416808852828752948720818852939095529394929390929081611d578660016132d0565b6001600160801b03168152602080820192909252604090810160009081206001600160a01b038e16825260069093529081209192505b88811015611ebd5783816101008110611da857611da8613211565b015415611eab5760019a50600082826101008110611dc857611dc8613211565b015485836101008110611ddd57611ddd613211565b0154611de99190613294565b90506000633b9aca0085846101008110611e0557611e05613211565b0154611e1191906132f7565b9050670de0b6b3a764000087611e2783856132a7565b611e31908d613319565b611e3b91906132f7565b611e4591906132f7565b8c846101008110611e5857611e58613211565b60039182820401919006600a028282829054906101000a90046001600160501b0316611e84919061336b565b92506101000a8154816001600160501b0302191690836001600160501b0316021790555050505b80611eb58161323d565b915050611d8d565b50505050505050505050919050565b6000818310611edb57816118e5565b5090919050565b6000611eed826127c9565b6001600160a01b038316600090815260086020526040902054909150611f149082906132a7565b6001600160a01b0390921660009081526008602052604090209190915550565b600081600354611f449190613294565b60038190556040518181529091507f5c1eb83edfbe7709b9a63e8c7e294df8731e15bc212a85bf6e95cb906600bcbb9060200160405180910390a15050565b60008160000361204b57506001600160a01b038216600090815260056020526040812081815560018101829055600290810182905554905b81811015612001576001600160a01b0384166000908152600660205260408120826101008110611fed57611fed613211565b015580611ff98161323d565b915050611fbb565b5060408051600080825260208201526001600160a01b038516917fc48943df4095f4f20d171fd2872eafdc0eed4d9014ac3672f3bde7fd425449d5910160405180910390a2505050565b50600a546009546001600160801b03600160801b80840482166000818152600b6020908152604080832095909716808352948152868220838352600c82528783208684528252878320546001600160a01b038b1684526005909252968220868155600181018290559383028517600294850155925495939491939192905b8681101561212457828161010081106120e4576120e4613211565b01546001600160a01b038a16600090815260066020526040902082610100811061211057612110613211565b01558061211c8161323d565b9150506120c9565b5060408051848152602081018390526001600160a01b038a16917fc48943df4095f4f20d171fd2872eafdc0eed4d9014ac3672f3bde7fd425449d5910160405180910390a25050505050505050565b600254819060009067ffffffffffffffff811115612193576121936132ba565b6040519080825280602002602001820160405280156121bc578160200160208202803683370190505b503360009081526007602052604081209192505b838110156122de5760008686838181106121ec576121ec613211565b90506020020135905060008382610100811061220a5761220a613211565b60039182820401919006600a029054906101000a90046001600160501b03166001600160501b0316905060008111156122d4578085838151811061225057612250613211565b60200260200101818152505060008483610100811061227157612271613211565b60039182820401919006600a026101000a8154816001600160501b0302191690836001600160501b031602179055506122d48982600285815481106122b8576122b8613211565b6000918252602090912001546001600160a01b03169190612866565b50506001016121d0565b50336001600160a01b03167faecf5c2e84838a7ed87234d73965fc51f96b87b4c957f03bf22cfeb618c9aae183604051610e03919061304c565b6001600160a01b0381166000908152600460205260408120546001600160801b0316801561241f576001600160a01b038316600090815260046020526040902054600160801b90046001600160801b0316612371611af6565b600061237c85611cb0565b9050600061238986611551565b905060006123978286613294565b90506123a2876127c9565b955060008111806123b05750825b806123bb5750600086115b1561241a576040805180820182526001600160801b03808516825286811660208084019182526001600160a01b038c166000908152600490915293909320915192518116600160801b029216919091179055816124188882611f83565b505b505050505b6001600160a01b03831660009081526008602052604090205480156124645761244881846132a7565b6001600160a01b03851660009081526008602052604081205592505b5050919050565b805160408201516060830151600a546000939291906001600160801b03600160801b909104811690821610156124a757600093505050506118e8565b600a5460009081906124c39085906001600160801b031661338b565b9050806001600160801b03166000036124f65784600954896124e59190613319565b6124ef91906132f7565b915061252a565b806001600160801b031660010361252557633b9aca00856009548a61251b9190613319565b6124e591906132f7565b600091505b612538633b9aca00896132f7565b82101561254d576000955050505050506118e8565b509695505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146125e95760405162461bcd60e51b815260206004820152603060248201527f53746162696c697479506f6f6c3a2043616c6c6572206973206e6f74204c697160448201526f3ab4b230ba34b7b71026b0b730b3b2b960811b606482015260840161072d565b6001600160a01b038316600090815260016020819052604090912054906126109082613294565b600354909150801580612621575083155b1561262d575050505050565b612635611af6565b6000806126438587856128b8565b9150915061265282828661297d565b61265b86611f34565b50505050505050565b60008054600160a01b900463ffffffff16428111156126805750425b600054600160801b900463ffffffff168181106126a05760009250505090565b60006126ac8284613294565b6000549091506126c5906001600160801b031682613319565b935050505090565b6003548015806126db575081155b156126e4575050565b60006126f08383612c9f565b600a546009549192506001600160801b03600160801b820481169291169060009061271b9085613319565b6001600160801b038085166000908152600c60209081526040808320938716835292905290812054919250906127529083906132a7565b6001600160801b038581166000818152600c60209081526040808320948916808452948252918290208590558151858152908101929092528101919091529091507f2d6127771b164a9cc8827d24b5955db2a77e7a81dac389107ebb8bce9fb649689060600160405180910390a150505050505050565b6001600160a01b0381166000908152600460205260408120546001600160801b03168082036127fb5750600092915050565b6001600160a01b038316600090815260056020908152604091829020825160808101845281548152600182015492810192909252600201546001600160801b0380821693830193909352600160801b9004909116606082015261285e8282612cf2565b949350505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261093c908490612dd6565b6000806000600e54670de0b6b3a7640000876128d49190613319565b6128de91906132a7565b90508385036128fc576000600f55670de0b6b3a76400009150612951565b600f54600090612914670de0b6b3a764000088613319565b61291e9190613294565b905061292a85826132f7565b6129359060016132a7565b9250806129428685613319565b61294c9190613294565b600f55505b61295b84826132f7565b92506129678484613319565b6129719082613294565b600e5550935093915050565b60095460008061299585670de0b6b3a7640000613294565b600a546001600160801b03600160801b820481166000818152600b602090815260408083209490951680835293905292832093945090929091908761010081106129e1576129e1613211565b0154905060006129f1878b613319565b905060006129ff82846132a7565b6001600160801b038086166000908152600b60209081526040808320938a1683529290522090915081908a6101008110612a3b57612a3b613211565b0155604080518a8152602081018390526001600160801b03868116828401528716606082015290517fe150473acddd94d1c6add794bd840c8d3e297dc3e50d863b56c0fba04d0d02479181900360800190a185600003612b4957612aa08460016132d0565b600a80546001600160801b03908116600160801b93821684021791829055604051929091041681527fb50f0f59e7cb5b421dc77581c3a9919e3806e076e5fa78a874c3f120cb7d874d9060200160405180910390a1600a80546001600160801b0319169055604051600081527f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe9060200160405180910390a1670de0b6b3a76400009650612c21565b633b9aca00670de0b6b3a7640000612b61888b613319565b612b6b91906132f7565b1015612c0157670de0b6b3a7640000633b9aca00612b89888b613319565b612b939190613319565b612b9d91906132f7565b9650612baa8560016132d0565b600a80546001600160801b0319166001600160801b039290921691821790556040519081527f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe9060200160405180910390a1612c21565b670de0b6b3a7640000612c14878a613319565b612c1e91906132f7565b96505b60008711612c5a5760405162461bcd60e51b815260040161072d9060208082526004908201526304e6577560e41b604082015260600190565b60098790556040518781527fc1a9618cb59ebca77cbdbc2949f126823c407ff13edb285fd0262519a9c18e8c9060200160405180910390a15050505050505050505050565b600080600d54670de0b6b3a764000085612cb99190613319565b612cc391906132a7565b90506000612cd184836132f7565b9050612cdd8482613319565b612ce79083613294565b600d55949350505050565b606081015160408083015160208085015185516001600160801b038087166000908152600c8552868120918616815293529382205491949390918590612d39908490613294565b6001600160801b0386166000908152600c6020526040812091925090633b9aca009082612d678860016132d0565b6001600160801b03166001600160801b0316815260200190815260200160002054612d9291906132f7565b90506000670de0b6b3a764000084612daa84866132a7565b612db4908d613319565b612dbe91906132f7565b612dc891906132f7565b9a9950505050505050505050565b6000612e2b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612ea89092919063ffffffff16565b80519091501561093c5780806020019051810190612e499190613330565b61093c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161072d565b606061285e848460008585600080866001600160a01b03168587604051612ecf91906133cf565b60006040518083038185875af1925050503d8060008114612f0c576040519150601f19603f3d011682016040523d82523d6000602084013e612f11565b606091505b5091509150612f2287838387612f2d565b979650505050505050565b60608315612f9c578251600003612f95576001600160a01b0385163b612f955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161072d565b508161285e565b61285e8383815115612fb15781518083602001fd5b8060405162461bcd60e51b815260040161072d91906133eb565b6001600160a01b0381168114612fe057600080fd5b50565b60008060408385031215612ff657600080fd5b823561300181612fcb565b946020939093013593505050565b60006020828403121561302157600080fd5b813561302c81612fcb565b9392505050565b60006020828403121561304557600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561308457835183529284019291840191600101613068565b50909695505050505050565b6000806000604084860312156130a557600080fd5b83356130b081612fcb565b9250602084013567ffffffffffffffff808211156130cd57600080fd5b818601915086601f8301126130e157600080fd5b8135818111156130f057600080fd5b8760208260051b850101111561310557600080fd5b6020830194508093505050509250925092565b80356001600160801b038116811461312f57600080fd5b919050565b6000806040838503121561314757600080fd5b61315083613118565b915061315e60208401613118565b90509250929050565b60008060006060848603121561317c57600080fd5b61318584613118565b925061319360208501613118565b9150604084013590509250925092565b6000806000606084860312156131b857600080fd5b83356131c381612fcb565b95602085013595506040909401359392505050565b600080604083850312156131eb57600080fd5b82356131f681612fcb565b9150602083013561320681612fcb565b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161324f5761324f613227565b5060010190565b600061ffff80831681810361326d5761326d613227565b6001019392505050565b60006020828403121561328957600080fd5b815161302c81612fcb565b818103818111156118e8576118e8613227565b808201808211156118e8576118e8613227565b634e487b7160e01b600052604160045260246000fd5b6001600160801b038181168382160190808211156132f0576132f0613227565b5092915050565b60008261331457634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176118e8576118e8613227565b60006020828403121561334257600080fd5b8151801515811461302c57600080fd5b60006020828403121561336457600080fd5b5051919050565b6001600160501b038181168382160190808211156132f0576132f0613227565b6001600160801b038281168282160390808211156132f0576132f0613227565b60005b838110156133c65781810151838201526020016133ae565b50506000910152565b600082516133e18184602087016133ab565b9190910192915050565b602081526000825180602084015261340a8160408501602087016133ab565b601f01601f1916919091016040019291505056fea2646970667358221220a6b414ff3abbf71aa38488f4215b453604386370247c248fe9244c5ea26a787964736f6c634300081300330000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf80000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2800000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c00000000000000000000000070b66e20766b775b2e9ce5b718bbd285af59b7e10000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102525760003560e01c806386da082411610146578063ce4b5bbe116100c3578063e666673311610087578063e666673314610607578063e95034251461061a578063ebe2b12b1461062d578063f058203814610644578063f8d8989814610657578063fbfa77cf1461067e57600080fd5b8063ce4b5bbe146105ba578063d279c191146105c5578063d5f195fe146105d8578063d7936b7e146105eb578063db03fdaa146105f457600080fd5b8063a4e59ac81161010a578063a4e59ac814610523578063a7528a0314610536578063c046371114610540578063c45a01551461056c578063cc9641a81461059357600080fd5b806386da082414610489578063874d6d81146104fb5780638b8fbd92146105035780638da5cb5b1461050c578063a20baee61461051457600080fd5b8063452a9320116101d457806378c77a241161019857806378c77a24146103db5780637b0a47ee146103ee57806381bafb311461040157806382e0a5741461040a578063835dada01461043557600080fd5b8063452a932014610366578063476363711461036e5780635383dfcb146103765780635e3078ec1461039657806376671808146103a957600080fd5b8063172c48c71161021b578063172c48c7146102ce57806319f27b3b146102f95780631ef3a04c1461030c5780632e54bf9514610333578063307d36121461034657600080fd5b8062ba85b51461025757806309e2acb0146102735780630d9a6b351461028657806311be0de51461028e5780631500d2c3146102a3575b600080fd5b610260600e5481565b6040519081526020015b60405180910390f35b610260610281366004612fe3565b6106a5565b600354610260565b6102a161029c36600461300f565b6106cb565b005b6102b66102b1366004612fe3565b610941565b6040516001600160501b03909116815260200161026a565b6102e16102dc366004613033565b610984565b6040516001600160a01b03909116815260200161026a565b6102a161030736600461300f565b6109ae565b6102e17f0000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e281565b6102a1610341366004613033565b610bcf565b61035961035436600461300f565b610e13565b60405161026a919061304c565b6102e1611085565b610260600081565b61026061038436600461300f565b60016020526000908152604090205481565b6102a16103a4366004613090565b61110e565b600a546103c390600160801b90046001600160801b031681565b6040516001600160801b03909116815260200161026a565b6102a16103e9366004613033565b611119565b6000546103c3906001600160801b031681565b610260600f5481565b610260610418366004613134565b600c60209081526000928352604080842090915290825290205481565b61046961044336600461300f565b6004602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b0393841681529290911660208301520161026a565b6104cc61049736600461300f565b6005602052600090815260409020805460018201546002909201549091906001600160801b0380821691600160801b90041684565b6040805194855260208501939093526001600160801b039182169284019290925216606082015260800161026a565b6102606113c4565b61026060095481565b6102e16113fe565b610260670de0b6b3a764000081565b600a546103c3906001600160801b031681565b6103c362ed4e0081565b60005461055790600160801b900463ffffffff1681565b60405163ffffffff909116815260200161026a565b6102e17f00000000000000000000000070b66e20766b775b2e9ce5b718bbd285af59b7e181565b6102e17f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf881565b610260633b9aca0081565b6102606105d336600461300f565b61145e565b6102606105e636600461300f565b611551565b610260600d5481565b610260610602366004613167565b6115ed565b6102a16106153660046131a3565b611620565b61026061062836600461300f565b61162b565b60005461055790600160a01b900463ffffffff1681565b6102606106523660046131d8565b6118a5565b6102e17f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2881565b6102e17f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c81565b60066020528160005260406000208161010081106106c257600080fd5b01549150829050565b336001600160a01b037f00000000000000000000000070b66e20766b775b2e9ce5b718bbd285af59b7e116146107365760405162461bcd60e51b815260206004820152600b60248201526a4e6f7420666163746f727960a81b60448201526064015b60405180910390fd5b6002546000805b8281101561079757836001600160a01b03166002828154811061076257610762613211565b6000918252602090912001546001600160a01b0316036107855760019150610797565b8061078f8161323d565b91505061073d565b50806108d7576040805180820190915260115461ffff808216808452620100009092041660208301819052111561087357805161ffff166000908152601060209081526040918290208251808401909352546001600160801b038082168452600160801b90910416908201819052421115610871576011805460109160009161ffff16908261082583613256565b82546101009290920a61ffff8181021990931691831602179091551681526020810191909152604001600090812055805161086a9086906001600160801b03166118ee565b5050505050565b505b5060028054600180820183557f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180546001600160a01b0319166001600160a01b03871690811790915591546000928352602091909152604090912055505050565b6001600160a01b03831660009081526001602052604090205461093c5760405162461bcd60e51b815260206004820152601860248201527f436f6c6c61746572616c2069732073756e73657474696e670000000000000000604482015260640161072d565b505050565b600760205281600052604060002081610100811061095e57600080fd5b60039182820401919006600a02915091509054906101000a90046001600160501b031681565b6002818154811061099457600080fd5b6000918252602090912001546001600160a01b0316905081565b7f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a309190613277565b6001600160a01b0316336001600160a01b031614610a7d5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015260640161072d565b6001600160a01b038116600090815260016020526040902054610ae25760405162461bcd60e51b815260206004820152601d60248201527f436f6c6c61746572616c20616c72656164792073756e73657474696e67000000604482015260640161072d565b60405180604001604052806001806000856001600160a01b03166001600160a01b0316815260200190815260200160002054610b1e9190613294565b6001600160801b03168152602001610b3962ed4e00426132a7565b6001600160801b031690526011805460109160009162010000900461ffff16906002610b6483613256565b825461ffff9182166101009390930a928302928202191691909117909155168152602080820192909252604090810160009081208451948401516001600160801b03908116600160801b029516949094179093556001600160a01b0390931682526001905290812055565b336000908152600460205260409020546001600160801b0380821691600160801b90041681610c595760405162461bcd60e51b815260206004820152603060248201527f53746162696c697479506f6f6c3a2055736572206d757374206861766520612060448201526f1b9bdb8b5e995c9bc819195c1bdcda5d60821b606482015260840161072d565b42816001600160801b031610610cb15760405162461bcd60e51b815260206004820181905260248201527f214465706f73697420616e642077697468647261772073616d6520626c6f636b604482015260640161072d565b610cb9611af6565b610cc233611cb0565b506000610cce33611551565b90506000610cdc8583611ecc565b9050610ce733611ee2565b8015610d7c57604051631062c15f60e11b8152306004820152336024820152604481018290527f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb286001600160a01b0316906320c582be90606401600060405180830381600087803b158015610d5b57600080fd5b505af1158015610d6f573d6000803e3d6000fd5b50505050610d7c81611f34565b6000610d888284613294565b6040805180820182526001600160801b03808416825287811660208084019182523360008181526004909252949020925190518216600160801b029116179055909150610dd59082611f83565b60405181815233907fbce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c9906020015b60405180910390a2505050505050565b60025460609067ffffffffffffffff811115610e3157610e316132ba565b604051908082528060200260200182016040528015610e5a578160200160208202803683370190505b506001600160a01b038316600090815260056020526040812054919250819003610e845750919050565b6001600160a01b0383166000908152600760209081526040808320600483528184205460058452828520600201546001600160801b03600160801b82048116808852600b808852868920938316808a52848952968920828a5297529396921694929392919081610ef58560016132d0565b6001600160801b03168152602080820192909252604090810160009081206001600160a01b038d16825260069093529081209192505b89518110156110775787816101008110610f4757610f47613211565b60039182820401919006600a029054906101000a90046001600160501b03166001600160501b03168a8281518110610f8157610f81613211565b60200260200101818152505083816101008110610fa057610fa0613211565b01541561106557600082826101008110610fbc57610fbc613211565b015485836101008110610fd157610fd1613211565b0154610fdd9190613294565b90506000633b9aca0085846101008110610ff957610ff9613211565b015461100591906132f7565b9050670de0b6b3a76400008b61101b83856132a7565b611025908c613319565b61102f91906132f7565b61103991906132f7565b8c848151811061104b5761104b613211565b6020026020010181815161105f91906132a7565b90525050505b8061106f8161323d565b915050610f2b565b505050505050505050919050565b60007f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111099190613277565b905090565b61093c838383612173565b7f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119b9190613330565b156111de5760405162461bcd60e51b815260206004820152601360248201527211195c1bdcda5d1cc8185c99481c185d5cd959606a1b604482015260640161072d565b6000811161123d5760405162461bcd60e51b815260206004820152602660248201527f53746162696c697479506f6f6c3a20416d6f756e74206d757374206265206e6f6044820152656e2d7a65726f60d01b606482015260840161072d565b611245611af6565b61124e33611cb0565b50600061125a33611551565b905061126533611ee2565b60405163e75b3ae760e01b8152336004820152602481018390527f0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb286001600160a01b03169063e75b3ae790604401600060405180830381600087803b1580156112cd57600080fd5b505af11580156112e1573d6000803e3d6000fd5b505050506000826003546112f591906132a7565b60038190556040518181529091507f5c1eb83edfbe7709b9a63e8c7e294df8731e15bc212a85bf6e95cb906600bcbb9060200160405180910390a1600061133c84846132a7565b6040805180820182526001600160801b03808416825242811660208084019182523360008181526004909252949020925190518216600160801b0291161790559091506113899082611f83565b60405181815233907fbce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c99060200160405180910390a250505050565b600062093a806113f47f0000000000000000000000000000000000000000000000000000000064d4288042613294565b61110991906132f7565b60007f0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf86001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e5573d6000803e3d6000fd5b600061146933612318565b9050801561150c576040516335e97f1f60e11b81523360048201526001600160a01b038381166024830152604482018390527f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c1690636bd2fe3e906064016020604051808303816000875af11580156114e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150a9190613330565b505b6040518181526001600160a01b0383169033907f0aa4d283470c904c551d18bb894d37e17674920f3261a7f854be501e25f421b79060200160405180910390a3919050565b6001600160a01b0381166000908152600460205260408120546001600160801b03168082036115835750600092915050565b6001600160a01b0383166000908152600560209081526040808320815160808101835281548152600182015493810193909352600201546001600160801b0380821692840192909252600160801b9004166060820152906115e4838361246b565b95945050505050565b600b60205282600052604060002060205281600052604060002081610100811061161657600080fd5b0154925083915050565b61093c838383612558565b6003546001600160a01b0382166000908152600460205260408120549091906001600160801b031681158061165e575080155b1561166d575060009392505050565b6000600d54670de0b6b3a7640000611683612664565b61168d9190613319565b61169791906132a7565b905060006116a584836132f7565b90506000600954826116b79190613319565b6001600160a01b0388166000908152600560209081526040808320815160808101835281548152600182015493810193909352600201546001600160801b03808216928401839052600160801b909104811660608401819052600a5495965092949293919282911683036117c5576020808601516001600160801b038087166000908152600c8452604080822092881682529190935290912054879161175c91613294565b61176691906132a7565b6001600160801b0385166000908152600c60205260408120919350633b9aca0091906117938660016132d0565b6001600160801b03166001600160801b03168152602001908152602001600020546117be91906132f7565b9050611861565b6020808601516001600160801b038087166000908152600c84526040808220928816825291909352909120546117fb9190613294565b6001600160801b0385166000908152600c60205260408120919350633b9aca009188916118298760016132d0565b6001600160801b03166001600160801b031681526020019081526020016000205461185491906132a7565b61185e91906132f7565b90505b8451670de0b6b3a76400009061187783856132a7565b611881908c613319565b61188b91906132f7565b61189591906132f7565b9c9b505050505050505050505050565b6000336001600160a01b037f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c16146118dc57600080fd5b6118e583612318565b90505b92915050565b6001600160a01b038216600090815260016020526040902054156119545760405162461bcd60e51b815260206004820152601960248201527f436f6c6c61746572616c206d7573742062652073756e73657400000000000000604482015260640161072d565b6002548082106119985760405162461bcd60e51b815260206004820152600f60248201526e496e64657820746f6f206c6172676560881b604482015260640161072d565b600a546001600160801b03600160801b82048116911660005b82816001600160801b031611611a205760005b82816001600160801b031611611a17576001600160801b038083166000908152600b602090815260408083209385168352929052908120876101008110611a0d57611a0d613211565b01556001016119c4565b506001016119b1565b50611a2c8460016132a7565b6001600160a01b038616600090815260016020526040902055600280547f9e147d339c63698deb55c3d0d44ed3eba29bac2a068a88c4bc5bde17d6331e19919086908110611a7c57611a7c613211565b60009182526020918290200154604080516001600160a01b039283168152918916928201929092520160405180910390a18460028581548110611ac157611ac1613211565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505050505050565b611b06611b01612664565b6126cd565b60008054600160a01b900463ffffffff169062093a80611b467f0000000000000000000000000000000000000000000000000000000064d4288084613294565b611b5091906132f7565b905080611b5b6113c4565b10611c8e5760405163378cbf7560e01b8152600060048201819052907f00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c6001600160a01b03169063378cbf75906024016020604051808303816000875af1158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee9190613352565b90508015611c8c5782421015611c31576000611c0a4285613294565b600054909150611c23906001600160801b031682613319565b611c2d90836132a7565b9150505b611c3e62093a80826132f7565b600080546001600160801b0319166001600160801b0392909216919091179055611c6b62093a80426132a7565b600060146101000a81548163ffffffff021916908363ffffffff1602179055505b505b50506000805463ffffffff60801b1916600160801b4263ffffffff1602179055565b6001600160a01b03811660009081526007602090815260408083206002546004909352908320549091906001600160801b0316808403611cf257505050919050565b6001600160a01b0385166000908152600560209081526040808320600281015490546001600160801b03600160801b83048116808752600b80875285882092909416808852828752948720818852939095529394929390929081611d578660016132d0565b6001600160801b03168152602080820192909252604090810160009081206001600160a01b038e16825260069093529081209192505b88811015611ebd5783816101008110611da857611da8613211565b015415611eab5760019a50600082826101008110611dc857611dc8613211565b015485836101008110611ddd57611ddd613211565b0154611de99190613294565b90506000633b9aca0085846101008110611e0557611e05613211565b0154611e1191906132f7565b9050670de0b6b3a764000087611e2783856132a7565b611e31908d613319565b611e3b91906132f7565b611e4591906132f7565b8c846101008110611e5857611e58613211565b60039182820401919006600a028282829054906101000a90046001600160501b0316611e84919061336b565b92506101000a8154816001600160501b0302191690836001600160501b0316021790555050505b80611eb58161323d565b915050611d8d565b50505050505050505050919050565b6000818310611edb57816118e5565b5090919050565b6000611eed826127c9565b6001600160a01b038316600090815260086020526040902054909150611f149082906132a7565b6001600160a01b0390921660009081526008602052604090209190915550565b600081600354611f449190613294565b60038190556040518181529091507f5c1eb83edfbe7709b9a63e8c7e294df8731e15bc212a85bf6e95cb906600bcbb9060200160405180910390a15050565b60008160000361204b57506001600160a01b038216600090815260056020526040812081815560018101829055600290810182905554905b81811015612001576001600160a01b0384166000908152600660205260408120826101008110611fed57611fed613211565b015580611ff98161323d565b915050611fbb565b5060408051600080825260208201526001600160a01b038516917fc48943df4095f4f20d171fd2872eafdc0eed4d9014ac3672f3bde7fd425449d5910160405180910390a2505050565b50600a546009546001600160801b03600160801b80840482166000818152600b6020908152604080832095909716808352948152868220838352600c82528783208684528252878320546001600160a01b038b1684526005909252968220868155600181018290559383028517600294850155925495939491939192905b8681101561212457828161010081106120e4576120e4613211565b01546001600160a01b038a16600090815260066020526040902082610100811061211057612110613211565b01558061211c8161323d565b9150506120c9565b5060408051848152602081018390526001600160a01b038a16917fc48943df4095f4f20d171fd2872eafdc0eed4d9014ac3672f3bde7fd425449d5910160405180910390a25050505050505050565b600254819060009067ffffffffffffffff811115612193576121936132ba565b6040519080825280602002602001820160405280156121bc578160200160208202803683370190505b503360009081526007602052604081209192505b838110156122de5760008686838181106121ec576121ec613211565b90506020020135905060008382610100811061220a5761220a613211565b60039182820401919006600a029054906101000a90046001600160501b03166001600160501b0316905060008111156122d4578085838151811061225057612250613211565b60200260200101818152505060008483610100811061227157612271613211565b60039182820401919006600a026101000a8154816001600160501b0302191690836001600160501b031602179055506122d48982600285815481106122b8576122b8613211565b6000918252602090912001546001600160a01b03169190612866565b50506001016121d0565b50336001600160a01b03167faecf5c2e84838a7ed87234d73965fc51f96b87b4c957f03bf22cfeb618c9aae183604051610e03919061304c565b6001600160a01b0381166000908152600460205260408120546001600160801b0316801561241f576001600160a01b038316600090815260046020526040902054600160801b90046001600160801b0316612371611af6565b600061237c85611cb0565b9050600061238986611551565b905060006123978286613294565b90506123a2876127c9565b955060008111806123b05750825b806123bb5750600086115b1561241a576040805180820182526001600160801b03808516825286811660208084019182526001600160a01b038c166000908152600490915293909320915192518116600160801b029216919091179055816124188882611f83565b505b505050505b6001600160a01b03831660009081526008602052604090205480156124645761244881846132a7565b6001600160a01b03851660009081526008602052604081205592505b5050919050565b805160408201516060830151600a546000939291906001600160801b03600160801b909104811690821610156124a757600093505050506118e8565b600a5460009081906124c39085906001600160801b031661338b565b9050806001600160801b03166000036124f65784600954896124e59190613319565b6124ef91906132f7565b915061252a565b806001600160801b031660010361252557633b9aca00856009548a61251b9190613319565b6124e591906132f7565b600091505b612538633b9aca00896132f7565b82101561254d576000955050505050506118e8565b509695505050505050565b336001600160a01b037f0000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e216146125e95760405162461bcd60e51b815260206004820152603060248201527f53746162696c697479506f6f6c3a2043616c6c6572206973206e6f74204c697160448201526f3ab4b230ba34b7b71026b0b730b3b2b960811b606482015260840161072d565b6001600160a01b038316600090815260016020819052604090912054906126109082613294565b600354909150801580612621575083155b1561262d575050505050565b612635611af6565b6000806126438587856128b8565b9150915061265282828661297d565b61265b86611f34565b50505050505050565b60008054600160a01b900463ffffffff16428111156126805750425b600054600160801b900463ffffffff168181106126a05760009250505090565b60006126ac8284613294565b6000549091506126c5906001600160801b031682613319565b935050505090565b6003548015806126db575081155b156126e4575050565b60006126f08383612c9f565b600a546009549192506001600160801b03600160801b820481169291169060009061271b9085613319565b6001600160801b038085166000908152600c60209081526040808320938716835292905290812054919250906127529083906132a7565b6001600160801b038581166000818152600c60209081526040808320948916808452948252918290208590558151858152908101929092528101919091529091507f2d6127771b164a9cc8827d24b5955db2a77e7a81dac389107ebb8bce9fb649689060600160405180910390a150505050505050565b6001600160a01b0381166000908152600460205260408120546001600160801b03168082036127fb5750600092915050565b6001600160a01b038316600090815260056020908152604091829020825160808101845281548152600182015492810192909252600201546001600160801b0380821693830193909352600160801b9004909116606082015261285e8282612cf2565b949350505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261093c908490612dd6565b6000806000600e54670de0b6b3a7640000876128d49190613319565b6128de91906132a7565b90508385036128fc576000600f55670de0b6b3a76400009150612951565b600f54600090612914670de0b6b3a764000088613319565b61291e9190613294565b905061292a85826132f7565b6129359060016132a7565b9250806129428685613319565b61294c9190613294565b600f55505b61295b84826132f7565b92506129678484613319565b6129719082613294565b600e5550935093915050565b60095460008061299585670de0b6b3a7640000613294565b600a546001600160801b03600160801b820481166000818152600b602090815260408083209490951680835293905292832093945090929091908761010081106129e1576129e1613211565b0154905060006129f1878b613319565b905060006129ff82846132a7565b6001600160801b038086166000908152600b60209081526040808320938a1683529290522090915081908a6101008110612a3b57612a3b613211565b0155604080518a8152602081018390526001600160801b03868116828401528716606082015290517fe150473acddd94d1c6add794bd840c8d3e297dc3e50d863b56c0fba04d0d02479181900360800190a185600003612b4957612aa08460016132d0565b600a80546001600160801b03908116600160801b93821684021791829055604051929091041681527fb50f0f59e7cb5b421dc77581c3a9919e3806e076e5fa78a874c3f120cb7d874d9060200160405180910390a1600a80546001600160801b0319169055604051600081527f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe9060200160405180910390a1670de0b6b3a76400009650612c21565b633b9aca00670de0b6b3a7640000612b61888b613319565b612b6b91906132f7565b1015612c0157670de0b6b3a7640000633b9aca00612b89888b613319565b612b939190613319565b612b9d91906132f7565b9650612baa8560016132d0565b600a80546001600160801b0319166001600160801b039290921691821790556040519081527f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe9060200160405180910390a1612c21565b670de0b6b3a7640000612c14878a613319565b612c1e91906132f7565b96505b60008711612c5a5760405162461bcd60e51b815260040161072d9060208082526004908201526304e6577560e41b604082015260600190565b60098790556040518781527fc1a9618cb59ebca77cbdbc2949f126823c407ff13edb285fd0262519a9c18e8c9060200160405180910390a15050505050505050505050565b600080600d54670de0b6b3a764000085612cb99190613319565b612cc391906132a7565b90506000612cd184836132f7565b9050612cdd8482613319565b612ce79083613294565b600d55949350505050565b606081015160408083015160208085015185516001600160801b038087166000908152600c8552868120918616815293529382205491949390918590612d39908490613294565b6001600160801b0386166000908152600c6020526040812091925090633b9aca009082612d678860016132d0565b6001600160801b03166001600160801b0316815260200190815260200160002054612d9291906132f7565b90506000670de0b6b3a764000084612daa84866132a7565b612db4908d613319565b612dbe91906132f7565b612dc891906132f7565b9a9950505050505050505050565b6000612e2b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612ea89092919063ffffffff16565b80519091501561093c5780806020019051810190612e499190613330565b61093c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161072d565b606061285e848460008585600080866001600160a01b03168587604051612ecf91906133cf565b60006040518083038185875af1925050503d8060008114612f0c576040519150601f19603f3d011682016040523d82523d6000602084013e612f11565b606091505b5091509150612f2287838387612f2d565b979650505050505050565b60608315612f9c578251600003612f95576001600160a01b0385163b612f955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161072d565b508161285e565b61285e8383815115612fb15781518083602001fd5b8060405162461bcd60e51b815260040161072d91906133eb565b6001600160a01b0381168114612fe057600080fd5b50565b60008060408385031215612ff657600080fd5b823561300181612fcb565b946020939093013593505050565b60006020828403121561302157600080fd5b813561302c81612fcb565b9392505050565b60006020828403121561304557600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561308457835183529284019291840191600101613068565b50909695505050505050565b6000806000604084860312156130a557600080fd5b83356130b081612fcb565b9250602084013567ffffffffffffffff808211156130cd57600080fd5b818601915086601f8301126130e157600080fd5b8135818111156130f057600080fd5b8760208260051b850101111561310557600080fd5b6020830194508093505050509250925092565b80356001600160801b038116811461312f57600080fd5b919050565b6000806040838503121561314757600080fd5b61315083613118565b915061315e60208401613118565b90509250929050565b60008060006060848603121561317c57600080fd5b61318584613118565b925061319360208501613118565b9150604084013590509250925092565b6000806000606084860312156131b857600080fd5b83356131c381612fcb565b95602085013595506040909401359392505050565b600080604083850312156131eb57600080fd5b82356131f681612fcb565b9150602083013561320681612fcb565b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161324f5761324f613227565b5060010190565b600061ffff80831681810361326d5761326d613227565b6001019392505050565b60006020828403121561328957600080fd5b815161302c81612fcb565b818103818111156118e8576118e8613227565b808201808211156118e8576118e8613227565b634e487b7160e01b600052604160045260246000fd5b6001600160801b038181168382160190808211156132f0576132f0613227565b5092915050565b60008261331457634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176118e8576118e8613227565b60006020828403121561334257600080fd5b8151801515811461302c57600080fd5b60006020828403121561336457600080fd5b5051919050565b6001600160501b038181168382160190808211156132f0576132f0613227565b6001600160801b038281168282160390808211156132f0576132f0613227565b60005b838110156133c65781810151838201526020016133ae565b50506000910152565b600082516133e18184602087016133ab565b9190910192915050565b602081526000825180602084015261340a8160408501602087016133ab565b601f01601f1916919091016040019291505056fea2646970667358221220a6b414ff3abbf71aa38488f4215b453604386370247c248fe9244c5ea26a787964736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf80000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb2800000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c00000000000000000000000070b66e20766b775b2e9ce5b718bbd285af59b7e10000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e2
-----Decoded View---------------
Arg [0] : _prismaCore (address): 0x5d17eA085F2FF5da3e6979D5d26F1dBaB664ccf8
Arg [1] : _debtTokenAddress (address): 0x4591DBfF62656E7859Afe5e45f6f47D3669fBB28
Arg [2] : _vault (address): 0x06bDF212C290473dCACea9793890C5024c7Eb02c
Arg [3] : _factory (address): 0x70b66E20766b775B2E9cE5B718bbD285Af59b7E1
Arg [4] : _liquidationManager (address): 0x5de309dfd7f94e9e2A18Cb6bA61CA305aBF8e9E2
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000005d17ea085f2ff5da3e6979d5d26f1dbab664ccf8
Arg [1] : 0000000000000000000000004591dbff62656e7859afe5e45f6f47d3669fbb28
Arg [2] : 00000000000000000000000006bdf212c290473dcacea9793890c5024c7eb02c
Arg [3] : 00000000000000000000000070b66e20766b775b2e9ce5b718bbd285af59b7e1
Arg [4] : 0000000000000000000000005de309dfd7f94e9e2a18cb6ba61ca305abf8e9e2
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.