Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
HintHelpers
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 1 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.24;
import "./Interfaces/ICollateralRegistry.sol";
import "./Dependencies/LiquityMath.sol";
import "./Dependencies/Constants.sol";
import "./Interfaces/IHintHelpers.sol";
contract HintHelpers is IHintHelpers {
string public constant NAME = "HintHelpers";
ICollateralRegistry public immutable collateralRegistry;
constructor(ICollateralRegistry _collateralRegistry) {
collateralRegistry = _collateralRegistry;
}
/* getApproxHint() - return id of a Trove that is, on average, (length / numTrials) positions away in the
sortedTroves list from the correct insert position of the Trove to be inserted.
Note: The output id is worst-case O(n) positions away from the correct insert position, however, the function
is probabilistic. Input can be tuned to guarantee results to a high degree of confidence, e.g:
Submitting numTrials = k * sqrt(length), with k = 15 makes it very, very likely that the ouput id will
be <= sqrt(length) positions away from the correct insert position.
*/
function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed)
external
view
returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed)
{
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
ISortedTroves sortedTroves = troveManager.sortedTroves();
uint256 arrayLength = troveManager.getTroveIdsCount();
if (arrayLength == 0) {
return (0, 0, _inputRandomSeed);
}
hintId = sortedTroves.getLast();
diff = LiquityMath._getAbsoluteDifference(_interestRate, troveManager.getTroveAnnualInterestRate(hintId));
latestRandomSeed = _inputRandomSeed;
for (uint256 i = 1; i < _numTrials; ++i) {
latestRandomSeed = uint256(keccak256(abi.encodePacked(latestRandomSeed)));
uint256 arrayIndex = latestRandomSeed % arrayLength;
uint256 currentId = troveManager.getTroveFromTroveIdsArray(arrayIndex);
// Skip this Trove if it's zombie and not in the sorted list
if (!sortedTroves.contains(currentId)) continue;
uint256 currentInterestRate = troveManager.getTroveAnnualInterestRate(currentId);
// check if abs(current - IR) > abs(closest - IR), and update closest if current is closer
uint256 currentDiff = LiquityMath._getAbsoluteDifference(currentInterestRate, _interestRate);
if (currentDiff < diff) {
diff = currentDiff;
hintId = currentId;
}
}
}
function _calcUpfrontFee(uint256 _debt, uint256 _avgInterestRate) internal pure returns (uint256) {
return _debt * _avgInterestRate * UPFRONT_INTEREST_PERIOD / ONE_YEAR / DECIMAL_PRECISION;
}
function predictOpenTroveUpfrontFee(uint256 _collIndex, uint256 _borrowedAmount, uint256 _interestRate)
external
view
returns (uint256)
{
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
IActivePool activePool = troveManager.activePool();
TroveChange memory openTrove;
openTrove.debtIncrease = _borrowedAmount;
openTrove.newWeightedRecordedDebt = openTrove.debtIncrease * _interestRate;
uint256 avgInterestRate = activePool.getNewApproxAvgInterestRateFromTroveChange(openTrove);
return _calcUpfrontFee(openTrove.debtIncrease, avgInterestRate);
}
function predictAdjustInterestRateUpfrontFee(uint256 _collIndex, uint256 _troveId, uint256 _newInterestRate)
external
view
returns (uint256)
{
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
IActivePool activePool = troveManager.activePool();
LatestTroveData memory trove = troveManager.getLatestTroveData(_troveId);
if (
_newInterestRate == trove.annualInterestRate
|| block.timestamp >= trove.lastInterestRateAdjTime + INTEREST_RATE_ADJ_COOLDOWN
) {
return 0;
}
return _predictAdjustInterestRateUpfrontFee(activePool, trove, _newInterestRate);
}
function forcePredictAdjustInterestRateUpfrontFee(uint256 _collIndex, uint256 _troveId, uint256 _newInterestRate)
external
view
returns (uint256)
{
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
IActivePool activePool = troveManager.activePool();
LatestTroveData memory trove = troveManager.getLatestTroveData(_troveId);
return _predictAdjustInterestRateUpfrontFee(activePool, trove, _newInterestRate);
}
function _predictAdjustInterestRateUpfrontFee(
IActivePool _activePool,
LatestTroveData memory _trove,
uint256 _newInterestRate
) internal view returns (uint256) {
TroveChange memory troveChange;
troveChange.appliedRedistBoldDebtGain = _trove.redistBoldDebtGain;
troveChange.newWeightedRecordedDebt = _trove.entireDebt * _newInterestRate;
troveChange.oldWeightedRecordedDebt = _trove.weightedRecordedDebt;
uint256 avgInterestRate = _activePool.getNewApproxAvgInterestRateFromTroveChange(troveChange);
return _calcUpfrontFee(_trove.entireDebt, avgInterestRate);
}
function predictAdjustTroveUpfrontFee(uint256 _collIndex, uint256 _troveId, uint256 _debtIncrease)
external
view
returns (uint256)
{
if (_debtIncrease == 0) return 0;
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
IActivePool activePool = troveManager.activePool();
LatestTroveData memory trove = troveManager.getLatestTroveData(_troveId);
(,,,,,,,, address batchManager,) = troveManager.Troves(_troveId);
TroveChange memory troveChange;
troveChange.appliedRedistBoldDebtGain = trove.redistBoldDebtGain;
troveChange.debtIncrease = _debtIncrease;
if (batchManager == address(0)) {
troveChange.newWeightedRecordedDebt = (trove.entireDebt + _debtIncrease) * trove.annualInterestRate;
troveChange.oldWeightedRecordedDebt = trove.weightedRecordedDebt;
} else {
LatestBatchData memory batch = troveManager.getLatestBatchData(batchManager);
troveChange.batchAccruedManagementFee = batch.accruedManagementFee;
troveChange.newWeightedRecordedDebt = (
batch.entireDebtWithoutRedistribution + trove.redistBoldDebtGain + _debtIncrease
) * batch.annualInterestRate;
troveChange.oldWeightedRecordedDebt = batch.weightedRecordedDebt;
}
uint256 avgInterestRate = activePool.getNewApproxAvgInterestRateFromTroveChange(troveChange);
return _calcUpfrontFee(_debtIncrease, avgInterestRate);
}
function predictAdjustBatchInterestRateUpfrontFee(
uint256 _collIndex,
address _batchAddress,
uint256 _newInterestRate
) external view returns (uint256) {
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
IActivePool activePool = troveManager.activePool();
LatestBatchData memory batch = troveManager.getLatestBatchData(_batchAddress);
if (
_newInterestRate == batch.annualInterestRate
|| block.timestamp >= batch.lastInterestRateAdjTime + INTEREST_RATE_ADJ_COOLDOWN
) {
return 0;
}
TroveChange memory troveChange;
troveChange.batchAccruedManagementFee = batch.accruedManagementFee;
troveChange.newWeightedRecordedDebt = batch.entireDebtWithoutRedistribution * _newInterestRate;
troveChange.oldWeightedRecordedDebt = batch.weightedRecordedDebt;
uint256 avgInterestRate = activePool.getNewApproxAvgInterestRateFromTroveChange(troveChange);
return _calcUpfrontFee(batch.entireDebtWithoutRedistribution, avgInterestRate);
}
function predictOpenTroveAndJoinBatchUpfrontFee(uint256 _collIndex, uint256 _borrowedAmount, address _batchAddress)
external
view
returns (uint256)
{
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
IActivePool activePool = troveManager.activePool();
LatestBatchData memory batch = troveManager.getLatestBatchData(_batchAddress);
TroveChange memory openTrove;
openTrove.debtIncrease = _borrowedAmount;
openTrove.batchAccruedManagementFee = batch.accruedManagementFee;
openTrove.oldWeightedRecordedDebt = batch.weightedRecordedDebt;
openTrove.newWeightedRecordedDebt =
(batch.entireDebtWithoutRedistribution + _borrowedAmount) * batch.annualInterestRate;
uint256 avgInterestRate = activePool.getNewApproxAvgInterestRateFromTroveChange(openTrove);
return _calcUpfrontFee(_borrowedAmount, avgInterestRate);
}
function predictJoinBatchInterestRateUpfrontFee(uint256 _collIndex, uint256 _troveId, address _batchAddress)
external
view
returns (uint256)
{
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
IActivePool activePool = troveManager.activePool();
LatestTroveData memory trove = troveManager.getLatestTroveData(_troveId);
LatestBatchData memory batch = troveManager.getLatestBatchData(_batchAddress);
TroveChange memory newBatchTroveChange;
newBatchTroveChange.appliedRedistBoldDebtGain = trove.redistBoldDebtGain;
newBatchTroveChange.batchAccruedManagementFee = batch.accruedManagementFee;
newBatchTroveChange.oldWeightedRecordedDebt = batch.weightedRecordedDebt + trove.weightedRecordedDebt;
newBatchTroveChange.newWeightedRecordedDebt =
(batch.entireDebtWithoutRedistribution + trove.entireDebt) * batch.annualInterestRate;
uint256 avgInterestRate = activePool.getNewApproxAvgInterestRateFromTroveChange(newBatchTroveChange);
return _calcUpfrontFee(trove.entireDebt, avgInterestRate);
}
function predictRemoveFromBatchUpfrontFee(uint256 _collIndex, uint256 _troveId, uint256 _newInterestRate)
external
view
returns (uint256)
{
ITroveManager troveManager = collateralRegistry.getTroveManager(_collIndex);
IActivePool activePool = troveManager.activePool();
LatestTroveData memory trove = troveManager.getLatestTroveData(_troveId);
(,,,,,,,, address batchManager,) = troveManager.Troves(_troveId);
LatestBatchData memory batch = troveManager.getLatestBatchData(batchManager);
if (
_newInterestRate == batch.annualInterestRate
|| block.timestamp >= trove.lastInterestRateAdjTime + INTEREST_RATE_ADJ_COOLDOWN
) {
return 0;
}
TroveChange memory troveChange;
troveChange.appliedRedistBoldDebtGain = trove.redistBoldDebtGain;
troveChange.batchAccruedManagementFee = batch.accruedManagementFee;
troveChange.oldWeightedRecordedDebt = batch.weightedRecordedDebt;
troveChange.newWeightedRecordedDebt = (
batch.entireDebtWithoutRedistribution - (trove.entireDebt - trove.redistBoldDebtGain)
) * batch.annualInterestRate + trove.entireDebt * _newInterestRate;
uint256 avgInterestRate = activePool.getNewApproxAvgInterestRateFromTroveChange(troveChange);
return _calcUpfrontFee(trove.entireDebt, avgInterestRate);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IActivePool.sol";
import "./IDefaultPool.sol";
import "./IPriceFeed.sol";
import "./IWhitelist.sol";
interface ILiquityBase {
function activePool() external view returns (IActivePool);
function getEntireBranchDebt() external view returns (uint256);
function getEntireBranchColl() external view returns (uint256);
function setWhitelist(IWhitelist _whitelist) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ILiquityBase.sol";
import "./ITroveNFT.sol";
import "./IBorrowerOperations.sol";
import "./IStabilityPool.sol";
import "./IBoldToken.sol";
import "./ISortedTroves.sol";
import "../Types/LatestTroveData.sol";
import "../Types/LatestBatchData.sol";
import "./IAddressesRegistryWhitelist.sol";
// Common interface for the Trove Manager.
interface ITroveManager is ILiquityBase {
enum Status {
nonExistent,
active,
closedByOwner,
closedByLiquidation,
zombie
}
function shutdownTime() external view returns (uint256);
function troveNFT() external view returns (ITroveNFT);
function stabilityPool() external view returns (IStabilityPool);
//function boldToken() external view returns (IBoldToken);
function sortedTroves() external view returns (ISortedTroves);
function borrowerOperations() external view returns (IBorrowerOperations);
function updateCRs(uint256 newCCR, uint256 newSCR, uint256 newMCR) external;
function updateLiquidationValues(uint256 newLiquidationPenaltySP, uint256 newliquidationPenaltyRedistribution)
external;
function isWhitelisted(address user) external view returns (bool);
function Troves(uint256 _id)
external
view
returns (
uint256 debt,
uint256 coll,
uint256 stake,
Status status,
uint64 arrayIndex,
uint64 lastDebtUpdateTime,
uint64 lastInterestRateAdjTime,
uint256 annualInterestRate,
address interestBatchManager,
uint256 batchDebtShares
);
function rewardSnapshots(uint256 _id) external view returns (uint256 coll, uint256 boldDebt);
function getTroveIdsCount() external view returns (uint256);
function getTroveFromTroveIdsArray(uint256 _index) external view returns (uint256);
function getCurrentICR(uint256 _troveId, uint256 _price) external view returns (uint256);
function lastZombieTroveId() external view returns (uint256);
function batchLiquidateTroves(uint256[] calldata _troveArray) external;
function redeemCollateral(
address _sender,
uint256 _boldAmount,
uint256 _price,
uint256 _redemptionRate,
uint256 _maxIterations
) external returns (uint256 _redemeedAmount);
function shutdown() external;
function urgentRedemption(uint256 _boldAmount, uint256[] calldata _troveIds, uint256 _minCollateral) external;
function getUnbackedPortionPriceAndRedeemability() external returns (uint256, uint256, bool);
function getLatestTroveData(uint256 _troveId) external view returns (LatestTroveData memory);
function getTroveAnnualInterestRate(uint256 _troveId) external view returns (uint256);
function getTroveStatus(uint256 _troveId) external view returns (Status);
function getLatestBatchData(address _batchAddress) external view returns (LatestBatchData memory);
// -- permissioned functions called by BorrowerOperations
function onOpenTrove(address _owner, uint256 _troveId, TroveChange memory _troveChange, uint256 _annualInterestRate)
external;
function onOpenTroveAndJoinBatch(
address _owner,
uint256 _troveId,
TroveChange memory _troveChange,
address _batchAddress,
uint256 _batchColl,
uint256 _batchDebt
) external;
// Called from `adjustZombieTrove()`
function setTroveStatusToActive(uint256 _troveId) external;
function onAdjustTroveInterestRate(
uint256 _troveId,
uint256 _newColl,
uint256 _newDebt,
uint256 _newAnnualInterestRate,
TroveChange calldata _troveChange
) external;
function onAdjustTrove(uint256 _troveId, uint256 _newColl, uint256 _newDebt, TroveChange calldata _troveChange)
external;
function onAdjustTroveInsideBatch(
uint256 _troveId,
uint256 _newTroveColl,
uint256 _newTroveDebt,
TroveChange memory _troveChange,
address _batchAddress,
uint256 _newBatchColl,
uint256 _newBatchDebt
) external;
function onApplyTroveInterest(
uint256 _troveId,
uint256 _newTroveColl,
uint256 _newTroveDebt,
address _batchAddress,
uint256 _newBatchColl,
uint256 _newBatchDebt,
TroveChange calldata _troveChange
) external;
function onCloseTrove(
uint256 _troveId,
TroveChange memory _troveChange, // decrease vars: entire, with interest, batch fee and redistribution
address _batchAddress,
uint256 _newBatchColl,
uint256 _newBatchDebt // entire, with interest and batch fee
) external;
// -- batches --
function onRegisterBatchManager(address _batchAddress, uint256 _annualInterestRate, uint256 _annualFee) external;
function onLowerBatchManagerAnnualFee(
address _batchAddress,
uint256 _newColl,
uint256 _newDebt,
uint256 _newAnnualManagementFee
) external;
function onSetBatchManagerAnnualInterestRate(
address _batchAddress,
uint256 _newColl,
uint256 _newDebt,
uint256 _newAnnualInterestRate,
uint256 _upfrontFee // needed by BatchUpdated event
) external;
struct OnSetInterestBatchManagerParams {
uint256 troveId;
uint256 troveColl; // entire, with redistribution
uint256 troveDebt; // entire, with interest, batch fee and redistribution
TroveChange troveChange;
address newBatchAddress;
uint256 newBatchColl; // updated collateral for new batch manager
uint256 newBatchDebt; // updated debt for new batch manager
}
function onSetInterestBatchManager(OnSetInterestBatchManagerParams calldata _params) external;
function onRemoveFromBatch(
uint256 _troveId,
uint256 _newTroveColl, // entire, with redistribution
uint256 _newTroveDebt, // entire, with interest, batch fee and redistribution
TroveChange memory _troveChange,
address _batchAddress,
uint256 _newBatchColl,
uint256 _newBatchDebt, // entire, with interest and batch fee
uint256 _newAnnualInterestRate
) external;
// -- end of permissioned functions --
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.24;
address constant ZERO_ADDRESS = address(0);
uint256 constant MAX_UINT256 = type(uint256).max;
uint256 constant DECIMAL_PRECISION = 1e18;
uint256 constant _100pct = DECIMAL_PRECISION;
uint256 constant _1pct = DECIMAL_PRECISION / 100;
// Amount of ETH to be locked in gas pool on opening troves
uint256 constant ETH_GAS_COMPENSATION = 0.0375 ether;
// Liquidation
uint256 constant MIN_LIQUIDATION_PENALTY_SP = 5e16; // 5%
uint256 constant MAX_LIQUIDATION_PENALTY_REDISTRIBUTION = 20e16; // 20%
// Batch CR buffer (same for all branches for now)
// On top of MCR to join a batch, or adjust inside a batch
uint256 constant BCR_ALL = 10 * _1pct;
// Fraction of collateral awarded to liquidator
uint256 constant COLL_GAS_COMPENSATION_DIVISOR = 200; // dividing by 200 yields 0.5%
uint256 constant COLL_GAS_COMPENSATION_CAP = 2 ether; // Max coll gas compensation capped at 2 ETH
// Minimum amount of net Bold debt a trove must have
uint256 constant MIN_DEBT = 2e18;
uint256 constant MIN_ANNUAL_INTEREST_RATE = _1pct / 2; // 0.5%
uint256 constant MAX_ANNUAL_INTEREST_RATE = 250 * _1pct;
// Batch management params
uint128 constant MAX_ANNUAL_BATCH_MANAGEMENT_FEE = uint128(_100pct / 10); // 10%
uint128 constant MIN_INTEREST_RATE_CHANGE_PERIOD = 1 hours; // only applies to batch managers / batched Troves
uint256 constant REDEMPTION_FEE_FLOOR = _1pct / 2; // 0.5%
// For the debt / shares ratio to increase by a factor 1e9
// at a average annual debt increase (compounded interest + fees) of 10%, it would take more than 217 years (log(1e9)/log(1.1))
// at a average annual debt increase (compounded interest + fees) of 50%, it would take more than 51 years (log(1e9)/log(1.5))
// The increase pace could be forced to be higher through an inflation attack,
// but precisely the fact that we have this max value now prevents the attack
uint256 constant MAX_BATCH_SHARES_RATIO = 1e9;
// Half-life of 6h. 6h = 360 min
// (1/2) = d^360 => d = (1/2)^(1/360)
uint256 constant REDEMPTION_MINUTE_DECAY_FACTOR = 998076443575628800;
// BETA: 18 digit decimal. Parameter by which to divide the redeemed fraction, in order to calc the new base rate from a redemption.
// Corresponds to (1 / ALPHA) in the white paper.
uint256 constant REDEMPTION_BETA = 1;
// To prevent redemptions unless Bold depegs below 0.95 and allow the system to take off
uint256 constant INITIAL_BASE_RATE = _100pct; // 100% initial redemption rate
// Discount to be used once the shutdown thas been triggered
uint256 constant URGENT_REDEMPTION_BONUS = 2e16; // 2%
uint256 constant ONE_MINUTE = 1 minutes;
uint256 constant ONE_YEAR = 365 days;
uint256 constant UPFRONT_INTEREST_PERIOD = 7 days;
uint256 constant INTEREST_RATE_ADJ_COOLDOWN = 7 days;
uint256 constant MIN_BOLD_IN_SP = 1e18;
// Dummy contract that lets legacy Hardhat tests query some of the constants
contract Constants {
uint256 public constant _ETH_GAS_COMPENSATION = ETH_GAS_COMPENSATION;
uint256 public constant _MIN_DEBT = MIN_DEBT;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IActivePool.sol";
import "./ILiquityBase.sol";
import "./IBoldToken.sol";
import "./ITroveManager.sol";
import "./IBoldRewardsReceiver.sol";
/*
* The Stability Pool holds Bold tokens deposited by Stability Pool depositors.
*
* When a trove is liquidated, then depending on system conditions, some of its Bold debt gets offset with
* Bold in the Stability Pool: that is, the offset debt evaporates, and an equal amount of Bold tokens in the Stability Pool is burned.
*
* Thus, a liquidation causes each depositor to receive a Bold loss, in proportion to their deposit as a share of total deposits.
* They also receive an Coll gain, as the collateral of the liquidated trove is distributed among Stability depositors,
* in the same proportion.
*
* When a liquidation occurs, it depletes every deposit by the same fraction: for example, a liquidation that depletes 40%
* of the total Bold in the Stability Pool, depletes 40% of each deposit.
*
* A deposit that has experienced a series of liquidations is termed a "compounded deposit": each liquidation depletes the deposit,
* multiplying it by some factor in range ]0,1[
*
* Please see the implementation spec in the proof document, which closely follows on from the compounded deposit / Coll gain derivations:
* https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf
*
*/
interface IStabilityPool is ILiquityBase, IBoldRewardsReceiver {
function boldToken() external view returns (IBoldToken);
function troveManager() external view returns (ITroveManager);
/* provideToSP():
* - Calculates depositor's Coll gain
* - Calculates the compounded deposit
* - Increases deposit, and takes new snapshots of accumulators P and S
* - Sends depositor's accumulated Coll gains to depositor
*/
function provideToSP(uint256 _amount, bool _doClaim) external;
/* withdrawFromSP():
* - Calculates depositor's Coll gain
* - Calculates the compounded deposit
* - Sends the requested BOLD withdrawal to depositor
* - (If _amount > userDeposit, the user withdraws all of their compounded deposit)
* - Decreases deposit by withdrawn amount and takes new snapshots of accumulators P and S
*/
function withdrawFromSP(uint256 _amount, bool doClaim) external;
function claimAllCollGains() external;
/*
* Initial checks:
* - Caller is TroveManager
* ---
* Cancels out the specified debt against the Bold contained in the Stability Pool (as far as possible)
* and transfers the Trove's collateral from ActivePool to StabilityPool.
* Only called by liquidation functions in the TroveManager.
*/
function offset(uint256 _debt, uint256 _coll) external;
function deposits(address _depositor) external view returns (uint256 initialValue);
function stashedColl(address _depositor) external view returns (uint256);
/*
* Returns the total amount of Coll held by the pool, accounted in an internal variable instead of `balance`,
* to exclude edge cases like Coll received from a self-destruct.
*/
function getCollBalance() external view returns (uint256);
/*
* Returns Bold held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset.
*/
function getTotalBoldDeposits() external view returns (uint256);
function getYieldGainsOwed() external view returns (uint256);
function getYieldGainsPending() external view returns (uint256);
/*
* Calculates the Coll gain earned by the deposit since its last snapshots were taken.
*/
function getDepositorCollGain(address _depositor) external view returns (uint256);
/*
* Calculates the BOLD yield gain earned by the deposit since its last snapshots were taken.
*/
function getDepositorYieldGain(address _depositor) external view returns (uint256);
/*
* Calculates what `getDepositorYieldGain` will be if interest is minted now.
*/
function getDepositorYieldGainWithPending(address _depositor) external view returns (uint256);
/*
* Return the user's compounded deposit.
*/
function getCompoundedBoldDeposit(address _depositor) external view returns (uint256);
function scaleToS(uint256 _scale) external view returns (uint256);
function scaleToB(uint256 _scale) external view returns (uint256);
function P() external view returns (uint256);
function currentScale() external view returns (uint256);
function P_PRECISION() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IDefaultPool {
function troveManagerAddress() external view returns (address);
function activePoolAddress() external view returns (address);
// --- Functions ---
function getCollBalance() external view returns (uint256);
function getBoldDebt() external view returns (uint256);
function sendCollToActivePool(uint256 _amount) external;
function receiveColl(uint256 _amount) external;
function increaseBoldDebt(uint256 _amount) external;
function decreaseBoldDebt(uint256 _amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {DECIMAL_PRECISION} from "./Constants.sol";
library LiquityMath {
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;
}
function _sub_min_0(uint256 _a, uint256 _b) internal pure returns (uint256) {
return (_a > _b) ? _a - _b : 0;
}
/*
* 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 function CollateralRegistry._calcDecayedBaseRate, that represent time in units of minutes
*
* 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 _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 debt is 0. Represents "infinite" CR.
else {
// if (_debt == 0)
return 2 ** 256 - 1;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ILiquityBase.sol";
import "./IAddRemoveManagers.sol";
import "./IBoldToken.sol";
import "./IPriceFeed.sol";
import "./ISortedTroves.sol";
import "./ITroveManager.sol";
import "./IWETH.sol";
// Common interface for the Borrower Operations.
interface IBorrowerOperations is ILiquityBase, IAddRemoveManagers {
function CCR() external view returns (uint256);
function MCR() external view returns (uint256);
function SCR() external view returns (uint256);
function BCR() external view returns (uint256);
function updateCRs(uint256 newCCR, uint256 newSCR, uint256 newMCR, uint256 newBCR) external;
function openTrove(
address _owner,
uint256 _ownerIndex,
uint256 _ETHAmount,
uint256 _boldAmount,
uint256 _upperHint,
uint256 _lowerHint,
uint256 _annualInterestRate,
uint256 _maxUpfrontFee,
address _addManager,
address _removeManager,
address _receiver
) external returns (uint256);
struct OpenTroveAndJoinInterestBatchManagerParams {
address owner;
uint256 ownerIndex;
uint256 collAmount;
uint256 boldAmount;
uint256 upperHint;
uint256 lowerHint;
address interestBatchManager;
uint256 maxUpfrontFee;
address addManager;
address removeManager;
address receiver;
}
function openTroveAndJoinInterestBatchManager(OpenTroveAndJoinInterestBatchManagerParams calldata _params)
external
returns (uint256);
function addColl(uint256 _troveId, uint256 _ETHAmount) external;
function withdrawColl(uint256 _troveId, uint256 _amount) external;
function withdrawBold(uint256 _troveId, uint256 _amount, uint256 _maxUpfrontFee) external;
function repayBold(uint256 _troveId, uint256 _amount) external;
function closeTrove(uint256 _troveId) external;
function adjustTrove(
uint256 _troveId,
uint256 _collChange,
bool _isCollIncrease,
uint256 _debtChange,
bool isDebtIncrease,
uint256 _maxUpfrontFee
) external;
function adjustZombieTrove(
uint256 _troveId,
uint256 _collChange,
bool _isCollIncrease,
uint256 _boldChange,
bool _isDebtIncrease,
uint256 _upperHint,
uint256 _lowerHint,
uint256 _maxUpfrontFee
) external;
function adjustTroveInterestRate(
uint256 _troveId,
uint256 _newAnnualInterestRate,
uint256 _upperHint,
uint256 _lowerHint,
uint256 _maxUpfrontFee
) external;
function applyPendingDebt(uint256 _troveId, uint256 _lowerHint, uint256 _upperHint) external;
function onLiquidateTrove(uint256 _troveId) external;
function claimCollateral() external;
function hasBeenShutDown() external view returns (bool);
function shutdown() external;
function shutdownFromOracleFailure() external;
function checkBatchManagerExists(address _batchMananger) external view returns (bool);
// -- individual delegation --
struct InterestIndividualDelegate {
address account;
uint128 minInterestRate;
uint128 maxInterestRate;
uint256 minInterestRateChangePeriod;
}
function getInterestIndividualDelegateOf(uint256 _troveId)
external
view
returns (InterestIndividualDelegate memory);
function setInterestIndividualDelegate(
uint256 _troveId,
address _delegate,
uint128 _minInterestRate,
uint128 _maxInterestRate,
// only needed if trove was previously in a batch:
uint256 _newAnnualInterestRate,
uint256 _upperHint,
uint256 _lowerHint,
uint256 _maxUpfrontFee,
uint256 _minInterestRateChangePeriod
) external;
function removeInterestIndividualDelegate(uint256 _troveId) external;
// -- batches --
struct InterestBatchManager {
uint128 minInterestRate;
uint128 maxInterestRate;
uint256 minInterestRateChangePeriod;
}
function registerBatchManager(
uint128 minInterestRate,
uint128 maxInterestRate,
uint128 currentInterestRate,
uint128 fee,
uint128 minInterestRateChangePeriod
) external;
function lowerBatchManagementFee(uint256 _newAnnualFee) external;
function setBatchManagerAnnualInterestRate(
uint128 _newAnnualInterestRate,
uint256 _upperHint,
uint256 _lowerHint,
uint256 _maxUpfrontFee
) external;
function interestBatchManagerOf(uint256 _troveId) external view returns (address);
function getInterestBatchManager(address _account) external view returns (InterestBatchManager memory);
function setInterestBatchManager(
uint256 _troveId,
address _newBatchManager,
uint256 _upperHint,
uint256 _lowerHint,
uint256 _maxUpfrontFee
) external;
function removeFromBatch(
uint256 _troveId,
uint256 _newAnnualInterestRate,
uint256 _upperHint,
uint256 _lowerHint,
uint256 _maxUpfrontFee
) external;
function switchBatchManager(
uint256 _troveId,
uint256 _removeUpperHint,
uint256 _removeLowerHint,
address _newBatchManager,
uint256 _addUpperHint,
uint256 _addLowerHint,
uint256 _maxUpfrontFee
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IWhitelist {
function addToWhitelist(address callingContract, address user) external;
function removeFromWhitelist(address callingContract, address user) external;
function isWhitelisted(address callingContract, address user) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IAddRemoveManagers {
function setAddManager(uint256 _troveId, address _manager) external;
function setRemoveManagerWithReceiver(uint256 _troveId, address _manager, address _receiver) external;
function addManagerOf(uint256 _troveId) external view returns (address);
function removeManagerReceiverOf(uint256 _troveId) external view returns (address, address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
struct LatestTroveData {
uint256 entireDebt;
uint256 entireColl;
uint256 redistBoldDebtGain;
uint256 redistCollGain;
uint256 accruedInterest;
uint256 recordedDebt;
uint256 annualInterestRate;
uint256 weightedRecordedDebt;
uint256 accruedBatchManagementFee;
uint256 lastInterestRateAdjTime;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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
pragma solidity ^0.8.0;
interface IBoldRewardsReceiver {
function triggerBoldRewards(uint256 _boldYield) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
struct LatestBatchData {
uint256 entireDebtWithoutRedistribution;
uint256 entireCollWithoutRedistribution;
uint256 accruedInterest;
uint256 recordedDebt;
uint256 annualInterestRate;
uint256 weightedRecordedDebt;
uint256 annualManagementFee;
uint256 accruedManagementFee;
uint256 weightedRecordedBatchManagementFee;
uint256 lastDebtUpdateTime;
uint256 lastInterestRateAdjTime;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IPriceFeed {
function fetchPrice() external returns (uint256, bool);
function fetchRedemptionPrice() external returns (uint256, bool);
function lastGoodPrice() external view returns (uint256);
function setAddresses(address _borrowerOperationsAddress) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ITroveManager.sol";
import {BatchId, BATCH_ID_ZERO} from "../Types/BatchId.sol";
interface ISortedTroves {
// -- Mutating functions (permissioned) --
function insert(uint256 _id, uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId) external;
function insertIntoBatch(
uint256 _troveId,
BatchId _batchId,
uint256 _annualInterestRate,
uint256 _prevId,
uint256 _nextId
) external;
function remove(uint256 _id) external;
function removeFromBatch(uint256 _id) external;
function reInsert(uint256 _id, uint256 _newAnnualInterestRate, uint256 _prevId, uint256 _nextId) external;
function reInsertBatch(BatchId _id, uint256 _newAnnualInterestRate, uint256 _prevId, uint256 _nextId) external;
// -- View functions --
function contains(uint256 _id) external view returns (bool);
function isBatchedNode(uint256 _id) external view returns (bool);
function isEmptyBatch(BatchId _id) external view returns (bool);
function isEmpty() external view returns (bool);
function getSize() external view returns (uint256);
function getFirst() external view returns (uint256);
function getLast() external view returns (uint256);
function getNext(uint256 _id) external view returns (uint256);
function getPrev(uint256 _id) external view returns (uint256);
function validInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId)
external
view
returns (bool);
function findInsertPosition(uint256 _annualInterestRate, uint256 _prevId, uint256 _nextId)
external
view
returns (uint256, uint256);
// Public state variable getters
function borrowerOperationsAddress() external view returns (address);
function troveManager() external view returns (ITroveManager);
function size() external view returns (uint256);
function nodes(uint256 _id) external view returns (uint256 nextId, uint256 prevId, BatchId batchId, bool exists);
function batches(BatchId _id) external view returns (uint256 head, uint256 tail);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "./IBoldToken.sol";
import "./ITroveManager.sol";
interface ICollateralRegistry {
struct RedemptionTotals {
uint256 numCollaterals;
uint256 boldSupplyAtStart;
uint256 unbacked;
uint256 redeemedAmount;
}
function addNewCollaterals(
IERC20Metadata[] memory _tokens,
ITroveManager[] memory _troveManagers
) external;
function removeCollateral(uint256 index) external;
function baseRate() external view returns (uint256);
function lastFeeOperationTime() external view returns (uint256);
function redeemCollateral(uint256 _boldamount, uint256 _maxIterations, uint256 _maxFeePercentage) external;
// getters
function totalCollaterals() external view returns (uint256);
function getToken(uint256 _index) external view returns (IERC20Metadata);
function getTroveManager(uint256 _index) external view returns (ITroveManager);
function boldToken() external view returns (IBoldToken);
function getRedemptionRate() external view returns (uint256);
function getRedemptionRateWithDecay() external view returns (uint256);
function getRedemptionRateForRedeemedAmount(uint256 _redeemAmount) external view returns (uint256);
function getRedemptionFeeWithDecay(uint256 _ETHDrawn) external view returns (uint256);
function getEffectiveRedemptionFeeInBold(uint256 _redeemAmount) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOwned {
function owner() external view returns (address);
function nominatedOwner() external view returns (address);
function nominateNewOwner(address owner) external;
function acceptOwnership() external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)
pragma solidity ^0.8.0;
interface IERC5267 {
/**
* @dev MAY be emitted to signal that the domain could have changed.
*/
event EIP712DomainChanged();
/**
* @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
* signature.
*/
function eip712Domain()
external
view
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IHintHelpers {
function getApproxHint(uint256 _collIndex, uint256 _interestRate, uint256 _numTrials, uint256 _inputRandomSeed)
external
view
returns (uint256 hintId, uint256 diff, uint256 latestRandomSeed);
function predictOpenTroveUpfrontFee(uint256 _collIndex, uint256 _borrowedAmount, uint256 _interestRate)
external
view
returns (uint256);
function predictAdjustInterestRateUpfrontFee(uint256 _collIndex, uint256 _troveId, uint256 _newInterestRate)
external
view
returns (uint256);
function forcePredictAdjustInterestRateUpfrontFee(uint256 _collIndex, uint256 _troveId, uint256 _newInterestRate)
external
view
returns (uint256);
function predictAdjustTroveUpfrontFee(uint256 _collIndex, uint256 _troveId, uint256 _debtIncrease)
external
view
returns (uint256);
function predictAdjustBatchInterestRateUpfrontFee(
uint256 _collIndex,
address _batchAddress,
uint256 _newInterestRate
) external view returns (uint256);
function predictJoinBatchInterestRateUpfrontFee(uint256 _collIndex, uint256 _troveId, address _batchAddress)
external
view
returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "./ITroveManager.sol";
import "../Interfaces/IWhitelist.sol";
interface ITroveNFT is IERC721Metadata {
function mint(address _owner, uint256 _troveId) external;
function burn(uint256 _troveId) external;
function setWhitelist(IWhitelist _whitelist) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/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.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
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].
*
* CAUTION: See Security Considerations above.
*/
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
pragma solidity ^0.8.0;
import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol";
import "openzeppelin-contracts/contracts/interfaces/IERC5267.sol";
import "./IOwned.sol";
interface IBoldToken is IERC20Metadata, IERC20Permit, IOwned, IERC5267 {
function mint(address _account, uint256 _amount) external;
function burn(address _account, uint256 _amount) external;
function sendToPool(address _sender, address poolAddress, uint256 _amount) external;
function returnFromPool(address poolAddress, address user, uint256 _amount) external;
function setCollateralRegistry(address _collateralRegistryAddress) external;
function setMinter(address minter, bool isMinter) external;
function setBurner(address burner, bool isBurner) external;
function setStabilityPool(address stabilityPool, bool isStabilityPool) external;
function isMinter(address minter) external view returns (bool);
function isBurner(address burner) external view returns (bool);
function isStabilityPool(address stabilityPool) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IInterestRouter.sol";
import "./IBoldRewardsReceiver.sol";
import "../Types/TroveChange.sol";
interface IActivePool {
function SP_YIELD_SPLIT() external view returns (uint256);
function defaultPoolAddress() external view returns (address);
function borrowerOperationsAddress() external view returns (address);
function troveManagerAddress() external view returns (address);
function interestRouter() external view returns (IInterestRouter);
// We avoid IStabilityPool here in order to prevent creating a dependency cycle that would break flattening
function stabilityPool() external view returns (IBoldRewardsReceiver);
function getCollBalance() external view returns (uint256);
function getBoldDebt() external view returns (uint256);
function lastAggUpdateTime() external view returns (uint256);
function aggRecordedDebt() external view returns (uint256);
function aggWeightedDebtSum() external view returns (uint256);
function aggBatchManagementFees() external view returns (uint256);
function aggWeightedBatchManagementFeeSum() external view returns (uint256);
function calcPendingAggInterest() external view returns (uint256);
function calcPendingSPYield() external view returns (uint256);
function calcPendingAggBatchManagementFee() external view returns (uint256);
function getNewApproxAvgInterestRateFromTroveChange(TroveChange calldata _troveChange)
external
view
returns (uint256);
function mintAggInterest() external;
function mintAggInterestAndAccountForTroveChange(TroveChange calldata _troveChange, address _batchManager)
external;
function mintBatchManagementFeeAndAccountForChange(TroveChange calldata _troveChange, address _batchAddress)
external;
function setShutdownFlag() external;
function hasBeenShutDown() external view returns (bool);
function shutdownTime() external view returns (uint256);
function sendColl(address _account, uint256 _amount) external;
function sendCollToDefaultPool(uint256 _amount) external;
function receiveColl(uint256 _amount) external;
function accountForReceivedColl(uint256 _amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IInterestRouter {
// Currently the Interest Router doesn’t need any specific function
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IWETH is IERC20Metadata {
function deposit() external payable;
function withdraw(uint256 wad) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
type BatchId is address;
using {equals as ==, notEquals as !=, isZero, isNotZero} for BatchId global;
function equals(BatchId a, BatchId b) pure returns (bool) {
return BatchId.unwrap(a) == BatchId.unwrap(b);
}
function notEquals(BatchId a, BatchId b) pure returns (bool) {
return !(a == b);
}
function isZero(BatchId x) pure returns (bool) {
return x == BATCH_ID_ZERO;
}
function isNotZero(BatchId x) pure returns (bool) {
return !x.isZero();
}
BatchId constant BATCH_ID_ZERO = BatchId.wrap(address(0));// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
struct TroveChange {
uint256 appliedRedistBoldDebtGain;
uint256 appliedRedistCollGain;
uint256 collIncrease;
uint256 collDecrease;
uint256 debtIncrease;
uint256 debtDecrease;
uint256 newWeightedRecordedDebt;
uint256 oldWeightedRecordedDebt;
uint256 upfrontFee;
uint256 batchAccruedManagementFee;
uint256 newWeightedRecordedBatchManagementFee;
uint256 oldWeightedRecordedBatchManagementFee;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IWhitelist.sol";
interface IAddressesRegistryWhitelist {
function whitelist() external view returns (IWhitelist);
}{
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"appendCBOR": true,
"bytecodeHash": "ipfs",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 1
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"openzeppelin/=lib/V2-gov/lib/openzeppelin-contracts/",
"@chimera/=lib/V2-gov/lib/chimera/src/",
"@openzeppelin/contracts/=lib/V2-gov/lib/openzeppelin-contracts/contracts/",
"Solady/=lib/Solady/src/",
"V2-gov/=lib/V2-gov/",
"chimera/=lib/V2-gov/lib/chimera/src/",
"ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"v4-core/=lib/V2-gov/lib/v4-core/"
],
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ICollateralRegistry","name":"_collateralRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralRegistry","outputs":[{"internalType":"contract ICollateralRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"uint256","name":"_troveId","type":"uint256"},{"internalType":"uint256","name":"_newInterestRate","type":"uint256"}],"name":"forcePredictAdjustInterestRateUpfrontFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"uint256","name":"_interestRate","type":"uint256"},{"internalType":"uint256","name":"_numTrials","type":"uint256"},{"internalType":"uint256","name":"_inputRandomSeed","type":"uint256"}],"name":"getApproxHint","outputs":[{"internalType":"uint256","name":"hintId","type":"uint256"},{"internalType":"uint256","name":"diff","type":"uint256"},{"internalType":"uint256","name":"latestRandomSeed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"address","name":"_batchAddress","type":"address"},{"internalType":"uint256","name":"_newInterestRate","type":"uint256"}],"name":"predictAdjustBatchInterestRateUpfrontFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"uint256","name":"_troveId","type":"uint256"},{"internalType":"uint256","name":"_newInterestRate","type":"uint256"}],"name":"predictAdjustInterestRateUpfrontFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"uint256","name":"_troveId","type":"uint256"},{"internalType":"uint256","name":"_debtIncrease","type":"uint256"}],"name":"predictAdjustTroveUpfrontFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"uint256","name":"_troveId","type":"uint256"},{"internalType":"address","name":"_batchAddress","type":"address"}],"name":"predictJoinBatchInterestRateUpfrontFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"uint256","name":"_borrowedAmount","type":"uint256"},{"internalType":"address","name":"_batchAddress","type":"address"}],"name":"predictOpenTroveAndJoinBatchUpfrontFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"uint256","name":"_borrowedAmount","type":"uint256"},{"internalType":"uint256","name":"_interestRate","type":"uint256"}],"name":"predictOpenTroveUpfrontFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collIndex","type":"uint256"},{"internalType":"uint256","name":"_troveId","type":"uint256"},{"internalType":"uint256","name":"_newInterestRate","type":"uint256"}],"name":"predictRemoveFromBatchUpfrontFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a060405234801561000f575f80fd5b50604051611fa8380380611fa883398101604081905261002e9161003f565b6001600160a01b031660805261006c565b5f6020828403121561004f575f80fd5b81516001600160a01b0381168114610065575f80fd5b9392505050565b608051611ee56100c35f395f818161019d015281816101e50152818161060f015281816107be01528181610b2c01528181610d5501528181610eec01528181611188015281816112f0015261152f0152611ee55ff3fe608060405234801561000f575f80fd5b5060043610610097575f3560e01c80631c2feb321461009b5780631cfc19ee146100ce5780633a0b1dfa146100ef5780634e5d055414610102578063663224be146101155780639e6bd07a14610128578063a3bc96721461013b578063a3f4df7e1461014e578063a5937ba514610185578063d330fadd14610198578063e18c9c01146101cc575b5f80fd5b6100ae6100a93660046119ea565b6101df565b604080519384526020840192909252908201526060015b60405180910390f35b6100e16100dc366004611a19565b6105ed565b6040519081526020016100c5565b6100e16100fd366004611a19565b610797565b6100e1610110366004611a59565b610b0a565b6100e1610123366004611a19565b610d33565b6100e1610136366004611a59565b610eca565b6100e1610149366004611a19565b611166565b6101786040518060400160405280600b81526020016a48696e7448656c7065727360a81b81525081565b6040516100c59190611a8f565b6100e1610193366004611adb565b6112ce565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b6040516100c59190611b10565b6100e16101da366004611a19565b61150d565b5f805f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630bc17feb896040518263ffffffff1660e01b815260040161023191815260200190565b602060405180830381865afa15801561024c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102709190611b24565b90505f816001600160a01b031663ae9187546040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102d39190611b24565b90505f826001600160a01b0316634aff96e16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610312573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103369190611b3f565b9050805f03610350575f80889550955095505050506105e3565b816001600160a01b0316634d6228316040518163ffffffff1660e01b8152600401602060405180830381865afa15801561038c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103b09190611b3f565b955061042889846001600160a01b0316635ef3b8bf896040518263ffffffff1660e01b81526004016103e491815260200190565b602060405180830381865afa1580156103ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104239190611b3f565b61187d565b945086935060015b888110156105de5760408051602081018790520160408051601f19818403018152919052805160209091012094505f6104698387611b6a565b604051630f788db160e11b8152600481018290529091505f906001600160a01b03871690631ef11b6290602401602060405180830381865afa1580156104b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104d59190611b3f565b60405163061a029760e51b8152600481018290529091506001600160a01b0386169063c34052e090602401602060405180830381865afa15801561051b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053f9190611b7d565b61054a5750506105d6565b604051635ef3b8bf60e01b8152600481018290525f906001600160a01b03881690635ef3b8bf90602401602060405180830381865afa15801561058f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105b39190611b3f565b90505f6105c0828f61187d565b9050898110156105d157809950829a505b505050505b600101610430565b505050505b9450945094915050565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630bc17feb90602401602060405180830381865afa158015610654573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106789190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106db9190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa158015610724573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107489190611c00565b90508060c0015185148061076f575062093a8081610120015161076b9190611c99565b4210155b1561077f575f9350505050610790565b61078a8282876118a8565b93505050505b9392505050565b5f815f036107a657505f610790565b604051630bc17feb60e01b8152600481018590525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630bc17feb90602401602060405180830381865afa15801561080b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061082f9190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108929190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa1580156108db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108ff9190611c00565b604051632904486760e21b8152600481018890529091505f906001600160a01b0385169063a411219c9060240161014060405180830381865afa158015610948573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096c9190611cc7565b509850505050505050505061097f611995565b60408301518152608081018790526001600160a01b0382166109cb5760c083015183516109ad908990611c99565b6109b79190611d61565b60c082015260e08084015190820152610a83565b60405163309e565760e11b81525f906001600160a01b0387169063613cacae906109f9908690600401611b10565b61016060405180830381865afa158015610a15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a399190611d78565b60e081015161012084015260808101516040860151825192935090918a91610a6091611c99565b610a6a9190611c99565b610a749190611d61565b60c083015260a0015160e08201525b6040516385fe37a360e01b81525f906001600160a01b038616906385fe37a390610ab1908590600401611e09565b602060405180830381865afa158015610acc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610af09190611b3f565b9050610afc888261195a565b9a9950505050505050505050565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630bc17feb90602401602060405180830381865afa158015610b71573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b959190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf89190611b24565b90505f826001600160a01b031663613cacae866040518263ffffffff1660e01b8152600401610c279190611b10565b61016060405180830381865afa158015610c43573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c679190611d78565b9050610c71611995565b608080820188905260e08084015161012084015260a0840151908301528201518251610c9e908990611c99565b610ca89190611d61565b60c08201526040516385fe37a360e01b81525f906001600160a01b038516906385fe37a390610cdb908590600401611e09565b602060405180830381865afa158015610cf6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1a9190611b3f565b9050610d26888261195a565b9998505050505050505050565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630bc17feb90602401602060405180830381865afa158015610d9a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dbe9190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dfd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e219190611b24565b9050610e2b611995565b60808101869052610e3c8587611d61565b60c08201526040516385fe37a360e01b81525f906001600160a01b038416906385fe37a390610e6f908590600401611e09565b602060405180830381865afa158015610e8a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eae9190611b3f565b9050610ebe82608001518261195a565b98975050505050505050565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630bc17feb90602401602060405180830381865afa158015610f31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f559190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fb89190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa158015611001573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110259190611c00565b90505f836001600160a01b031663613cacae876040518263ffffffff1660e01b81526004016110549190611b10565b61016060405180830381865afa158015611070573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110949190611d78565b905061109e611995565b6040830151815260e08083015161012083015283015160a08301516110c39190611c99565b60e08201526080820151835183516110db9190611c99565b6110e59190611d61565b60c08201526040516385fe37a360e01b81525f906001600160a01b038616906385fe37a390611118908590600401611e09565b602060405180830381865afa158015611133573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111579190611b3f565b9050610afc845f01518261195a565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630bc17feb90602401602060405180830381865afa1580156111cd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f19190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611230573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112549190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa15801561129d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112c19190611c00565b905061078a8282876118a8565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630bc17feb90602401602060405180830381865afa158015611335573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113599190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611398573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113bc9190611b24565b90505f826001600160a01b031663613cacae876040518263ffffffff1660e01b81526004016113eb9190611b10565b61016060405180830381865afa158015611407573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061142b9190611d78565b90508060800151851480611452575062093a8081610140015161144e9190611c99565b4210155b15611462575f9350505050610790565b61146a611995565b60e08201516101208201528151611482908790611d61565b60c082015260a082015160e08201526040516385fe37a360e01b81525f906001600160a01b038516906385fe37a3906114bf908590600401611e09565b602060405180830381865afa1580156114da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114fe9190611b3f565b9050610d26835f01518261195a565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630bc17feb90602401602060405180830381865afa158015611574573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115989190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115fb9190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa158015611644573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116689190611c00565b604051632904486760e21b8152600481018890529091505f906001600160a01b0385169063a411219c9060240161014060405180830381865afa1580156116b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116d59190611cc7565b50985050505050505050505f846001600160a01b031663613cacae836040518263ffffffff1660e01b815260040161170d9190611b10565b61016060405180830381865afa158015611729573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061174d9190611d78565b90508060800151871480611774575062093a808361012001516117709190611c99565b4210155b15611786575f95505050505050610790565b61178e611995565b6040840151815260e08083015161012083015260a08301519082015283516117b7908990611d61565b6080830151604086015186516117cd9190611e89565b84516117d99190611e89565b6117e39190611d61565b6117ed9190611c99565b60c08201526040516385fe37a360e01b81525f906001600160a01b038716906385fe37a390611820908590600401611e09565b602060405180830381865afa15801561183b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185f9190611b3f565b905061186e855f01518261195a565b9b9a5050505050505050505050565b5f81831015611895576118908383611e89565b61189f565b61189f8284611e89565b90505b92915050565b5f6118b1611995565b6040840151815283516118c5908490611d61565b60c082015260e080850151908201526040516385fe37a360e01b81525f906001600160a01b038716906385fe37a390611902908590600401611e09565b602060405180830381865afa15801561191d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119419190611b3f565b9050611950855f01518261195a565b9695505050505050565b5f670de0b6b3a76400006301e1338062093a806119778587611d61565b6119819190611d61565b61198b9190611e9c565b61189f9190611e9c565b6040518061018001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f805f80608085870312156119fd575f80fd5b5050823594602084013594506040840135936060013592509050565b5f805f60608486031215611a2b575f80fd5b505081359360208301359350604090920135919050565b6001600160a01b0381168114611a56575f80fd5b50565b5f805f60608486031215611a6b575f80fd5b83359250602084013591506040840135611a8481611a42565b809150509250925092565b5f602080835283518060208501525f5b81811015611abb57858101830151858201604001528201611a9f565b505f604082860101526040601f19601f8301168501019250505092915050565b5f805f60608486031215611aed575f80fd5b833592506020840135611aff81611a42565b929592945050506040919091013590565b6001600160a01b0391909116815260200190565b5f60208284031215611b34575f80fd5b815161079081611a42565b5f60208284031215611b4f575f80fd5b5051919050565b634e487b7160e01b5f52601260045260245ffd5b5f82611b7857611b78611b56565b500690565b5f60208284031215611b8d575f80fd5b81518015158114610790575f80fd5b60405161014081016001600160401b0381118282101715611bcb57634e487b7160e01b5f52604160045260245ffd5b60405290565b60405161016081016001600160401b0381118282101715611bcb57634e487b7160e01b5f52604160045260245ffd5b5f6101408284031215611c11575f80fd5b611c19611b9c565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152508091505092915050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156118a2576118a2611c85565b80516001600160401b0381168114611cc2575f80fd5b919050565b5f805f805f805f805f806101408b8d031215611ce1575f80fd5b8a51995060208b0151985060408b0151975060608b015160058110611d04575f80fd5b9650611d1260808c01611cac565b9550611d2060a08c01611cac565b9450611d2e60c08c01611cac565b935060e08b015192506101008b0151611d4681611a42565b809250506101208b015190509295989b9194979a5092959850565b80820281158282048414176118a2576118a2611c85565b5f6101608284031215611d89575f80fd5b611d91611bd1565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152506101408084015181830152508091505092915050565b815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c0808301519082015260e0808301519082015261010080830151908201526101208083015190820152610140808301519082015261016091820151918101919091526101800190565b818103818111156118a2576118a2611c85565b5f82611eaa57611eaa611b56565b50049056fea26469706673582212200901534e3758b3607d425af809880c8f3807c451cc4e84ba24e34b15a5b60f1d64736f6c634300081800330000000000000000000000009431a1cd7f53fdf299f89eac7450682ff3551313
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610097575f3560e01c80631c2feb321461009b5780631cfc19ee146100ce5780633a0b1dfa146100ef5780634e5d055414610102578063663224be146101155780639e6bd07a14610128578063a3bc96721461013b578063a3f4df7e1461014e578063a5937ba514610185578063d330fadd14610198578063e18c9c01146101cc575b5f80fd5b6100ae6100a93660046119ea565b6101df565b604080519384526020840192909252908201526060015b60405180910390f35b6100e16100dc366004611a19565b6105ed565b6040519081526020016100c5565b6100e16100fd366004611a19565b610797565b6100e1610110366004611a59565b610b0a565b6100e1610123366004611a19565b610d33565b6100e1610136366004611a59565b610eca565b6100e1610149366004611a19565b611166565b6101786040518060400160405280600b81526020016a48696e7448656c7065727360a81b81525081565b6040516100c59190611a8f565b6100e1610193366004611adb565b6112ce565b6101bf7f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff355131381565b6040516100c59190611b10565b6100e16101da366004611a19565b61150d565b5f805f807f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513136001600160a01b0316630bc17feb896040518263ffffffff1660e01b815260040161023191815260200190565b602060405180830381865afa15801561024c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102709190611b24565b90505f816001600160a01b031663ae9187546040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102d39190611b24565b90505f826001600160a01b0316634aff96e16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610312573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103369190611b3f565b9050805f03610350575f80889550955095505050506105e3565b816001600160a01b0316634d6228316040518163ffffffff1660e01b8152600401602060405180830381865afa15801561038c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103b09190611b3f565b955061042889846001600160a01b0316635ef3b8bf896040518263ffffffff1660e01b81526004016103e491815260200190565b602060405180830381865afa1580156103ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104239190611b3f565b61187d565b945086935060015b888110156105de5760408051602081018790520160408051601f19818403018152919052805160209091012094505f6104698387611b6a565b604051630f788db160e11b8152600481018290529091505f906001600160a01b03871690631ef11b6290602401602060405180830381865afa1580156104b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104d59190611b3f565b60405163061a029760e51b8152600481018290529091506001600160a01b0386169063c34052e090602401602060405180830381865afa15801561051b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053f9190611b7d565b61054a5750506105d6565b604051635ef3b8bf60e01b8152600481018290525f906001600160a01b03881690635ef3b8bf90602401602060405180830381865afa15801561058f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105b39190611b3f565b90505f6105c0828f61187d565b9050898110156105d157809950829a505b505050505b600101610430565b505050505b9450945094915050565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513131690630bc17feb90602401602060405180830381865afa158015610654573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106789190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106db9190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa158015610724573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107489190611c00565b90508060c0015185148061076f575062093a8081610120015161076b9190611c99565b4210155b1561077f575f9350505050610790565b61078a8282876118a8565b93505050505b9392505050565b5f815f036107a657505f610790565b604051630bc17feb60e01b8152600481018590525f907f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513136001600160a01b031690630bc17feb90602401602060405180830381865afa15801561080b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061082f9190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108929190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa1580156108db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108ff9190611c00565b604051632904486760e21b8152600481018890529091505f906001600160a01b0385169063a411219c9060240161014060405180830381865afa158015610948573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096c9190611cc7565b509850505050505050505061097f611995565b60408301518152608081018790526001600160a01b0382166109cb5760c083015183516109ad908990611c99565b6109b79190611d61565b60c082015260e08084015190820152610a83565b60405163309e565760e11b81525f906001600160a01b0387169063613cacae906109f9908690600401611b10565b61016060405180830381865afa158015610a15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a399190611d78565b60e081015161012084015260808101516040860151825192935090918a91610a6091611c99565b610a6a9190611c99565b610a749190611d61565b60c083015260a0015160e08201525b6040516385fe37a360e01b81525f906001600160a01b038616906385fe37a390610ab1908590600401611e09565b602060405180830381865afa158015610acc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610af09190611b3f565b9050610afc888261195a565b9a9950505050505050505050565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513131690630bc17feb90602401602060405180830381865afa158015610b71573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b959190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf89190611b24565b90505f826001600160a01b031663613cacae866040518263ffffffff1660e01b8152600401610c279190611b10565b61016060405180830381865afa158015610c43573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c679190611d78565b9050610c71611995565b608080820188905260e08084015161012084015260a0840151908301528201518251610c9e908990611c99565b610ca89190611d61565b60c08201526040516385fe37a360e01b81525f906001600160a01b038516906385fe37a390610cdb908590600401611e09565b602060405180830381865afa158015610cf6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1a9190611b3f565b9050610d26888261195a565b9998505050505050505050565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513131690630bc17feb90602401602060405180830381865afa158015610d9a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dbe9190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dfd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e219190611b24565b9050610e2b611995565b60808101869052610e3c8587611d61565b60c08201526040516385fe37a360e01b81525f906001600160a01b038416906385fe37a390610e6f908590600401611e09565b602060405180830381865afa158015610e8a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eae9190611b3f565b9050610ebe82608001518261195a565b98975050505050505050565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513131690630bc17feb90602401602060405180830381865afa158015610f31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f559190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fb89190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa158015611001573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110259190611c00565b90505f836001600160a01b031663613cacae876040518263ffffffff1660e01b81526004016110549190611b10565b61016060405180830381865afa158015611070573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110949190611d78565b905061109e611995565b6040830151815260e08083015161012083015283015160a08301516110c39190611c99565b60e08201526080820151835183516110db9190611c99565b6110e59190611d61565b60c08201526040516385fe37a360e01b81525f906001600160a01b038616906385fe37a390611118908590600401611e09565b602060405180830381865afa158015611133573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111579190611b3f565b9050610afc845f01518261195a565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513131690630bc17feb90602401602060405180830381865afa1580156111cd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f19190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611230573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112549190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa15801561129d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112c19190611c00565b905061078a8282876118a8565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513131690630bc17feb90602401602060405180830381865afa158015611335573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113599190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611398573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113bc9190611b24565b90505f826001600160a01b031663613cacae876040518263ffffffff1660e01b81526004016113eb9190611b10565b61016060405180830381865afa158015611407573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061142b9190611d78565b90508060800151851480611452575062093a8081610140015161144e9190611c99565b4210155b15611462575f9350505050610790565b61146a611995565b60e08201516101208201528151611482908790611d61565b60c082015260a082015160e08201526040516385fe37a360e01b81525f906001600160a01b038516906385fe37a3906114bf908590600401611e09565b602060405180830381865afa1580156114da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114fe9190611b3f565b9050610d26835f01518261195a565b604051630bc17feb60e01b8152600481018490525f9081906001600160a01b037f0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff35513131690630bc17feb90602401602060405180830381865afa158015611574573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115989190611b24565b90505f816001600160a01b0316637f7dde4a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115fb9190611b24565b604051632ab4fd0160e21b8152600481018790529091505f906001600160a01b0384169063aad3f4049060240161014060405180830381865afa158015611644573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116689190611c00565b604051632904486760e21b8152600481018890529091505f906001600160a01b0385169063a411219c9060240161014060405180830381865afa1580156116b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116d59190611cc7565b50985050505050505050505f846001600160a01b031663613cacae836040518263ffffffff1660e01b815260040161170d9190611b10565b61016060405180830381865afa158015611729573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061174d9190611d78565b90508060800151871480611774575062093a808361012001516117709190611c99565b4210155b15611786575f95505050505050610790565b61178e611995565b6040840151815260e08083015161012083015260a08301519082015283516117b7908990611d61565b6080830151604086015186516117cd9190611e89565b84516117d99190611e89565b6117e39190611d61565b6117ed9190611c99565b60c08201526040516385fe37a360e01b81525f906001600160a01b038716906385fe37a390611820908590600401611e09565b602060405180830381865afa15801561183b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185f9190611b3f565b905061186e855f01518261195a565b9b9a5050505050505050505050565b5f81831015611895576118908383611e89565b61189f565b61189f8284611e89565b90505b92915050565b5f6118b1611995565b6040840151815283516118c5908490611d61565b60c082015260e080850151908201526040516385fe37a360e01b81525f906001600160a01b038716906385fe37a390611902908590600401611e09565b602060405180830381865afa15801561191d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119419190611b3f565b9050611950855f01518261195a565b9695505050505050565b5f670de0b6b3a76400006301e1338062093a806119778587611d61565b6119819190611d61565b61198b9190611e9c565b61189f9190611e9c565b6040518061018001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f805f80608085870312156119fd575f80fd5b5050823594602084013594506040840135936060013592509050565b5f805f60608486031215611a2b575f80fd5b505081359360208301359350604090920135919050565b6001600160a01b0381168114611a56575f80fd5b50565b5f805f60608486031215611a6b575f80fd5b83359250602084013591506040840135611a8481611a42565b809150509250925092565b5f602080835283518060208501525f5b81811015611abb57858101830151858201604001528201611a9f565b505f604082860101526040601f19601f8301168501019250505092915050565b5f805f60608486031215611aed575f80fd5b833592506020840135611aff81611a42565b929592945050506040919091013590565b6001600160a01b0391909116815260200190565b5f60208284031215611b34575f80fd5b815161079081611a42565b5f60208284031215611b4f575f80fd5b5051919050565b634e487b7160e01b5f52601260045260245ffd5b5f82611b7857611b78611b56565b500690565b5f60208284031215611b8d575f80fd5b81518015158114610790575f80fd5b60405161014081016001600160401b0381118282101715611bcb57634e487b7160e01b5f52604160045260245ffd5b60405290565b60405161016081016001600160401b0381118282101715611bcb57634e487b7160e01b5f52604160045260245ffd5b5f6101408284031215611c11575f80fd5b611c19611b9c565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152508091505092915050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156118a2576118a2611c85565b80516001600160401b0381168114611cc2575f80fd5b919050565b5f805f805f805f805f806101408b8d031215611ce1575f80fd5b8a51995060208b0151985060408b0151975060608b015160058110611d04575f80fd5b9650611d1260808c01611cac565b9550611d2060a08c01611cac565b9450611d2e60c08c01611cac565b935060e08b015192506101008b0151611d4681611a42565b809250506101208b015190509295989b9194979a5092959850565b80820281158282048414176118a2576118a2611c85565b5f6101608284031215611d89575f80fd5b611d91611bd1565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152506101408084015181830152508091505092915050565b815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c0808301519082015260e0808301519082015261010080830151908201526101208083015190820152610140808301519082015261016091820151918101919091526101800190565b818103818111156118a2576118a2611c85565b5f82611eaa57611eaa611b56565b50049056fea26469706673582212200901534e3758b3607d425af809880c8f3807c451cc4e84ba24e34b15a5b60f1d64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff3551313
-----Decoded View---------------
Arg [0] : _collateralRegistry (address): 0x9431A1CD7f53FDf299f89EAc7450682Ff3551313
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000009431a1cd7f53fdf299f89eac7450682ff3551313
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.