Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 105 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Redeem Collatera... | 23431191 | 53 days ago | IN | 0 ETH | 0.00126415 | ||||
| Redeem Collatera... | 23413986 | 56 days ago | IN | 0 ETH | 0.00125868 | ||||
| Redeem Collatera... | 23400190 | 58 days ago | IN | 0 ETH | 0.0012849 | ||||
| Redeem Collatera... | 23386516 | 60 days ago | IN | 0 ETH | 0.00135645 | ||||
| Redeem Collatera... | 23371916 | 62 days ago | IN | 0 ETH | 0.00131151 | ||||
| Redeem Collatera... | 23360158 | 63 days ago | IN | 0 ETH | 0.00127124 | ||||
| Redeem Collatera... | 23350375 | 65 days ago | IN | 0 ETH | 0.00166456 | ||||
| Redeem Collatera... | 23341372 | 66 days ago | IN | 0 ETH | 0.00175143 | ||||
| Redeem Collatera... | 23331156 | 67 days ago | IN | 0 ETH | 0.00160653 | ||||
| Redeem Collatera... | 23323332 | 69 days ago | IN | 0 ETH | 0.00160729 | ||||
| Redeem Collatera... | 23315824 | 70 days ago | IN | 0 ETH | 0.00161076 | ||||
| Redeem Collatera... | 23308486 | 71 days ago | IN | 0 ETH | 0.00162122 | ||||
| Redeem Collatera... | 23301339 | 72 days ago | IN | 0 ETH | 0.00166937 | ||||
| Redeem Collatera... | 23294107 | 73 days ago | IN | 0 ETH | 0.00161472 | ||||
| Redeem Collatera... | 23287142 | 74 days ago | IN | 0 ETH | 0.00166824 | ||||
| Redeem Collatera... | 23280205 | 75 days ago | IN | 0 ETH | 0.00166858 | ||||
| Redeem Collatera... | 23273178 | 76 days ago | IN | 0 ETH | 0.00164509 | ||||
| Redeem Collatera... | 23266575 | 76 days ago | IN | 0 ETH | 0.00162171 | ||||
| Redeem Collatera... | 23262008 | 77 days ago | IN | 0 ETH | 0.00165645 | ||||
| Redeem Collatera... | 23257402 | 78 days ago | IN | 0 ETH | 0.00162701 | ||||
| Redeem Collatera... | 23252917 | 78 days ago | IN | 0 ETH | 0.00161784 | ||||
| Redeem Collatera... | 23248585 | 79 days ago | IN | 0 ETH | 0.00177858 | ||||
| Redeem Collatera... | 23243804 | 80 days ago | IN | 0 ETH | 0.00171732 | ||||
| Redeem Collatera... | 23239280 | 80 days ago | IN | 0 ETH | 0.00169345 | ||||
| Redeem Collatera... | 23234977 | 81 days ago | IN | 0 ETH | 0.00189712 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
CollateralRegistry
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.24;
import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "./Interfaces/ITroveManager.sol";
import "./Interfaces/IBoldToken.sol";
import "./Dependencies/Constants.sol";
import "./Dependencies/LiquityMath.sol";
import "./Interfaces/ICollateralRegistry.sol";
contract CollateralRegistry is ICollateralRegistry {
// See: https://github.com/ethereum/solidity/issues/12587
uint256 public immutable totalCollaterals;
IERC20Metadata internal immutable token0;
IERC20Metadata internal immutable token1;
IERC20Metadata internal immutable token2;
IERC20Metadata internal immutable token3;
IERC20Metadata internal immutable token4;
IERC20Metadata internal immutable token5;
IERC20Metadata internal immutable token6;
IERC20Metadata internal immutable token7;
IERC20Metadata internal immutable token8;
IERC20Metadata internal immutable token9;
ITroveManager internal immutable troveManager0;
ITroveManager internal immutable troveManager1;
ITroveManager internal immutable troveManager2;
ITroveManager internal immutable troveManager3;
ITroveManager internal immutable troveManager4;
ITroveManager internal immutable troveManager5;
ITroveManager internal immutable troveManager6;
ITroveManager internal immutable troveManager7;
ITroveManager internal immutable troveManager8;
ITroveManager internal immutable troveManager9;
IBoldToken public immutable boldToken;
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);
constructor(IBoldToken _boldToken, IERC20Metadata[] memory _tokens, ITroveManager[] memory _troveManagers) {
uint256 numTokens = _tokens.length;
require(numTokens > 0, "Collateral list cannot be empty");
require(numTokens <= 10, "Collateral list too long");
totalCollaterals = numTokens;
boldToken = _boldToken;
token0 = _tokens[0];
token1 = numTokens > 1 ? _tokens[1] : IERC20Metadata(address(0));
token2 = numTokens > 2 ? _tokens[2] : IERC20Metadata(address(0));
token3 = numTokens > 3 ? _tokens[3] : IERC20Metadata(address(0));
token4 = numTokens > 4 ? _tokens[4] : IERC20Metadata(address(0));
token5 = numTokens > 5 ? _tokens[5] : IERC20Metadata(address(0));
token6 = numTokens > 6 ? _tokens[6] : IERC20Metadata(address(0));
token7 = numTokens > 7 ? _tokens[7] : IERC20Metadata(address(0));
token8 = numTokens > 8 ? _tokens[8] : IERC20Metadata(address(0));
token9 = numTokens > 9 ? _tokens[9] : IERC20Metadata(address(0));
troveManager0 = _troveManagers[0];
troveManager1 = numTokens > 1 ? _troveManagers[1] : ITroveManager(address(0));
troveManager2 = numTokens > 2 ? _troveManagers[2] : ITroveManager(address(0));
troveManager3 = numTokens > 3 ? _troveManagers[3] : ITroveManager(address(0));
troveManager4 = numTokens > 4 ? _troveManagers[4] : ITroveManager(address(0));
troveManager5 = numTokens > 5 ? _troveManagers[5] : ITroveManager(address(0));
troveManager6 = numTokens > 6 ? _troveManagers[6] : ITroveManager(address(0));
troveManager7 = numTokens > 7 ? _troveManagers[7] : ITroveManager(address(0));
troveManager8 = numTokens > 8 ? _troveManagers[8] : ITroveManager(address(0));
troveManager9 = numTokens > 9 ? _troveManagers[9] : ITroveManager(address(0));
// Initialize the baseRate state variable
baseRate = INITIAL_BASE_RATE;
emit BaseRateUpdated(INITIAL_BASE_RATE);
}
struct RedemptionTotals {
uint256 numCollaterals;
uint256 boldSupplyAtStart;
uint256 unbacked;
uint256 redeemedAmount;
}
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) {
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) {
uint256 unbackedPortion = troveManager.getEntireSystemDebt();
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 timePassed = block.timestamp - lastFeeOperationTime;
if (timePassed >= ONE_MINUTE) {
lastFeeOperationTime = block.timestamp;
emit LastFeeOpTimeUpdated(block.timestamp);
}
}
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) {
if (_index == 0) return token0;
else if (_index == 1) return token1;
else if (_index == 2) return token2;
else if (_index == 3) return token3;
else if (_index == 4) return token4;
else if (_index == 5) return token5;
else if (_index == 6) return token6;
else if (_index == 7) return token7;
else if (_index == 8) return token8;
else if (_index == 9) return token9;
else revert("Invalid index");
}
function getTroveManager(uint256 _index) public view returns (ITroveManager) {
if (_index == 0) return troveManager0;
else if (_index == 1) return troveManager1;
else if (_index == 2) return troveManager2;
else if (_index == 3) return troveManager3;
else if (_index == 4) return troveManager4;
else if (_index == 5) return troveManager5;
else if (_index == 6) return troveManager6;
else if (_index == 7) return troveManager7;
else if (_index == 8) return troveManager8;
else if (_index == 9) return troveManager9;
else revert("Invalid 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");
}
}// 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;
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";
// 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 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: 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";
interface IBoldToken is IERC20Metadata, IERC20Permit, IERC5267 {
function setBranchAddresses(
address _troveManagerAddress,
address _stabilityPoolAddress,
address _borrowerOperationsAddress,
address _activePoolAddress
) external;
function setCollateralRegistry(address _collateralRegistryAddress) external;
function mint(address _account, uint256 _amount) external;
function burn(address _account, uint256 _amount) external;
function sendToPool(address _sender, address poolAddress, uint256 _amount) external;
function returnFromPool(address poolAddress, address user, uint256 _amount) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.24;
address constant ZERO_ADDRESS = address(0);
uint256 constant MAX_UINT256 = type(uint256).max;
uint256 constant DECIMAL_PRECISION = 1e18;
uint256 constant _100pct = DECIMAL_PRECISION;
uint256 constant _1pct = DECIMAL_PRECISION / 100;
// Amount of ETH to be locked in gas pool on opening troves
uint256 constant ETH_GAS_COMPENSATION = 0.0375 ether;
// Liquidation
uint256 constant MIN_LIQUIDATION_PENALTY_SP = 5e16; // 5%
uint256 constant MAX_LIQUIDATION_PENALTY_REDISTRIBUTION = 20e16; // 20%
// Fraction of collateral awarded to liquidator
uint256 constant COLL_GAS_COMPENSATION_DIVISOR = 200; // dividing by 200 yields 0.5%
uint256 constant COLL_GAS_COMPENSATION_CAP = 2 ether; // Max coll gas compensation capped at 2 ETH
// Minimum amount of net Bold debt a trove must have
uint256 constant MIN_DEBT = 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 SP_YIELD_SPLIT = 75 * _1pct; // 75%
// 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.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 "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "./IBoldToken.sol";
import "./ITroveManager.sol";
interface ICollateralRegistry {
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
// 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;
import "./IActivePool.sol";
import "./IDefaultPool.sol";
import "./IPriceFeed.sol";
interface ILiquityBase {
function activePool() external view returns (IActivePool);
function getEntireSystemDebt() external view returns (uint256);
function getEntireSystemColl() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "./ITroveManager.sol";
interface ITroveNFT is IERC721Metadata {
function mint(address _owner, uint256 _troveId) external;
function burn(uint256 _troveId) external;
}// 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 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;
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 epochToScaleToS(uint128 _epoch, uint128 _scale) external view returns (uint256);
function epochToScaleToB(uint128 _epoch, uint128 _scale) external view returns (uint256);
function P() external view returns (uint256);
function currentScale() external view returns (uint128);
function currentEpoch() external view returns (uint128);
}// 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.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
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 (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
// 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 "./IInterestRouter.sol";
import "./IBoldRewardsReceiver.sol";
import "../Types/TroveChange.sol";
interface IActivePool {
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 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.0;
interface IPriceFeed {
function fetchPrice() external returns (uint256, bool);
function fetchRedemptionPrice() external returns (uint256, bool);
function lastGoodPrice() external view returns (uint256);
function setAddresses(address _borrowerOperationsAddress) external;
}// SPDX-License-Identifier: MIT
// 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
pragma solidity ^0.8.0;
interface IAddRemoveManagers {
function setAddManager(uint256 _troveId, address _manager) external;
function setRemoveManager(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
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.0;
interface IBoldRewardsReceiver {
function triggerBoldRewards(uint256 _boldYield) 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
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.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
// 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
// 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);
}{
"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/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {}
}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[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_baseRate","type":"uint256"}],"name":"BaseRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_lastFeeOpTime","type":"uint256"}],"name":"LastFeeOpTimeUpdated","type":"event"},{"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":"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":[],"name":"totalCollaterals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6103406040524260015534801562000015575f80fd5b5060405162001b6638038062001b668339810160408190526200003891620006cf565b8151806200008d5760405162461bcd60e51b815260206004820152601f60248201527f436f6c6c61746572616c206c6973742063616e6e6f7420626520656d7074790060448201526064015b60405180910390fd5b600a811115620000e05760405162461bcd60e51b815260206004820152601860248201527f436f6c6c61746572616c206c69737420746f6f206c6f6e670000000000000000604482015260640162000084565b60808190526001600160a01b03841661032052825183905f90620001085762000108620007b0565b60209081029190910101516001600160a01b031660a052600181116200012f575f6200014e565b82600181518110620001455762000145620007b0565b60200260200101515b6001600160a01b031660c052600281116200016a575f62000189565b82600281518110620001805762000180620007b0565b60200260200101515b6001600160a01b031660e05260038111620001a5575f620001c4565b82600381518110620001bb57620001bb620007b0565b60200260200101515b6001600160a01b03166101005260048111620001e1575f62000200565b82600481518110620001f757620001f7620007b0565b60200260200101515b6001600160a01b031661012052600581116200021d575f6200023c565b82600581518110620002335762000233620007b0565b60200260200101515b6001600160a01b0316610140526006811162000259575f62000278565b826006815181106200026f576200026f620007b0565b60200260200101515b6001600160a01b0316610160526007811162000295575f620002b4565b82600781518110620002ab57620002ab620007b0565b60200260200101515b6001600160a01b03166101805260088111620002d1575f620002f0565b82600881518110620002e757620002e7620007b0565b60200260200101515b6001600160a01b03166101a052600981116200030d575f6200032c565b82600981518110620003235762000323620007b0565b60200260200101515b6001600160a01b03166101c052815182905f906200034e576200034e620007b0565b60209081029190910101516001600160a01b03166101e0526001811162000376575f62000395565b816001815181106200038c576200038c620007b0565b60200260200101515b6001600160a01b03166102005260028111620003b2575f620003d1565b81600281518110620003c857620003c8620007b0565b60200260200101515b6001600160a01b03166102205260038111620003ee575f6200040d565b81600381518110620004045762000404620007b0565b60200260200101515b6001600160a01b031661024052600481116200042a575f62000449565b81600481518110620004405762000440620007b0565b60200260200101515b6001600160a01b0316610260526005811162000466575f62000485565b816005815181106200047c576200047c620007b0565b60200260200101515b6001600160a01b03166102805260068111620004a2575f620004c1565b81600681518110620004b857620004b8620007b0565b60200260200101515b6001600160a01b03166102a05260078111620004de575f620004fd565b81600781518110620004f457620004f4620007b0565b60200260200101515b6001600160a01b03166102c052600881116200051a575f62000539565b81600881518110620005305762000530620007b0565b60200260200101515b6001600160a01b03166102e0526009811162000556575f62000575565b816009815181106200056c576200056c620007b0565b60200260200101515b6001600160a01b031661030052670de0b6b3a76400005f8190556040519081527fc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600c9060200160405180910390a150505050620007c4565b6001600160a01b0381168114620005e1575f80fd5b50565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715620006235762000623620005e4565b604052919050565b5f6001600160401b03821115620006465762000646620005e4565b5060051b60200190565b5f82601f83011262000660575f80fd5b815160206200067962000673836200062b565b620005f8565b8083825260208201915060208460051b8701019350868411156200069b575f80fd5b602086015b84811015620006c4578051620006b681620005cc565b8352918301918301620006a0565b509695505050505050565b5f805f60608486031215620006e2575f80fd5b8351620006ef81620005cc565b602085810151919450906001600160401b03808211156200070e575f80fd5b818701915087601f83011262000722575f80fd5b81516200073362000673826200062b565b81815260059190911b8301840190848101908a83111562000752575f80fd5b938501935b828510156200077d5784516200076d81620005cc565b8252938501939085019062000757565b60408a0151909750945050508083111562000796575f80fd5b5050620007a68682870162000650565b9150509250925092565b634e487b7160e01b5f52603260045260245ffd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e0516103005161032051611297620008cf5f395f818161012f015281816103ea0152818161057601528181610a610152610ace01525f61037501525f61034601525f61031701525f6102e801525f6102b901525f61028a01525f61025b01525f61022c01525f6101fd01525f6101ce01525f610d4301525f610d1401525f610ce501525f610cb601525f610c8701525f610c5801525f610c2901525f610bfa01525f610bcb01525f610b9c01525f818161010801526104c301526112975ff3fe608060405234801561000f575f80fd5b50600436106100b1575f3560e01c8063ab6d53bd1161006e578063ab6d53bd14610164578063c3bfd84214610179578063c52861f21461018c578063d380a37c14610194578063d5b356351461019d578063e4b50cb8146101b0575f80fd5b80630bc17feb146100b55780631f68f20a146100e55780632b11551a146100fb57806330504b6f14610103578063630afce51461012a57806363f1134e14610151575b5f80fd5b6100c86100c336600461111d565b6101c3565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ed5f5481565b6040519081526020016100dc565b6100ed6103d6565b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b6100c87f000000000000000000000000000000000000000000000000000000000000000081565b6100ed61015f36600461111d565b6103e6565b610177610172366004611134565b610488565b005b6100ed61018736600461111d565b610aca565b6100ed610b6d565b6100ed60015481565b6100ed6101ab36600461111d565b610b79565b6100c86101be36600461111d565b610b91565b5f815f036101f257507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160010361022157507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160020361025057507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160030361027f57507f0000000000000000000000000000000000000000000000000000000000000000919050565b816004036102ae57507f0000000000000000000000000000000000000000000000000000000000000000919050565b816005036102dd57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160060361030c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160070361033b57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160080361036a57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160090361039957507f0000000000000000000000000000000000000000000000000000000000000000919050565b60405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b60448201526064015b60405180910390fd5b5f6103e15f54610d67565b905090565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610444573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610468919061115d565b90505f6104758483610da3565b905061048081610d67565b949350505050565b61049181610e03565b61049a83610ea1565b6104c160405180608001604052805f81526020015f81526020015f81526020015f81525090565b7f00000000000000000000000000000000000000000000000000000000000000008082525f9067ffffffffffffffff8111156104ff576104ff611174565b604051908082528060200260200182016040528015610528578160200160208202803683370190505b5090505f825f015167ffffffffffffffff81111561054857610548611174565b604051908082528060200260200182016040528015610571578160200160208202803683370190505b5090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105f4919061115d565b602084018190525f906106119061060c908990610da3565b610d67565b90508481111561066d5760405162461bcd60e51b815260206004820152602160248201527f43523a204665652065786365656465642070726f7669646564206d6178696d756044820152606d60f81b60648201526084016103cd565b5f5b845181101561075b575f610682826101c3565b90505f805f836001600160a01b0316634ea15f376040518163ffffffff1660e01b81526004016060604051808303815f875af11580156106c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106e89190611188565b92509250925081878681518110610701576107016111c2565b602002602001018181525050801561074b57828960400181815161072591906111ea565b9052508751839089908790811061073e5761073e6111c2565b6020026020010181815250505b50506001909201915061066f9050565b5083604001515f036108d857835167ffffffffffffffff81111561078157610781611174565b6040519080825280602002602001820160405280156107aa578160200160208202803683370190505b5092505f5b84518110156108d6575f6107c2826101c3565b90505f816001600160a01b0316634ea15f376040518163ffffffff1660e01b81526004016060604051808303815f875af1158015610802573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108269190611188565b9250505080156108cc575f826001600160a01b031663795d26c36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610891919061115d565b905080886040018181516108a591906111ea565b905250865181908890869081106108be576108be6111c2565b602002602001018181525050505b50506001016107af565b505b5f5b8451811015610a22575f8482815181106108f6576108f66111c2565b60200260200101511115610a1a575f856040015185838151811061091c5761091c6111c2565b60200260200101518a61092f91906111fd565b6109399190611228565b90508015610a18575f61094b836101c3565b90505f816001600160a01b031663f8a239e83385898881518110610971576109716111c2565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0390931660048401526024830191909152604482015260648101889052608481018d905260a4016020604051808303815f875af11580156109da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109fe919061115d565b90508088606001818151610a1291906111ea565b90525050505b505b6001016108da565b50610a3584606001518560200151610f0d565b606084015115610ac1576060840151604051632770a7eb60e21b815233600482015260248101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac906044015f604051808303815f87803b158015610aaa575f80fd5b505af1158015610abc573d5f803e3d5ffd5b505050505b50505050505050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b4c919061115d565b90505f610b598483610da3565b9050610480610b6782610d67565b85610f5f565b5f6103e161060c610f7e565b5f610b8b610b85610b6d565b83610f5f565b92915050565b5f815f03610bc057507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600103610bef57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600203610c1e57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600303610c4d57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600403610c7c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600503610cab57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600603610cda57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600703610d0957507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600803610d3857507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160090361039957507f0000000000000000000000000000000000000000000000000000000000000000919050565b5f610b8b826002610d816064670de0b6b3a7640000611228565b610d8b9190611228565b610d9591906111ea565b670de0b6b3a7640000610fc6565b5f80610dad610f7e565b90505f83610dc3670de0b6b3a7640000876111fd565b610dcd9190611228565b90505f610ddb600183611228565b610de590846111ea565b9050610df981670de0b6b3a7640000610fc6565b9695505050505050565b6002610e186064670de0b6b3a7640000611228565b610e229190611228565b8110158015610e395750670de0b6b3a76400008111155b610e9e5760405162461bcd60e51b815260206004820152603060248201527f4d6178206665652070657263656e74616765206d75737420626520626574776560448201526f656e20302e352520616e64203130302560801b60648201526084016103cd565b50565b5f8111610e9e5760405162461bcd60e51b815260206004820152603460248201527f436f6c6c61746572616c52656769737472793a20416d6f756e74206d7573742060448201527362652067726561746572207468616e207a65726f60601b60648201526084016103cd565b5f610f188383610da3565b5f8190556040518181529091507fc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600c9060200160405180910390a1610f5a610fdd565b505050565b5f80670de0b6b3a7640000610f7484866111fd565b6104809190611228565b5f80610f88611032565b90505f610f9d670dd9e13cc602b4008361104d565b9050670de0b6b3a7640000815f54610fb591906111fd565b610fbf9190611228565b9250505090565b5f818310610fd45781610fd6565b825b9392505050565b5f60015442610fec919061123b565b9050603c8110610e9e574260018190556040519081527f860f8d2f0c74dd487e89e2883e3b25b8159ce1e1b3433a291cba7b82c508f3bc9060200160405180910390a150565b5f603c60015442611043919061123b565b6103e19190611228565b5f631f54050082111561106257631f54050091505b815f036110785750670de0b6b3a7640000610b8b565b670de0b6b3a764000083835b60018111156110eb5761109860028261124e565b5f036110bc576110a882836110f1565b91506110b5600282611228565b9050611084565b6110c682846110f1565b92506110d282836110f1565b915060026110e160018361123b565b6110b59190611228565b610df982845b5f806110fd83856111fd565b9050670de0b6b3a7640000611113600282611228565b610f7490836111ea565b5f6020828403121561112d575f80fd5b5035919050565b5f805f60608486031215611146575f80fd5b505081359360208301359350604090920135919050565b5f6020828403121561116d575f80fd5b5051919050565b634e487b7160e01b5f52604160045260245ffd5b5f805f6060848603121561119a575f80fd5b8351925060208401519150604084015180151581146111b7575f80fd5b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610b8b57610b8b6111d6565b8082028115828204841417610b8b57610b8b6111d6565b634e487b7160e01b5f52601260045260245ffd5b5f8261123657611236611214565b500490565b81810381811115610b8b57610b8b6111d6565b5f8261125c5761125c611214565b50069056fea264697066735822122006a832168dd1ee061efb0cecea018489256d2d4c10d0598b53a23f41c872a53864736f6c63430008180033000000000000000000000000b01dd87b29d187f3e3a4bf6cdaebfb97f3d9ab98000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0000000000000000000000000ae78736cd615f374d3085123a210448e74fc6393000000000000000000000000000000000000000000000000000000000000000300000000000000000000000081d78814df42da2cab0e8870c477bc3ed861de66000000000000000000000000b47ef60132deabc89580fd40e49c062d93070046000000000000000000000000de026433882a9dded65cac4fff8402fafff40fca
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100b1575f3560e01c8063ab6d53bd1161006e578063ab6d53bd14610164578063c3bfd84214610179578063c52861f21461018c578063d380a37c14610194578063d5b356351461019d578063e4b50cb8146101b0575f80fd5b80630bc17feb146100b55780631f68f20a146100e55780632b11551a146100fb57806330504b6f14610103578063630afce51461012a57806363f1134e14610151575b5f80fd5b6100c86100c336600461111d565b6101c3565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ed5f5481565b6040519081526020016100dc565b6100ed6103d6565b6100ed7f000000000000000000000000000000000000000000000000000000000000000381565b6100c87f000000000000000000000000b01dd87b29d187f3e3a4bf6cdaebfb97f3d9ab9881565b6100ed61015f36600461111d565b6103e6565b610177610172366004611134565b610488565b005b6100ed61018736600461111d565b610aca565b6100ed610b6d565b6100ed60015481565b6100ed6101ab36600461111d565b610b79565b6100c86101be36600461111d565b610b91565b5f815f036101f257507f00000000000000000000000081d78814df42da2cab0e8870c477bc3ed861de66919050565b8160010361022157507f000000000000000000000000b47ef60132deabc89580fd40e49c062d93070046919050565b8160020361025057507f000000000000000000000000de026433882a9dded65cac4fff8402fafff40fca919050565b8160030361027f57507f0000000000000000000000000000000000000000000000000000000000000000919050565b816004036102ae57507f0000000000000000000000000000000000000000000000000000000000000000919050565b816005036102dd57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160060361030c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160070361033b57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160080361036a57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160090361039957507f0000000000000000000000000000000000000000000000000000000000000000919050565b60405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b60448201526064015b60405180910390fd5b5f6103e15f54610d67565b905090565b5f807f000000000000000000000000b01dd87b29d187f3e3a4bf6cdaebfb97f3d9ab986001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610444573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610468919061115d565b90505f6104758483610da3565b905061048081610d67565b949350505050565b61049181610e03565b61049a83610ea1565b6104c160405180608001604052805f81526020015f81526020015f81526020015f81525090565b7f00000000000000000000000000000000000000000000000000000000000000038082525f9067ffffffffffffffff8111156104ff576104ff611174565b604051908082528060200260200182016040528015610528578160200160208202803683370190505b5090505f825f015167ffffffffffffffff81111561054857610548611174565b604051908082528060200260200182016040528015610571578160200160208202803683370190505b5090507f000000000000000000000000b01dd87b29d187f3e3a4bf6cdaebfb97f3d9ab986001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105f4919061115d565b602084018190525f906106119061060c908990610da3565b610d67565b90508481111561066d5760405162461bcd60e51b815260206004820152602160248201527f43523a204665652065786365656465642070726f7669646564206d6178696d756044820152606d60f81b60648201526084016103cd565b5f5b845181101561075b575f610682826101c3565b90505f805f836001600160a01b0316634ea15f376040518163ffffffff1660e01b81526004016060604051808303815f875af11580156106c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106e89190611188565b92509250925081878681518110610701576107016111c2565b602002602001018181525050801561074b57828960400181815161072591906111ea565b9052508751839089908790811061073e5761073e6111c2565b6020026020010181815250505b50506001909201915061066f9050565b5083604001515f036108d857835167ffffffffffffffff81111561078157610781611174565b6040519080825280602002602001820160405280156107aa578160200160208202803683370190505b5092505f5b84518110156108d6575f6107c2826101c3565b90505f816001600160a01b0316634ea15f376040518163ffffffff1660e01b81526004016060604051808303815f875af1158015610802573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108269190611188565b9250505080156108cc575f826001600160a01b031663795d26c36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610891919061115d565b905080886040018181516108a591906111ea565b905250865181908890869081106108be576108be6111c2565b602002602001018181525050505b50506001016107af565b505b5f5b8451811015610a22575f8482815181106108f6576108f66111c2565b60200260200101511115610a1a575f856040015185838151811061091c5761091c6111c2565b60200260200101518a61092f91906111fd565b6109399190611228565b90508015610a18575f61094b836101c3565b90505f816001600160a01b031663f8a239e83385898881518110610971576109716111c2565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0390931660048401526024830191909152604482015260648101889052608481018d905260a4016020604051808303815f875af11580156109da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109fe919061115d565b90508088606001818151610a1291906111ea565b90525050505b505b6001016108da565b50610a3584606001518560200151610f0d565b606084015115610ac1576060840151604051632770a7eb60e21b815233600482015260248101919091527f000000000000000000000000b01dd87b29d187f3e3a4bf6cdaebfb97f3d9ab986001600160a01b031690639dc29fac906044015f604051808303815f87803b158015610aaa575f80fd5b505af1158015610abc573d5f803e3d5ffd5b505050505b50505050505050565b5f807f000000000000000000000000b01dd87b29d187f3e3a4bf6cdaebfb97f3d9ab986001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b4c919061115d565b90505f610b598483610da3565b9050610480610b6782610d67565b85610f5f565b5f6103e161060c610f7e565b5f610b8b610b85610b6d565b83610f5f565b92915050565b5f815f03610bc057507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2919050565b81600103610bef57507f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0919050565b81600203610c1e57507f000000000000000000000000ae78736cd615f374d3085123a210448e74fc6393919050565b81600303610c4d57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600403610c7c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600503610cab57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600603610cda57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600703610d0957507f0000000000000000000000000000000000000000000000000000000000000000919050565b81600803610d3857507f0000000000000000000000000000000000000000000000000000000000000000919050565b8160090361039957507f0000000000000000000000000000000000000000000000000000000000000000919050565b5f610b8b826002610d816064670de0b6b3a7640000611228565b610d8b9190611228565b610d9591906111ea565b670de0b6b3a7640000610fc6565b5f80610dad610f7e565b90505f83610dc3670de0b6b3a7640000876111fd565b610dcd9190611228565b90505f610ddb600183611228565b610de590846111ea565b9050610df981670de0b6b3a7640000610fc6565b9695505050505050565b6002610e186064670de0b6b3a7640000611228565b610e229190611228565b8110158015610e395750670de0b6b3a76400008111155b610e9e5760405162461bcd60e51b815260206004820152603060248201527f4d6178206665652070657263656e74616765206d75737420626520626574776560448201526f656e20302e352520616e64203130302560801b60648201526084016103cd565b50565b5f8111610e9e5760405162461bcd60e51b815260206004820152603460248201527f436f6c6c61746572616c52656769737472793a20416d6f756e74206d7573742060448201527362652067726561746572207468616e207a65726f60601b60648201526084016103cd565b5f610f188383610da3565b5f8190556040518181529091507fc454ee9b76c52f782a256af821b857ca6e125d1e3333bcede402fec2bed9600c9060200160405180910390a1610f5a610fdd565b505050565b5f80670de0b6b3a7640000610f7484866111fd565b6104809190611228565b5f80610f88611032565b90505f610f9d670dd9e13cc602b4008361104d565b9050670de0b6b3a7640000815f54610fb591906111fd565b610fbf9190611228565b9250505090565b5f818310610fd45781610fd6565b825b9392505050565b5f60015442610fec919061123b565b9050603c8110610e9e574260018190556040519081527f860f8d2f0c74dd487e89e2883e3b25b8159ce1e1b3433a291cba7b82c508f3bc9060200160405180910390a150565b5f603c60015442611043919061123b565b6103e19190611228565b5f631f54050082111561106257631f54050091505b815f036110785750670de0b6b3a7640000610b8b565b670de0b6b3a764000083835b60018111156110eb5761109860028261124e565b5f036110bc576110a882836110f1565b91506110b5600282611228565b9050611084565b6110c682846110f1565b92506110d282836110f1565b915060026110e160018361123b565b6110b59190611228565b610df982845b5f806110fd83856111fd565b9050670de0b6b3a7640000611113600282611228565b610f7490836111ea565b5f6020828403121561112d575f80fd5b5035919050565b5f805f60608486031215611146575f80fd5b505081359360208301359350604090920135919050565b5f6020828403121561116d575f80fd5b5051919050565b634e487b7160e01b5f52604160045260245ffd5b5f805f6060848603121561119a575f80fd5b8351925060208401519150604084015180151581146111b7575f80fd5b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610b8b57610b8b6111d6565b8082028115828204841417610b8b57610b8b6111d6565b634e487b7160e01b5f52601260045260245ffd5b5f8261123657611236611214565b500490565b81810381811115610b8b57610b8b6111d6565b5f8261125c5761125c611214565b50069056fea264697066735822122006a832168dd1ee061efb0cecea018489256d2d4c10d0598b53a23f41c872a53864736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b01dd87b29d187f3e3a4bf6cdaebfb97f3d9ab98000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0000000000000000000000000ae78736cd615f374d3085123a210448e74fc6393000000000000000000000000000000000000000000000000000000000000000300000000000000000000000081d78814df42da2cab0e8870c477bc3ed861de66000000000000000000000000b47ef60132deabc89580fd40e49c062d93070046000000000000000000000000de026433882a9dded65cac4fff8402fafff40fca
-----Decoded View---------------
Arg [0] : _boldToken (address): 0xb01dd87B29d187F3E3a4Bf6cdAebfb97F3D9aB98
Arg [1] : _tokens (address[]): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0,0xae78736Cd615f374D3085123A210448E74Fc6393
Arg [2] : _troveManagers (address[]): 0x81D78814DF42DA2caB0E8870C477bC3Ed861DE66,0xb47eF60132dEaBc89580Fd40e49C062D93070046,0xde026433882a9DdED65cAc4FfF8402FAFFF40FcA
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 000000000000000000000000b01dd87b29d187f3e3a4bf6cdaebfb97f3d9ab98
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [4] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [5] : 0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0
Arg [6] : 000000000000000000000000ae78736cd615f374d3085123a210448e74fc6393
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [8] : 00000000000000000000000081d78814df42da2cab0e8870c477bc3ed861de66
Arg [9] : 000000000000000000000000b47ef60132deabc89580fd40e49c062d93070046
Arg [10] : 000000000000000000000000de026433882a9dded65cac4fff8402fafff40fca
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.