Overview
ETH Balance
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Nominate New Own... | 2472457 | 172 days ago | IN | 0 ETH | 0.00000005 |
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 2891226 | 167 days ago | 0 ETH |
Cross-Chain Transactions
Contract Source Code Verified (Exact Match)
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.24;
import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "./Dependencies/Constants.sol";
import "./Dependencies/LiquityMath.sol";
import "./Dependencies/Owned.sol";
import "./Interfaces/ITroveManager.sol";
import "./Interfaces/IBoldToken.sol";
import "./Interfaces/ICollateralRegistry.sol";
import "./Interfaces/IWhitelist.sol";
contract CollateralRegistry is Owned, ICollateralRegistry {
IBoldToken public immutable boldToken;
uint256 public totalCollaterals;
IERC20Metadata[10] internal collateralTokens;
ITroveManager[10] internal troveManagers;
uint256 public baseRate;
// The timestamp of the latest fee operation (redemption or new Bold issuance)
uint256 public lastFeeOperationTime = block.timestamp;
event BaseRateUpdated(uint256 _baseRate);
event LastFeeOpTimeUpdated(uint256 _lastFeeOpTime);
event NewCollateralAdded(address collateral, address troveManager);
event CollateralRemoved(address collateral, address troveManager);
event WhitelistSet(address whitelist);
error ZeroAddress();
// --- Constructor ---
constructor(
IBoldToken _boldToken,
IERC20Metadata[] memory _tokens,
ITroveManager[] memory _troveManagers,
address _owner
) Owned(_owner) {
uint256 numTokens = _tokens.length;
require(numTokens > 0 && numTokens <= 10, "Collateral list invalid");
totalCollaterals = numTokens;
boldToken = _boldToken;
for (uint8 i; i < numTokens; i++) {
requireNotZeroAddress(address(_tokens[i]));
requireNotZeroAddress(address(_troveManagers[i]));
collateralTokens[i] = _tokens[i];
troveManagers[i] = _troveManagers[i];
}
// Initialize the baseRate state variable
baseRate = INITIAL_BASE_RATE;
emit BaseRateUpdated(INITIAL_BASE_RATE);
}
function addNewCollaterals(
IERC20Metadata[] memory _tokens,
ITroveManager[] memory _troveManagers
) external override onlyOwner {
uint256 numTokens = _tokens.length;
uint256 numCollaterals = totalCollaterals;
require(
numTokens > 0 && numTokens == _troveManagers.length,
"Invalid input"
);
require(numCollaterals + numTokens <= 10, "Max collaterals");
// add new collaterals and trove managers
for (uint8 i; i < numTokens; i++) {
requireNotZeroAddress(address(_tokens[i]));
requireNotZeroAddress(address(_troveManagers[i]));
collateralTokens[numCollaterals+i] = _tokens[i];
troveManagers[numCollaterals+i] = _troveManagers[i];
emit NewCollateralAdded(address(_tokens[i]), address(_troveManagers[i]));
}
// update total Collaterals
totalCollaterals += numTokens;
}
// this function removes a branch from the collateralRegistry list
// and swaps the elements in order to push zero values at the end of the array
// it's meant to "clean up" space in the collaterals/troveManagers array
// can be executed only if the branch is in shutdown state
function removeCollateral(uint256 index) external override onlyOwner {
// remove collaterals and trove managers
require(index <= 9, "Invalid index");
require(
address(collateralTokens[index]) != address(0),
"Branch not initialised"
);
ITroveManager troveManager = ITroveManager(troveManagers[index]);
// revert if branch is not shutdown
require(troveManager.shutdownTime() != 0, "Branch is not shutdown");
emit CollateralRemoved(
address(collateralTokens[index]),
address(troveManagers[index])
);
// push the zero element at the end
uint256 swapIndex = totalCollaterals - 1;
if (swapIndex > index) {
// swap
collateralTokens[index] = collateralTokens[swapIndex];
troveManagers[index] = ITroveManager(troveManagers[swapIndex]);
collateralTokens[swapIndex] = IERC20Metadata(address(0));
troveManagers[swapIndex] = ITroveManager(address(0));
} else {
// no swap. deleted index is the last in the array
collateralTokens[index] = IERC20Metadata(address(0));
troveManagers[index] = ITroveManager(address(0));
}
totalCollaterals--;
}
// --- Redemption functions ---
function redeemCollateral(
uint256 _boldAmount,
uint256 _maxIterationsPerCollateral,
uint256 _maxFeePercentage
) external {
_requireValidMaxFeePercentage(_maxFeePercentage);
_requireAmountGreaterThanZero(_boldAmount);
RedemptionTotals memory totals;
totals.numCollaterals = totalCollaterals;
uint256[] memory unbackedPortions = new uint256[](
totals.numCollaterals
);
uint256[] memory prices = new uint256[](totals.numCollaterals);
totals.boldSupplyAtStart = boldToken.totalSupply();
// Decay the baseRate due to time passed, and then increase it according to the size of this redemption.
// Use the saved total Bold supply value, from before it was reduced by the redemption.
// We only compute it here, and update it at the end,
// because the final redeemed amount may be less than the requested amount
// Redeemers should take this into account in order to request the optimal amount to not overpay
uint256 redemptionRate = _calcRedemptionRate(
_getUpdatedBaseRateFromRedemption(
_boldAmount,
totals.boldSupplyAtStart
)
);
require(
redemptionRate <= _maxFeePercentage,
"CR: Fee exceeded provided maximum"
);
// Implicit by the above and the _requireValidMaxFeePercentage checks
//require(newBaseRate < DECIMAL_PRECISION, "CR: Fee would eat up all collateral");
// Gather and accumulate unbacked portions
for (uint256 index = 0; index < totals.numCollaterals; index++) {
ITroveManager troveManager = getTroveManager(index);
(
uint256 unbackedPortion,
uint256 price,
bool redeemable
) = troveManager.getUnbackedPortionPriceAndRedeemability();
prices[index] = price;
if (redeemable && troveManager.isWhitelisted(msg.sender)) {
totals.unbacked += unbackedPortion;
unbackedPortions[index] = unbackedPortion;
}
}
// There’s an unlikely scenario where all the normally redeemable branches (i.e. having TCR > SCR) have 0 unbacked
// In that case, we redeem proportinally to branch size
if (totals.unbacked == 0) {
unbackedPortions = new uint256[](totals.numCollaterals);
for (uint256 index = 0; index < totals.numCollaterals; index++) {
ITroveManager troveManager = getTroveManager(index);
(, , bool redeemable) = troveManager
.getUnbackedPortionPriceAndRedeemability();
if (redeemable && troveManager.isWhitelisted(msg.sender)) {
uint256 unbackedPortion = troveManager
.getEntireBranchDebt();
totals.unbacked += unbackedPortion;
unbackedPortions[index] = unbackedPortion;
}
}
}
// Compute redemption amount for each collateral and redeem against the corresponding TroveManager
for (uint256 index = 0; index < totals.numCollaterals; index++) {
//uint256 unbackedPortion = unbackedPortions[index];
if (unbackedPortions[index] > 0) {
uint256 redeemAmount = (_boldAmount * unbackedPortions[index]) /
totals.unbacked;
if (redeemAmount > 0) {
ITroveManager troveManager = getTroveManager(index);
uint256 redeemedAmount = troveManager.redeemCollateral(
msg.sender,
redeemAmount,
prices[index],
redemptionRate,
_maxIterationsPerCollateral
);
totals.redeemedAmount += redeemedAmount;
}
}
}
_updateBaseRateAndGetRedemptionRate(
totals.redeemedAmount,
totals.boldSupplyAtStart
);
// Burn the total Bold that is cancelled with debt
if (totals.redeemedAmount > 0) {
boldToken.burn(msg.sender, totals.redeemedAmount);
}
}
// --- Internal fee functions ---
// Update the last fee operation time only if time passed >= decay interval. This prevents base rate griefing.
function _updateLastFeeOpTime() internal {
uint256 minutesPassed = _minutesPassedSinceLastFeeOp();
if (minutesPassed > 0) {
lastFeeOperationTime += ONE_MINUTE * minutesPassed;
emit LastFeeOpTimeUpdated(lastFeeOperationTime);
}
}
function _minutesPassedSinceLastFeeOp() internal view returns (uint256) {
return (block.timestamp - lastFeeOperationTime) / ONE_MINUTE;
}
// Updates the `baseRate` state with math from `_getUpdatedBaseRateFromRedemption`
function _updateBaseRateAndGetRedemptionRate(
uint256 _boldAmount,
uint256 _totalBoldSupplyAtStart
) internal {
uint256 newBaseRate = _getUpdatedBaseRateFromRedemption(
_boldAmount,
_totalBoldSupplyAtStart
);
//assert(newBaseRate <= DECIMAL_PRECISION); // This is already enforced in `_getUpdatedBaseRateFromRedemption`
// Update the baseRate state variable
baseRate = newBaseRate;
emit BaseRateUpdated(newBaseRate);
_updateLastFeeOpTime();
}
/*
* This function calculates the new baseRate in the following way:
* 1) decays the baseRate based on time passed since last redemption or Bold borrowing operation.
* then,
* 2) increases the baseRate based on the amount redeemed, as a proportion of total supply
*/
function _getUpdatedBaseRateFromRedemption(
uint256 _redeemAmount,
uint256 _totalBoldSupply
) internal view returns (uint256) {
// decay the base rate
uint256 decayedBaseRate = _calcDecayedBaseRate();
// get the fraction of total supply that was redeemed
uint256 redeemedBoldFraction = (_redeemAmount * DECIMAL_PRECISION) /
_totalBoldSupply;
uint256 newBaseRate = decayedBaseRate +
redeemedBoldFraction /
REDEMPTION_BETA;
newBaseRate = LiquityMath._min(newBaseRate, DECIMAL_PRECISION); // cap baseRate at a maximum of 100%
return newBaseRate;
}
function _calcDecayedBaseRate() internal view returns (uint256) {
uint256 minutesPassed = _minutesPassedSinceLastFeeOp();
uint256 decayFactor = LiquityMath._decPow(
REDEMPTION_MINUTE_DECAY_FACTOR,
minutesPassed
);
return (baseRate * decayFactor) / DECIMAL_PRECISION;
}
function _calcRedemptionRate(
uint256 _baseRate
) internal pure returns (uint256) {
return
LiquityMath._min(
REDEMPTION_FEE_FLOOR + _baseRate,
DECIMAL_PRECISION // cap at a maximum of 100%
);
}
function _calcRedemptionFee(
uint256 _redemptionRate,
uint256 _amount
) internal pure returns (uint256) {
uint256 redemptionFee = (_redemptionRate * _amount) / DECIMAL_PRECISION;
return redemptionFee;
}
// external redemption rate/fee getters
function getRedemptionRate() external view override returns (uint256) {
return _calcRedemptionRate(baseRate);
}
function getRedemptionRateWithDecay()
public
view
override
returns (uint256)
{
return _calcRedemptionRate(_calcDecayedBaseRate());
}
function getRedemptionRateForRedeemedAmount(
uint256 _redeemAmount
) external view returns (uint256) {
uint256 totalBoldSupply = boldToken.totalSupply();
uint256 newBaseRate = _getUpdatedBaseRateFromRedemption(
_redeemAmount,
totalBoldSupply
);
return _calcRedemptionRate(newBaseRate);
}
function getRedemptionFeeWithDecay(
uint256 _ETHDrawn
) external view override returns (uint256) {
return _calcRedemptionFee(getRedemptionRateWithDecay(), _ETHDrawn);
}
function getEffectiveRedemptionFeeInBold(
uint256 _redeemAmount
) external view override returns (uint256) {
uint256 totalBoldSupply = boldToken.totalSupply();
uint256 newBaseRate = _getUpdatedBaseRateFromRedemption(
_redeemAmount,
totalBoldSupply
);
return
_calcRedemptionFee(_calcRedemptionRate(newBaseRate), _redeemAmount);
}
// getters
function getToken(uint256 _index) external view returns (IERC20Metadata) {
require(_index < 10, "Invalid index");
return collateralTokens[_index];
}
function getTroveManager(
uint256 _index
) public view returns (ITroveManager) {
require(_index < 10, "Invalid index");
return troveManagers[_index];
}
// require functions
function _requireValidMaxFeePercentage(
uint256 _maxFeePercentage
) internal pure {
require(
_maxFeePercentage >= REDEMPTION_FEE_FLOOR &&
_maxFeePercentage <= DECIMAL_PRECISION,
"Max fee percentage must be between 0.5% and 100%"
);
}
function _requireAmountGreaterThanZero(uint256 _amount) internal pure {
require(
_amount > 0,
"CollateralRegistry: Amount must be greater than zero"
);
}
function requireNotZeroAddress(address _address) internal pure {
if (_address == address(0)) revert ZeroAddress();
}
}// 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.01 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 = 0.01 ether; // Max coll gas compensation capped at 2 ETH
// Minimum amount of net Bold debt a trove must have
uint256 constant MIN_DEBT = 2000e18;
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: GPL-3.0
// Docgen-SOLC: 0.8.25
pragma solidity 0.8.24;
import "../Interfaces/IOwned.sol";
// https://docs.synthetix.io/contracts/source/contracts/owned
contract Owned is IOwned {
address public override owner;
address public override nominatedOwner;
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
constructor(address _owner) {
require(_owner != address(0), "Owned/owner-zero");
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external virtual override onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external virtual override {
require(msg.sender == nominatedOwner, "Owned/not-nominated");
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner() {
_onlyOwner();
_;
}
function _onlyOwner() private view {
require(msg.sender == owner, "Owned/not-owner");
}
}// 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;
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 IBoldToken","name":"_boldToken","type":"address"},{"internalType":"contract IERC20Metadata[]","name":"_tokens","type":"address[]"},{"internalType":"contract ITroveManager[]","name":"_troveManagers","type":"address[]"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_baseRate","type":"uint256"}],"name":"BaseRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"address","name":"troveManager","type":"address"}],"name":"CollateralRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_lastFeeOpTime","type":"uint256"}],"name":"LastFeeOpTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"address","name":"troveManager","type":"address"}],"name":"NewCollateralAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"whitelist","type":"address"}],"name":"WhitelistSet","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata[]","name":"_tokens","type":"address[]"},{"internalType":"contract ITroveManager[]","name":"_troveManagers","type":"address[]"}],"name":"addNewCollaterals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"baseRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boldToken","outputs":[{"internalType":"contract IBoldToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_redeemAmount","type":"uint256"}],"name":"getEffectiveRedemptionFeeInBold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ETHDrawn","type":"uint256"}],"name":"getRedemptionFeeWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedemptionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_redeemAmount","type":"uint256"}],"name":"getRedemptionRateForRedeemedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedemptionRateWithDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getTroveManager","outputs":[{"internalType":"contract ITroveManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastFeeOperationTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_boldAmount","type":"uint256"},{"internalType":"uint256","name":"_maxIterationsPerCollateral","type":"uint256"},{"internalType":"uint256","name":"_maxFeePercentage","type":"uint256"}],"name":"redeemCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"removeCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalCollaterals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a06040524260185534801562000014575f80fd5b5060405162001f9a38038062001f9a8339810160408190526200003791620003ff565b806001600160a01b038116620000875760405162461bcd60e51b815260206004820152601060248201526f4f776e65642f6f776e65722d7a65726f60801b60448201526064015b60405180910390fd5b5f80546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a15082518015801590620000f15750600a8111155b6200013f5760405162461bcd60e51b815260206004820152601760248201527f436f6c6c61746572616c206c69737420696e76616c696400000000000000000060448201526064016200007e565b60028190556001600160a01b0385166080525f5b818160ff16101562000275576200018f858260ff16815181106200017b576200017b620004f3565b6020026020010151620002c260201b60201c565b620001ab848260ff16815181106200017b576200017b620004f3565b848160ff1681518110620001c357620001c3620004f3565b602002602001015160038260ff16600a8110620001e457620001e4620004f3565b015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550838160ff1681518110620002205762000220620004f3565b6020026020010151600d8260ff16600a8110620002415762000241620004f3565b0180546001600160a01b0319166001600160a01b0392909216919091179055806200026c8162000507565b91505062000153565b50670de0b6b3a764000060178190556040519081527fc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600c9060200160405180910390a1505050505062000532565b6001600160a01b038116620002ea5760405163d92e233d60e01b815260040160405180910390fd5b50565b6001600160a01b0381168114620002ea575f80fd5b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171562000341576200034162000302565b604052919050565b5f6001600160401b0382111562000364576200036462000302565b5060051b60200190565b5f82601f8301126200037e575f80fd5b8151602062000397620003918362000349565b62000316565b8083825260208201915060208460051b870101935086841115620003b9575f80fd5b602086015b84811015620003e2578051620003d481620002ed565b8352918301918301620003be565b509695505050505050565b8051620003fa81620002ed565b919050565b5f805f806080858703121562000413575f80fd5b84516200042081620002ed565b602086810151919550906001600160401b03808211156200043f575f80fd5b818801915088601f83011262000453575f80fd5b815162000464620003918262000349565b81815260059190911b8301840190848101908b83111562000483575f80fd5b938501935b82851015620004ae5784516200049e81620002ed565b8252938501939085019062000488565b60408b01519098509450505080831115620004c7575f80fd5b5050620004d7878288016200036e565b925050620004e860608601620003ed565b905092959194509250565b634e487b7160e01b5f52603260045260245ffd5b5f60ff821660ff81036200052957634e487b7160e01b5f52601160045260245ffd5b60010192915050565b608051611a33620005675f395f8181610179015281816106700152818161089c01528181610e6a0152610ed70152611a335ff3fe608060405234801561000f575f80fd5b50600436106100e4575f3560e01c80630bc17feb146100e85780631627540c146101115780631f68f20a146101265780632b11551a1461013d57806330504b6f146101455780633237c1581461014e57806353a47bb714610161578063630afce51461017457806363f1134e1461019b57806379ba5097146101ae5780638da5cb5b146101b6578063ab6d53bd146101c8578063c3bfd842146101db578063c52861f2146101ee578063d380a37c146101f6578063d5b35635146101ff578063e4b50cb814610212578063e6845f7314610225575b5f80fd5b6100fb6100f636600461165b565b610238565b6040516101089190611672565b60405180910390f35b61012461011f36600461169a565b610286565b005b61012f60175481565b604051908152602001610108565b61012f6102e4565b61012f60025481565b61012461015c36600461165b565b6102f5565b6001546100fb906001600160a01b031681565b6100fb7f000000000000000000000000000000000000000000000000000000000000000081565b61012f6101a936600461165b565b61066c565b61012461070e565b5f546100fb906001600160a01b031681565b6101246101d63660046116b5565b6107ce565b61012f6101e936600461165b565b610ed3565b61012f610f76565b61012f60185481565b61012f61020d36600461165b565b610f82565b6100fb61022036600461165b565b610f9a565b6101246102333660046117b9565b610fce565b5f600a82106102625760405162461bcd60e51b815260040161025990611874565b60405180910390fd5b600d82600a81106102755761027561189b565b01546001600160a01b031692915050565b61028e611220565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906102d9908390611672565b60405180910390a150565b5f6102f060175461126d565b905090565b6102fd611220565b600981111561031e5760405162461bcd60e51b815260040161025990611874565b5f600382600a81106103325761033261189b565b01546001600160a01b0316036103835760405162461bcd60e51b8152602060048201526016602482015275109c985b98da081b9bdd081a5b9a5d1a585b1a5cd95960521b6044820152606401610259565b5f600d82600a81106103975761039761189b565b015f9054906101000a90046001600160a01b03169050806001600160a01b031663585690816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061040d91906118af565b5f036104545760405162461bcd60e51b8152602060048201526016602482015275213930b731b41034b9903737ba1039b43aba3237bbb760511b6044820152606401610259565b7ff30858681fdd836ac4f2fe8faf8ebad8a26300210abba0a1998218472772b523600383600a81106104885761048861189b565b01546001600160a01b0316600d84600a81106104a6576104a661189b565b01546040516104bf92916001600160a01b0316906118c6565b60405180910390a15f60016002546104d791906118f4565b9050828111156105ec57600381600a81106104f4576104f461189b565b01546001600160a01b0316600384600a81106105125761051261189b565b0180546001600160a01b0319166001600160a01b0392909216919091179055600d81600a81106105445761054461189b565b01546001600160a01b0316600d84600a81106105625761056261189b565b0180546001600160a01b0319166001600160a01b03929092169190911790555f600382600a81106105955761059561189b565b0180546001600160a01b0319166001600160a01b03929092169190911790555f600d82600a81106105c8576105c861189b565b0180546001600160a01b0319166001600160a01b0392909216919091179055610653565b5f600384600a81106106005761060061189b565b0180546001600160a01b0319166001600160a01b03929092169190911790555f600d84600a81106106335761063361189b565b0180546001600160a01b0319166001600160a01b03929092169190911790555b60028054905f61066283611907565b9190505550505050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ca573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106ee91906118af565b90505f6106fb84836112a9565b90506107068161126d565b949350505050565b6001546001600160a01b0316331461075e5760405162461bcd60e51b815260206004820152601360248201527213dddb99590bdb9bdd0b5b9bdb5a5b985d1959606a1b6044820152606401610259565b5f546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926107a0926001600160a01b03918216929116906118c6565b60405180910390a1600180545f80546001600160a01b03199081166001600160a01b03841617909155169055565b6107d781611309565b6107e0836113a7565b61080760405180608001604052805f81526020015f81526020015f81526020015f81525090565b6002548082525f906001600160401b03811115610826576108266116de565b60405190808252806020026020018201604052801561084f578160200160208202803683370190505b5090505f825f01516001600160401b0381111561086e5761086e6116de565b604051908082528060200260200182016040528015610897578160200160208202803683370190505b5090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061091a91906118af565b602084018190525f90610937906109329089906112a9565b61126d565b9050848111156109935760405162461bcd60e51b815260206004820152602160248201527f43523a204665652065786365656465642070726f7669646564206d6178696d756044820152606d60f81b6064820152608401610259565b5f5b8451811015610af3575f6109a882610238565b90505f805f836001600160a01b0316634ea15f376040518163ffffffff1660e01b81526004016060604051808303815f875af11580156109ea573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0e9190611930565b92509250925081878681518110610a2757610a2761189b565b602002602001018181525050808015610aa65750604051633af32abf60e01b81526001600160a01b03851690633af32abf90610a67903390600401611672565b602060405180830381865afa158015610a82573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa69190611962565b15610ae3578289604001818151610abd919061197b565b90525087518390899087908110610ad657610ad661189b565b6020026020010181815250505b5050600190920191506109959050565b5083604001515f03610ce15783516001600160401b03811115610b1857610b186116de565b604051908082528060200260200182016040528015610b41578160200160208202803683370190505b5092505f5b8451811015610cdf575f610b5982610238565b90505f816001600160a01b0316634ea15f376040518163ffffffff1660e01b81526004016060604051808303815f875af1158015610b99573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bbd9190611930565b92505050808015610c345750604051633af32abf60e01b81526001600160a01b03831690633af32abf90610bf5903390600401611672565b602060405180830381865afa158015610c10573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c349190611962565b15610cd5575f826001600160a01b031663105b403b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c9a91906118af565b90508088604001818151610cae919061197b565b90525086518190889086908110610cc757610cc761189b565b602002602001018181525050505b5050600101610b46565b505b5f5b8451811015610e2b575f848281518110610cff57610cff61189b565b60200260200101511115610e23575f8560400151858381518110610d2557610d2561189b565b60200260200101518a610d38919061198e565b610d4291906119b9565b90508015610e21575f610d5483610238565b90505f816001600160a01b031663f8a239e83385898881518110610d7a57610d7a61189b565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0390931660048401526024830191909152604482015260648101889052608481018d905260a4016020604051808303815f875af1158015610de3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e0791906118af565b90508088606001818151610e1b919061197b565b90525050505b505b600101610ce3565b50610e3e84606001518560200151611413565b606084015115610eca576060840151604051632770a7eb60e21b815233600482015260248101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac906044015f604051808303815f87803b158015610eb3575f80fd5b505af1158015610ec5573d5f803e3d5ffd5b505050505b50505050505050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5591906118af565b90505f610f6284836112a9565b9050610706610f708261126d565b85611466565b5f6102f0610932611485565b5f610f94610f8e610f76565b83611466565b92915050565b5f600a8210610fbb5760405162461bcd60e51b815260040161025990611874565b600382600a81106102755761027561189b565b610fd6611220565b81516002548115801590610fea5750825182145b6110265760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081a5b9c1d5d609a1b6044820152606401610259565b600a611032838361197b565b11156110725760405162461bcd60e51b815260206004820152600f60248201526e4d617820636f6c6c61746572616c7360881b6044820152606401610259565b5f5b828160ff161015611203576110a4858260ff16815181106110975761109761189b565b60200260200101516114ce565b6110bc848260ff16815181106110975761109761189b565b848160ff16815181106110d1576110d161189b565b602002602001015160038260ff16846110ea919061197b565b600a81106110fa576110fa61189b565b015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550838160ff16815181106111335761113361189b565b6020026020010151600d8260ff168461114c919061197b565b600a811061115c5761115c61189b565b015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055507fe3ff17581c53bf246f14c95373f2d316943397252dfe0c882513e68375b6e021858260ff16815181106111b6576111b661189b565b6020026020010151858360ff16815181106111d3576111d361189b565b60200260200101516040516111e99291906118c6565b60405180910390a1806111fb816119cc565b915050611074565b508160025f828254611215919061197b565b909155505050505050565b5f546001600160a01b0316331461126b5760405162461bcd60e51b815260206004820152600f60248201526e27bbb732b217b737ba16b7bbb732b960891b6044820152606401610259565b565b5f610f948260026112876064670de0b6b3a76400006119b9565b61129191906119b9565b61129b919061197b565b670de0b6b3a76400006114f5565b5f806112b3611485565b90505f836112c9670de0b6b3a76400008761198e565b6112d391906119b9565b90505f6112e16001836119b9565b6112eb908461197b565b90506112ff81670de0b6b3a76400006114f5565b9695505050505050565b600261131e6064670de0b6b3a76400006119b9565b61132891906119b9565b811015801561133f5750670de0b6b3a76400008111155b6113a45760405162461bcd60e51b815260206004820152603060248201527f4d6178206665652070657263656e74616765206d75737420626520626574776560448201526f656e20302e352520616e64203130302560801b6064820152608401610259565b50565b5f81116113a45760405162461bcd60e51b815260206004820152603460248201527f436f6c6c61746572616c52656769737472793a20416d6f756e74206d7573742060448201527362652067726561746572207468616e207a65726f60601b6064820152608401610259565b5f61141e83836112a9565b60178190556040518181529091507fc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600c9060200160405180910390a161146161150c565b505050565b5f80670de0b6b3a764000061147b848661198e565b61070691906119b9565b5f8061148f611570565b90505f6114a4670dd9e13cc602b4008361158b565b9050670de0b6b3a7640000816017546114bd919061198e565b6114c791906119b9565b9250505090565b6001600160a01b0381166113a45760405163d92e233d60e01b815260040160405180910390fd5b5f8183106115035781611505565b825b9392505050565b5f611515611570565b905080156113a45761152881603c61198e565b60185f828254611538919061197b565b90915550506018546040519081527f860f8d2f0c74dd487e89e2883e3b25b8159ce1e1b3433a291cba7b82c508f3bc906020016102d9565b5f603c6018544261158191906118f4565b6102f091906119b9565b5f631f5405008211156115a057631f54050091505b815f036115b65750670de0b6b3a7640000610f94565b670de0b6b3a764000083835b6001811115611629576115d66002826119ea565b5f036115fa576115e6828361162f565b91506115f36002826119b9565b90506115c2565b611604828461162f565b9250611610828361162f565b9150600261161f6001836118f4565b6115f391906119b9565b6112ff82845b5f8061163b838561198e565b9050670de0b6b3a76400006116516002826119b9565b61147b908361197b565b5f6020828403121561166b575f80fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b03811681146113a4575f80fd5b5f602082840312156116aa575f80fd5b813561150581611686565b5f805f606084860312156116c7575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561171a5761171a6116de565b604052919050565b5f6001600160401b0382111561173a5761173a6116de565b5060051b60200190565b5f82601f830112611753575f80fd5b8135602061176861176383611722565b6116f2565b8083825260208201915060208460051b870101935086841115611789575f80fd5b602086015b848110156117ae5780356117a181611686565b835291830191830161178e565b509695505050505050565b5f80604083850312156117ca575f80fd5b82356001600160401b03808211156117e0575f80fd5b818501915085601f8301126117f3575f80fd5b8135602061180361176383611722565b82815260059290921b84018101918181019089841115611821575f80fd5b948201945b8386101561184857853561183981611686565b82529482019490820190611826565b9650508601359250508082111561185d575f80fd5b5061186a85828601611744565b9150509250929050565b6020808252600d908201526c092dcecc2d8d2c840d2dcc8caf609b1b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156118bf575f80fd5b5051919050565b6001600160a01b0392831681529116602082015260400190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610f9457610f946118e0565b5f81611915576119156118e0565b505f190190565b8051801515811461192b575f80fd5b919050565b5f805f60608486031215611942575f80fd5b83519250602084015191506119596040850161191c565b90509250925092565b5f60208284031215611972575f80fd5b6115058261191c565b80820180821115610f9457610f946118e0565b8082028115828204841417610f9457610f946118e0565b634e487b7160e01b5f52601260045260245ffd5b5f826119c7576119c76119a5565b500490565b5f60ff821660ff81036119e1576119e16118e0565b60010192915050565b5f826119f8576119f86119a5565b50069056fea264697066735822122059b2b172d0f73450b37c03f8b5991d303b3f6f1819975d34e59367c5c8a2e28164736f6c63430008180033000000000000000000000000d4622e18029690dcc9fe60dd48ad1555e295745c000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000919d5a6f2cbc0731380c26b4ac4f6183dd3a40c800000000000000000000000000000000000000000000000000000000000000010000000000000000000000005ff46c6b2b2dc0cd858e48f2791c247f603ed75f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000386218f6c9d39fe8527bab17a151c3fd556f6386
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100e4575f3560e01c80630bc17feb146100e85780631627540c146101115780631f68f20a146101265780632b11551a1461013d57806330504b6f146101455780633237c1581461014e57806353a47bb714610161578063630afce51461017457806363f1134e1461019b57806379ba5097146101ae5780638da5cb5b146101b6578063ab6d53bd146101c8578063c3bfd842146101db578063c52861f2146101ee578063d380a37c146101f6578063d5b35635146101ff578063e4b50cb814610212578063e6845f7314610225575b5f80fd5b6100fb6100f636600461165b565b610238565b6040516101089190611672565b60405180910390f35b61012461011f36600461169a565b610286565b005b61012f60175481565b604051908152602001610108565b61012f6102e4565b61012f60025481565b61012461015c36600461165b565b6102f5565b6001546100fb906001600160a01b031681565b6100fb7f000000000000000000000000d4622e18029690dcc9fe60dd48ad1555e295745c81565b61012f6101a936600461165b565b61066c565b61012461070e565b5f546100fb906001600160a01b031681565b6101246101d63660046116b5565b6107ce565b61012f6101e936600461165b565b610ed3565b61012f610f76565b61012f60185481565b61012f61020d36600461165b565b610f82565b6100fb61022036600461165b565b610f9a565b6101246102333660046117b9565b610fce565b5f600a82106102625760405162461bcd60e51b815260040161025990611874565b60405180910390fd5b600d82600a81106102755761027561189b565b01546001600160a01b031692915050565b61028e611220565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906102d9908390611672565b60405180910390a150565b5f6102f060175461126d565b905090565b6102fd611220565b600981111561031e5760405162461bcd60e51b815260040161025990611874565b5f600382600a81106103325761033261189b565b01546001600160a01b0316036103835760405162461bcd60e51b8152602060048201526016602482015275109c985b98da081b9bdd081a5b9a5d1a585b1a5cd95960521b6044820152606401610259565b5f600d82600a81106103975761039761189b565b015f9054906101000a90046001600160a01b03169050806001600160a01b031663585690816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061040d91906118af565b5f036104545760405162461bcd60e51b8152602060048201526016602482015275213930b731b41034b9903737ba1039b43aba3237bbb760511b6044820152606401610259565b7ff30858681fdd836ac4f2fe8faf8ebad8a26300210abba0a1998218472772b523600383600a81106104885761048861189b565b01546001600160a01b0316600d84600a81106104a6576104a661189b565b01546040516104bf92916001600160a01b0316906118c6565b60405180910390a15f60016002546104d791906118f4565b9050828111156105ec57600381600a81106104f4576104f461189b565b01546001600160a01b0316600384600a81106105125761051261189b565b0180546001600160a01b0319166001600160a01b0392909216919091179055600d81600a81106105445761054461189b565b01546001600160a01b0316600d84600a81106105625761056261189b565b0180546001600160a01b0319166001600160a01b03929092169190911790555f600382600a81106105955761059561189b565b0180546001600160a01b0319166001600160a01b03929092169190911790555f600d82600a81106105c8576105c861189b565b0180546001600160a01b0319166001600160a01b0392909216919091179055610653565b5f600384600a81106106005761060061189b565b0180546001600160a01b0319166001600160a01b03929092169190911790555f600d84600a81106106335761063361189b565b0180546001600160a01b0319166001600160a01b03929092169190911790555b60028054905f61066283611907565b9190505550505050565b5f807f000000000000000000000000d4622e18029690dcc9fe60dd48ad1555e295745c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ca573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106ee91906118af565b90505f6106fb84836112a9565b90506107068161126d565b949350505050565b6001546001600160a01b0316331461075e5760405162461bcd60e51b815260206004820152601360248201527213dddb99590bdb9bdd0b5b9bdb5a5b985d1959606a1b6044820152606401610259565b5f546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926107a0926001600160a01b03918216929116906118c6565b60405180910390a1600180545f80546001600160a01b03199081166001600160a01b03841617909155169055565b6107d781611309565b6107e0836113a7565b61080760405180608001604052805f81526020015f81526020015f81526020015f81525090565b6002548082525f906001600160401b03811115610826576108266116de565b60405190808252806020026020018201604052801561084f578160200160208202803683370190505b5090505f825f01516001600160401b0381111561086e5761086e6116de565b604051908082528060200260200182016040528015610897578160200160208202803683370190505b5090507f000000000000000000000000d4622e18029690dcc9fe60dd48ad1555e295745c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061091a91906118af565b602084018190525f90610937906109329089906112a9565b61126d565b9050848111156109935760405162461bcd60e51b815260206004820152602160248201527f43523a204665652065786365656465642070726f7669646564206d6178696d756044820152606d60f81b6064820152608401610259565b5f5b8451811015610af3575f6109a882610238565b90505f805f836001600160a01b0316634ea15f376040518163ffffffff1660e01b81526004016060604051808303815f875af11580156109ea573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0e9190611930565b92509250925081878681518110610a2757610a2761189b565b602002602001018181525050808015610aa65750604051633af32abf60e01b81526001600160a01b03851690633af32abf90610a67903390600401611672565b602060405180830381865afa158015610a82573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa69190611962565b15610ae3578289604001818151610abd919061197b565b90525087518390899087908110610ad657610ad661189b565b6020026020010181815250505b5050600190920191506109959050565b5083604001515f03610ce15783516001600160401b03811115610b1857610b186116de565b604051908082528060200260200182016040528015610b41578160200160208202803683370190505b5092505f5b8451811015610cdf575f610b5982610238565b90505f816001600160a01b0316634ea15f376040518163ffffffff1660e01b81526004016060604051808303815f875af1158015610b99573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bbd9190611930565b92505050808015610c345750604051633af32abf60e01b81526001600160a01b03831690633af32abf90610bf5903390600401611672565b602060405180830381865afa158015610c10573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c349190611962565b15610cd5575f826001600160a01b031663105b403b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c9a91906118af565b90508088604001818151610cae919061197b565b90525086518190889086908110610cc757610cc761189b565b602002602001018181525050505b5050600101610b46565b505b5f5b8451811015610e2b575f848281518110610cff57610cff61189b565b60200260200101511115610e23575f8560400151858381518110610d2557610d2561189b565b60200260200101518a610d38919061198e565b610d4291906119b9565b90508015610e21575f610d5483610238565b90505f816001600160a01b031663f8a239e83385898881518110610d7a57610d7a61189b565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0390931660048401526024830191909152604482015260648101889052608481018d905260a4016020604051808303815f875af1158015610de3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e0791906118af565b90508088606001818151610e1b919061197b565b90525050505b505b600101610ce3565b50610e3e84606001518560200151611413565b606084015115610eca576060840151604051632770a7eb60e21b815233600482015260248101919091527f000000000000000000000000d4622e18029690dcc9fe60dd48ad1555e295745c6001600160a01b031690639dc29fac906044015f604051808303815f87803b158015610eb3575f80fd5b505af1158015610ec5573d5f803e3d5ffd5b505050505b50505050505050565b5f807f000000000000000000000000d4622e18029690dcc9fe60dd48ad1555e295745c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5591906118af565b90505f610f6284836112a9565b9050610706610f708261126d565b85611466565b5f6102f0610932611485565b5f610f94610f8e610f76565b83611466565b92915050565b5f600a8210610fbb5760405162461bcd60e51b815260040161025990611874565b600382600a81106102755761027561189b565b610fd6611220565b81516002548115801590610fea5750825182145b6110265760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081a5b9c1d5d609a1b6044820152606401610259565b600a611032838361197b565b11156110725760405162461bcd60e51b815260206004820152600f60248201526e4d617820636f6c6c61746572616c7360881b6044820152606401610259565b5f5b828160ff161015611203576110a4858260ff16815181106110975761109761189b565b60200260200101516114ce565b6110bc848260ff16815181106110975761109761189b565b848160ff16815181106110d1576110d161189b565b602002602001015160038260ff16846110ea919061197b565b600a81106110fa576110fa61189b565b015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550838160ff16815181106111335761113361189b565b6020026020010151600d8260ff168461114c919061197b565b600a811061115c5761115c61189b565b015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055507fe3ff17581c53bf246f14c95373f2d316943397252dfe0c882513e68375b6e021858260ff16815181106111b6576111b661189b565b6020026020010151858360ff16815181106111d3576111d361189b565b60200260200101516040516111e99291906118c6565b60405180910390a1806111fb816119cc565b915050611074565b508160025f828254611215919061197b565b909155505050505050565b5f546001600160a01b0316331461126b5760405162461bcd60e51b815260206004820152600f60248201526e27bbb732b217b737ba16b7bbb732b960891b6044820152606401610259565b565b5f610f948260026112876064670de0b6b3a76400006119b9565b61129191906119b9565b61129b919061197b565b670de0b6b3a76400006114f5565b5f806112b3611485565b90505f836112c9670de0b6b3a76400008761198e565b6112d391906119b9565b90505f6112e16001836119b9565b6112eb908461197b565b90506112ff81670de0b6b3a76400006114f5565b9695505050505050565b600261131e6064670de0b6b3a76400006119b9565b61132891906119b9565b811015801561133f5750670de0b6b3a76400008111155b6113a45760405162461bcd60e51b815260206004820152603060248201527f4d6178206665652070657263656e74616765206d75737420626520626574776560448201526f656e20302e352520616e64203130302560801b6064820152608401610259565b50565b5f81116113a45760405162461bcd60e51b815260206004820152603460248201527f436f6c6c61746572616c52656769737472793a20416d6f756e74206d7573742060448201527362652067726561746572207468616e207a65726f60601b6064820152608401610259565b5f61141e83836112a9565b60178190556040518181529091507fc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600c9060200160405180910390a161146161150c565b505050565b5f80670de0b6b3a764000061147b848661198e565b61070691906119b9565b5f8061148f611570565b90505f6114a4670dd9e13cc602b4008361158b565b9050670de0b6b3a7640000816017546114bd919061198e565b6114c791906119b9565b9250505090565b6001600160a01b0381166113a45760405163d92e233d60e01b815260040160405180910390fd5b5f8183106115035781611505565b825b9392505050565b5f611515611570565b905080156113a45761152881603c61198e565b60185f828254611538919061197b565b90915550506018546040519081527f860f8d2f0c74dd487e89e2883e3b25b8159ce1e1b3433a291cba7b82c508f3bc906020016102d9565b5f603c6018544261158191906118f4565b6102f091906119b9565b5f631f5405008211156115a057631f54050091505b815f036115b65750670de0b6b3a7640000610f94565b670de0b6b3a764000083835b6001811115611629576115d66002826119ea565b5f036115fa576115e6828361162f565b91506115f36002826119b9565b90506115c2565b611604828461162f565b9250611610828361162f565b9150600261161f6001836118f4565b6115f391906119b9565b6112ff82845b5f8061163b838561198e565b9050670de0b6b3a76400006116516002826119b9565b61147b908361197b565b5f6020828403121561166b575f80fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b03811681146113a4575f80fd5b5f602082840312156116aa575f80fd5b813561150581611686565b5f805f606084860312156116c7575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561171a5761171a6116de565b604052919050565b5f6001600160401b0382111561173a5761173a6116de565b5060051b60200190565b5f82601f830112611753575f80fd5b8135602061176861176383611722565b6116f2565b8083825260208201915060208460051b870101935086841115611789575f80fd5b602086015b848110156117ae5780356117a181611686565b835291830191830161178e565b509695505050505050565b5f80604083850312156117ca575f80fd5b82356001600160401b03808211156117e0575f80fd5b818501915085601f8301126117f3575f80fd5b8135602061180361176383611722565b82815260059290921b84018101918181019089841115611821575f80fd5b948201945b8386101561184857853561183981611686565b82529482019490820190611826565b9650508601359250508082111561185d575f80fd5b5061186a85828601611744565b9150509250929050565b6020808252600d908201526c092dcecc2d8d2c840d2dcc8caf609b1b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156118bf575f80fd5b5051919050565b6001600160a01b0392831681529116602082015260400190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610f9457610f946118e0565b5f81611915576119156118e0565b505f190190565b8051801515811461192b575f80fd5b919050565b5f805f60608486031215611942575f80fd5b83519250602084015191506119596040850161191c565b90509250925092565b5f60208284031215611972575f80fd5b6115058261191c565b80820180821115610f9457610f946118e0565b8082028115828204841417610f9457610f946118e0565b634e487b7160e01b5f52601260045260245ffd5b5f826119c7576119c76119a5565b500490565b5f60ff821660ff81036119e1576119e16118e0565b60010192915050565b5f826119f8576119f86119a5565b50069056fea264697066735822122059b2b172d0f73450b37c03f8b5991d303b3f6f1819975d34e59367c5c8a2e28164736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d4622e18029690dcc9fe60dd48ad1555e295745c000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000919d5a6f2cbc0731380c26b4ac4f6183dd3a40c800000000000000000000000000000000000000000000000000000000000000010000000000000000000000005ff46c6b2b2dc0cd858e48f2791c247f603ed75f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000386218f6c9d39fe8527bab17a151c3fd556f6386
-----Decoded View---------------
Arg [0] : _boldToken (address): 0xd4622E18029690dCc9Fe60dd48aD1555e295745c
Arg [1] : _tokens (address[]): 0x5ff46C6B2B2DC0CD858e48F2791C247F603ed75f
Arg [2] : _troveManagers (address[]): 0x386218f6C9D39FE8527BaB17A151C3Fd556f6386
Arg [3] : _owner (address): 0x919D5a6F2CBc0731380C26B4AC4f6183dD3A40C8
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000d4622e18029690dcc9fe60dd48ad1555e295745c
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [3] : 000000000000000000000000919d5a6f2cbc0731380c26b4ac4f6183dd3a40c8
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 0000000000000000000000005ff46c6b2b2dc0cd858e48f2791c247f603ed75f
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [7] : 000000000000000000000000386218f6c9d39fe8527bab17a151c3fd556f6386
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.