ETH Price: $2,660.31 (-0.20%)

Contract

0x3C5871D69C8d6503001e1A8f3bF7E5EbE447A9Cd
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Advanced mode:
Parent Transaction Hash Block
From
To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MultiCollateralHintHelpers

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion, MIT license
File 1 of 7 : MultiCollateralHintHelpers.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;

import "IBorrowerOperations.sol";
import "ITroveManager.sol";
import "ISortedTroves.sol";
import "IFactory.sol";
import "PrismaBase.sol";
import "PrismaMath.sol";

contract MultiCollateralHintHelpers is PrismaBase {
    IBorrowerOperations public immutable borrowerOperations;

    constructor(address _borrowerOperationsAddress, uint256 _gasCompensation) PrismaBase(_gasCompensation) {
        borrowerOperations = IBorrowerOperations(_borrowerOperationsAddress);
    }

    // --- Functions ---

    /* getRedemptionHints() - Helper function for finding the right hints to pass to redeemCollateral().
     *
     * It simulates a redemption of `_debtAmount` to figure out where the redemption sequence will start and what state the final Trove
     * of the sequence will end up in.
     *
     * Returns three hints:
     *  - `firstRedemptionHint` is the address of the first Trove with ICR >= MCR (i.e. the first Trove that will be redeemed).
     *  - `partialRedemptionHintNICR` is the final nominal ICR of the last Trove of the sequence after being hit by partial redemption,
     *     or zero in case of no partial redemption.
     *  - `truncatedDebtAmount` is the maximum amount that can be redeemed out of the the provided `_debtAmount`. This can be lower than
     *    `_debtAmount` when redeeming the full amount would leave the last Trove of the redemption sequence with less net debt than the
     *    minimum allowed value (i.e. MIN_NET_DEBT).
     *
     * The number of Troves to consider for redemption can be capped by passing a non-zero value as `_maxIterations`, while passing zero
     * will leave it uncapped.
     */

    function getRedemptionHints(
        ITroveManager troveManager,
        uint256 _debtAmount,
        uint256 _price,
        uint256 _maxIterations
    )
        external
        view
        returns (address firstRedemptionHint, uint256 partialRedemptionHintNICR, uint256 truncatedDebtAmount)
    {
        ISortedTroves sortedTrovesCached = ISortedTroves(troveManager.sortedTroves());

        uint256 remainingDebt = _debtAmount;
        address currentTroveuser = sortedTrovesCached.getLast();
        uint256 MCR = troveManager.MCR();

        while (currentTroveuser != address(0) && troveManager.getCurrentICR(currentTroveuser, _price) < MCR) {
            currentTroveuser = sortedTrovesCached.getPrev(currentTroveuser);
        }

        firstRedemptionHint = currentTroveuser;

        if (_maxIterations == 0) {
            _maxIterations = type(uint256).max;
        }

        uint256 minNetDebt = borrowerOperations.minNetDebt();
        while (currentTroveuser != address(0) && remainingDebt > 0 && _maxIterations-- > 0) {
            (uint256 debt, uint256 coll, , ) = troveManager.getEntireDebtAndColl(currentTroveuser);
            uint256 netDebt = _getNetDebt(debt);

            if (netDebt > remainingDebt) {
                if (netDebt > minNetDebt) {
                    uint256 maxRedeemableDebt = PrismaMath._min(remainingDebt, netDebt - minNetDebt);

                    uint256 newColl = coll - ((maxRedeemableDebt * DECIMAL_PRECISION) / _price);
                    uint256 newDebt = netDebt - maxRedeemableDebt;

                    uint256 compositeDebt = _getCompositeDebt(newDebt);
                    partialRedemptionHintNICR = PrismaMath._computeNominalCR(newColl, compositeDebt);

                    remainingDebt = remainingDebt - maxRedeemableDebt;
                }
                break;
            } else {
                remainingDebt = remainingDebt - netDebt;
            }

            currentTroveuser = sortedTrovesCached.getPrev(currentTroveuser);
        }

        truncatedDebtAmount = _debtAmount - remainingDebt;
    }

    /* getApproxHint() - return address of a Trove that is, on average, (length / numTrials) positions away in the
    sortedTroves list from the correct insert position of the Trove to be inserted.

    Note: The output address is worst-case O(n) positions away from the correct insert position, however, the function
    is probabilistic. Input can be tuned to guarantee results to a high degree of confidence, e.g:

    Submitting numTrials = k * sqrt(length), with k = 15 makes it very, very likely that the ouput address will
    be <= sqrt(length) positions away from the correct insert position.
    */
    function getApproxHint(
        ITroveManager troveManager,
        uint256 _CR,
        uint256 _numTrials,
        uint256 _inputRandomSeed
    ) external view returns (address hintAddress, uint256 diff, uint256 latestRandomSeed) {
        ISortedTroves sortedTroves = ISortedTroves(troveManager.sortedTroves());
        uint256 arrayLength = troveManager.getTroveOwnersCount();

        if (arrayLength == 0) {
            return (address(0), 0, _inputRandomSeed);
        }

        hintAddress = sortedTroves.getLast();
        diff = PrismaMath._getAbsoluteDifference(_CR, troveManager.getNominalICR(hintAddress));
        latestRandomSeed = _inputRandomSeed;

        uint256 i = 1;

        while (i < _numTrials) {
            latestRandomSeed = uint256(keccak256(abi.encodePacked(latestRandomSeed)));

            uint256 arrayIndex = latestRandomSeed % arrayLength;
            address currentAddress = troveManager.getTroveFromTroveOwnersArray(arrayIndex);
            uint256 currentNICR = troveManager.getNominalICR(currentAddress);

            // check if abs(current - CR) > abs(closest - CR), and update closest if current is closer
            uint256 currentDiff = PrismaMath._getAbsoluteDifference(currentNICR, _CR);

            if (currentDiff < diff) {
                diff = currentDiff;
                hintAddress = currentAddress;
            }
            i++;
        }
    }

    function computeNominalCR(uint256 _coll, uint256 _debt) external pure returns (uint256) {
        return PrismaMath._computeNominalCR(_coll, _debt);
    }

    function computeCR(uint256 _coll, uint256 _debt, uint256 _price) external pure returns (uint256) {
        return PrismaMath._computeCR(_coll, _debt, _price);
    }
}

File 2 of 7 : IBorrowerOperations.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IBorrowerOperations {
    struct Balances {
        uint256[] collaterals;
        uint256[] debts;
        uint256[] prices;
    }

    event BorrowingFeePaid(address indexed borrower, uint256 amount);
    event CollateralConfigured(address troveManager, address collateralToken);
    event TroveCreated(address indexed _borrower, uint256 arrayIndex);
    event TroveManagerRemoved(address troveManager);
    event TroveUpdated(address indexed _borrower, uint256 _debt, uint256 _coll, uint256 stake, uint8 operation);

    function addColl(
        address troveManager,
        address account,
        uint256 _collateralAmount,
        address _upperHint,
        address _lowerHint
    ) external;

    function adjustTrove(
        address troveManager,
        address account,
        uint256 _maxFeePercentage,
        uint256 _collDeposit,
        uint256 _collWithdrawal,
        uint256 _debtChange,
        bool _isDebtIncrease,
        address _upperHint,
        address _lowerHint
    ) external;

    function closeTrove(address troveManager, address account) external;

    function configureCollateral(address troveManager, address collateralToken) external;

    function fetchBalances() external returns (Balances memory balances);

    function getGlobalSystemBalances() external returns (uint256 totalPricedCollateral, uint256 totalDebt);

    function getTCR() external returns (uint256 globalTotalCollateralRatio);

    function openTrove(
        address troveManager,
        address account,
        uint256 _maxFeePercentage,
        uint256 _collateralAmount,
        uint256 _debtAmount,
        address _upperHint,
        address _lowerHint
    ) external;

    function removeTroveManager(address troveManager) external;

    function repayDebt(
        address troveManager,
        address account,
        uint256 _debtAmount,
        address _upperHint,
        address _lowerHint
    ) external;

    function setDelegateApproval(address _delegate, bool _isApproved) external;

    function setMinNetDebt(uint256 _minNetDebt) external;

    function withdrawColl(
        address troveManager,
        address account,
        uint256 _collWithdrawal,
        address _upperHint,
        address _lowerHint
    ) external;

    function withdrawDebt(
        address troveManager,
        address account,
        uint256 _maxFeePercentage,
        uint256 _debtAmount,
        address _upperHint,
        address _lowerHint
    ) external;

    function checkRecoveryMode(uint256 TCR) external pure returns (bool);

    function CCR() external view returns (uint256);

    function DEBT_GAS_COMPENSATION() external view returns (uint256);

    function DECIMAL_PRECISION() external view returns (uint256);

    function PERCENT_DIVISOR() external view returns (uint256);

    function PRISMA_CORE() external view returns (address);

    function _100pct() external view returns (uint256);

    function debtToken() external view returns (address);

    function factory() external view returns (address);

    function getCompositeDebt(uint256 _debt) external view returns (uint256);

    function guardian() external view returns (address);

    function isApprovedDelegate(address owner, address caller) external view returns (bool isApproved);

    function minNetDebt() external view returns (uint256);

    function owner() external view returns (address);

    function troveManagersData(address) external view returns (address collateralToken, uint16 index);
}

File 3 of 7 : ITroveManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface ITroveManager {
    event BaseRateUpdated(uint256 _baseRate);
    event CollateralSent(address _to, uint256 _amount);
    event LTermsUpdated(uint256 _L_collateral, uint256 _L_debt);
    event LastFeeOpTimeUpdated(uint256 _lastFeeOpTime);
    event Redemption(
        uint256 _attemptedDebtAmount,
        uint256 _actualDebtAmount,
        uint256 _collateralSent,
        uint256 _collateralFee
    );
    event RewardClaimed(address indexed account, address indexed recipient, uint256 claimed);
    event SystemSnapshotsUpdated(uint256 _totalStakesSnapshot, uint256 _totalCollateralSnapshot);
    event TotalStakesUpdated(uint256 _newTotalStakes);
    event TroveIndexUpdated(address _borrower, uint256 _newIndex);
    event TroveSnapshotsUpdated(uint256 _L_collateral, uint256 _L_debt);
    event TroveUpdated(address indexed _borrower, uint256 _debt, uint256 _coll, uint256 _stake, uint8 _operation);

    function addCollateralSurplus(address borrower, uint256 collSurplus) external;

    function applyPendingRewards(address _borrower) external returns (uint256 coll, uint256 debt);

    function claimCollateral(address _receiver) external;

    function claimReward(address receiver) external returns (uint256);

    function closeTrove(address _borrower, address _receiver, uint256 collAmount, uint256 debtAmount) external;

    function closeTroveByLiquidation(address _borrower) external;

    function collectInterests() external;

    function decayBaseRateAndGetBorrowingFee(uint256 _debt) external returns (uint256);

    function decreaseDebtAndSendCollateral(address account, uint256 debt, uint256 coll) external;

    function fetchPrice() external returns (uint256);

    function finalizeLiquidation(
        address _liquidator,
        uint256 _debt,
        uint256 _coll,
        uint256 _collSurplus,
        uint256 _debtGasComp,
        uint256 _collGasComp
    ) external;

    function getEntireSystemBalances() external returns (uint256, uint256, uint256);

    function movePendingTroveRewardsToActiveBalances(uint256 _debt, uint256 _collateral) external;

    function notifyRegisteredId(uint256[] calldata _assignedIds) external returns (bool);

    function openTrove(
        address _borrower,
        uint256 _collateralAmount,
        uint256 _compositeDebt,
        uint256 NICR,
        address _upperHint,
        address _lowerHint,
        bool _isRecoveryMode
    ) external returns (uint256 stake, uint256 arrayIndex);

    function redeemCollateral(
        uint256 _debtAmount,
        address _firstRedemptionHint,
        address _upperPartialRedemptionHint,
        address _lowerPartialRedemptionHint,
        uint256 _partialRedemptionHintNICR,
        uint256 _maxIterations,
        uint256 _maxFeePercentage
    ) external;

    function setAddresses(address _priceFeedAddress, address _sortedTrovesAddress, address _collateralToken) external;

    function setParameters(
        uint256 _minuteDecayFactor,
        uint256 _redemptionFeeFloor,
        uint256 _maxRedemptionFee,
        uint256 _borrowingFeeFloor,
        uint256 _maxBorrowingFee,
        uint256 _interestRateInBPS,
        uint256 _maxSystemDebt,
        uint256 _MCR
    ) external;

    function setPaused(bool _paused) external;

    function setPriceFeed(address _priceFeedAddress) external;

    function startSunset() external;

    function updateBalances() external;

    function updateTroveFromAdjustment(
        bool _isRecoveryMode,
        bool _isDebtIncrease,
        uint256 _debtChange,
        uint256 _netDebtChange,
        bool _isCollIncrease,
        uint256 _collChange,
        address _upperHint,
        address _lowerHint,
        address _borrower,
        address _receiver
    ) external returns (uint256, uint256, uint256);

    function vaultClaimReward(address claimant, address) external returns (uint256);

    function BOOTSTRAP_PERIOD() external view returns (uint256);

    function CCR() external view returns (uint256);

    function DEBT_GAS_COMPENSATION() external view returns (uint256);

    function DECIMAL_PRECISION() external view returns (uint256);

    function L_collateral() external view returns (uint256);

    function L_debt() external view returns (uint256);

    function MAX_INTEREST_RATE_IN_BPS() external view returns (uint256);

    function MCR() external view returns (uint256);

    function PERCENT_DIVISOR() external view returns (uint256);

    function PRISMA_CORE() external view returns (address);

    function SUNSETTING_INTEREST_RATE() external view returns (uint256);

    function Troves(
        address
    )
        external
        view
        returns (
            uint256 debt,
            uint256 coll,
            uint256 stake,
            uint8 status,
            uint128 arrayIndex,
            uint256 activeInterestIndex
        );

    function accountLatestMint(address) external view returns (uint32 amount, uint32 week, uint32 day);

    function activeInterestIndex() external view returns (uint256);

    function baseRate() external view returns (uint256);

    function borrowerOperationsAddress() external view returns (address);

    function borrowingFeeFloor() external view returns (uint256);

    function claimableReward(address account) external view returns (uint256);

    function collateralToken() external view returns (address);

    function dailyMintReward(uint256) external view returns (uint256);

    function debtToken() external view returns (address);

    function defaultedCollateral() external view returns (uint256);

    function defaultedDebt() external view returns (uint256);

    function emissionId() external view returns (uint16 debt, uint16 minting);

    function getBorrowingFee(uint256 _debt) external view returns (uint256);

    function getBorrowingFeeWithDecay(uint256 _debt) external view returns (uint256);

    function getBorrowingRate() external view returns (uint256);

    function getBorrowingRateWithDecay() external view returns (uint256);

    function getCurrentICR(address _borrower, uint256 _price) external view returns (uint256);

    function getEntireDebtAndColl(
        address _borrower
    ) external view returns (uint256 debt, uint256 coll, uint256 pendingDebtReward, uint256 pendingCollateralReward);

    function getEntireSystemColl() external view returns (uint256);

    function getEntireSystemDebt() external view returns (uint256);

    function getNominalICR(address _borrower) external view returns (uint256);

    function getPendingCollAndDebtRewards(address _borrower) external view returns (uint256, uint256);

    function getRedemptionFeeWithDecay(uint256 _collateralDrawn) external view returns (uint256);

    function getRedemptionRate() external view returns (uint256);

    function getRedemptionRateWithDecay() external view returns (uint256);

    function getTotalActiveCollateral() external view returns (uint256);

    function getTotalActiveDebt() external view returns (uint256);

    function getTotalMints(uint256 week) external view returns (uint32[7] memory);

    function getTroveCollAndDebt(address _borrower) external view returns (uint256 coll, uint256 debt);

    function getTroveFromTroveOwnersArray(uint256 _index) external view returns (address);

    function getTroveOwnersCount() external view returns (uint256);

    function getTroveStake(address _borrower) external view returns (uint256);

    function getTroveStatus(address _borrower) external view returns (uint256);

    function getWeek() external view returns (uint256 week);

    function getWeekAndDay() external view returns (uint256, uint256);

    function guardian() external view returns (address);

    function hasPendingRewards(address _borrower) external view returns (bool);

    function interestPayable() external view returns (uint256);

    function interestRate() external view returns (uint256);

    function lastActiveIndexUpdate() external view returns (uint256);

    function lastCollateralError_Redistribution() external view returns (uint256);

    function lastDebtError_Redistribution() external view returns (uint256);

    function lastFeeOperationTime() external view returns (uint256);

    function lastUpdate() external view returns (uint32);

    function liquidationManager() external view returns (address);

    function maxBorrowingFee() external view returns (uint256);

    function maxRedemptionFee() external view returns (uint256);

    function maxSystemDebt() external view returns (uint256);

    function minuteDecayFactor() external view returns (uint256);

    function owner() external view returns (address);

    function paused() external view returns (bool);

    function periodFinish() external view returns (uint32);

    function priceFeed() external view returns (address);

    function redemptionFeeFloor() external view returns (uint256);

    function rewardIntegral() external view returns (uint256);

    function rewardIntegralFor(address) external view returns (uint256);

    function rewardRate() external view returns (uint128);

    function rewardSnapshots(address) external view returns (uint256 collateral, uint256 debt);

    function sortedTroves() external view returns (address);

    function sunsetting() external view returns (bool);

    function surplusBalances(address) external view returns (uint256);

    function systemDeploymentTime() external view returns (uint256);

    function totalCollateralSnapshot() external view returns (uint256);

    function totalStakes() external view returns (uint256);

    function totalStakesSnapshot() external view returns (uint256);

    function vault() external view returns (address);
}

File 4 of 7 : ISortedTroves.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface ISortedTroves {
    event NodeAdded(address _id, uint256 _NICR);
    event NodeRemoved(address _id);

    function insert(address _id, uint256 _NICR, address _prevId, address _nextId) external;

    function reInsert(address _id, uint256 _newNICR, address _prevId, address _nextId) external;

    function remove(address _id) external;

    function setAddresses(address _troveManagerAddress) external;

    function contains(address _id) external view returns (bool);

    function data() external view returns (address head, address tail, uint256 size);

    function findInsertPosition(
        uint256 _NICR,
        address _prevId,
        address _nextId
    ) external view returns (address, address);

    function getFirst() external view returns (address);

    function getLast() external view returns (address);

    function getNext(address _id) external view returns (address);

    function getPrev(address _id) external view returns (address);

    function getSize() external view returns (uint256);

    function isEmpty() external view returns (bool);

    function troveManager() external view returns (address);

    function validInsertPosition(uint256 _NICR, address _prevId, address _nextId) external view returns (bool);
}

File 5 of 7 : IFactory.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;

interface IFactory {
    // commented values are suggested default parameters
    struct DeploymentParams {
        uint256 minuteDecayFactor; // 999037758833783000  (half life of 12 hours)
        uint256 redemptionFeeFloor; // 1e18 / 1000 * 5  (0.5%)
        uint256 maxRedemptionFee; // 1e18  (100%)
        uint256 borrowingFeeFloor; // 1e18 / 1000 * 5  (0.5%)
        uint256 maxBorrowingFee; // 1e18 / 100 * 5  (5%)
        uint256 interestRateInBps; // 100 (1%)
        uint256 maxDebt;
        uint256 MCR; // 12 * 1e17  (120%)
    }

    event NewDeployment(address collateral, address priceFeed, address troveManager, address sortedTroves);

    function deployNewInstance(
        address collateral,
        address priceFeed,
        address customTroveManagerImpl,
        address customSortedTrovesImpl,
        DeploymentParams calldata params
    ) external;

    function setImplementations(address _troveManagerImpl, address _sortedTrovesImpl) external;

    function PRISMA_CORE() external view returns (address);

    function borrowerOperations() external view returns (address);

    function debtToken() external view returns (address);

    function guardian() external view returns (address);

    function liquidationManager() external view returns (address);

    function owner() external view returns (address);

    function sortedTrovesImpl() external view returns (address);

    function stabilityPool() external view returns (address);

    function troveManagerCount() external view returns (uint256);

    function troveManagerImpl() external view returns (address);

    function troveManagers(uint256) external view returns (address);
}

File 6 of 7 : PrismaBase.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;

/*
 * Base contract for TroveManager, BorrowerOperations and StabilityPool. Contains global system constants and
 * common functions.
 */
contract PrismaBase {
    uint256 public constant DECIMAL_PRECISION = 1e18;

    // Critical system collateral ratio. If the system's total collateral ratio (TCR) falls below the CCR, Recovery Mode is triggered.
    uint256 public constant CCR = 1500000000000000000; // 150%

    // Amount of debt to be locked in gas pool on opening troves
    uint256 public immutable DEBT_GAS_COMPENSATION;

    uint256 public constant PERCENT_DIVISOR = 200; // dividing by 200 yields 0.5%

    constructor(uint256 _gasCompensation) {
        DEBT_GAS_COMPENSATION = _gasCompensation;
    }

    // --- Gas compensation functions ---

    // Returns the composite debt (drawn debt + gas compensation) of a trove, for the purpose of ICR calculation
    function _getCompositeDebt(uint256 _debt) internal view returns (uint256) {
        return _debt + DEBT_GAS_COMPENSATION;
    }

    function _getNetDebt(uint256 _debt) internal view returns (uint256) {
        return _debt - DEBT_GAS_COMPENSATION;
    }

    // Return the amount of collateral to be drawn from a trove's collateral and sent as gas compensation.
    function _getCollGasCompensation(uint256 _entireColl) internal pure returns (uint256) {
        return _entireColl / PERCENT_DIVISOR;
    }

    function _requireUserAcceptsFee(uint256 _fee, uint256 _amount, uint256 _maxFeePercentage) internal pure {
        uint256 feePercentage = (_fee * DECIMAL_PRECISION) / _amount;
        require(feePercentage <= _maxFeePercentage, "Fee exceeded provided maximum");
    }
}

File 7 of 7 : PrismaMath.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;

library PrismaMath {
    uint256 internal constant DECIMAL_PRECISION = 1e18;

    /* Precision for Nominal ICR (independent of price). Rationale for the value:
     *
     * - Making it “too high” could lead to overflows.
     * - Making it “too low” could lead to an ICR equal to zero, due to truncation from Solidity floor division.
     *
     * This value of 1e20 is chosen for safety: the NICR will only overflow for numerator > ~1e39,
     * and will only truncate to 0 if the denominator is at least 1e20 times greater than the numerator.
     *
     */
    uint256 internal constant NICR_PRECISION = 1e20;

    function _min(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return (_a < _b) ? _a : _b;
    }

    function _max(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return (_a >= _b) ? _a : _b;
    }

    /*
     * Multiply two decimal numbers and use normal rounding rules:
     * -round product up if 19'th mantissa digit >= 5
     * -round product down if 19'th mantissa digit < 5
     *
     * Used only inside the exponentiation, _decPow().
     */
    function decMul(uint256 x, uint256 y) internal pure returns (uint256 decProd) {
        uint256 prod_xy = x * y;

        decProd = (prod_xy + (DECIMAL_PRECISION / 2)) / DECIMAL_PRECISION;
    }

    /*
     * _decPow: Exponentiation function for 18-digit decimal base, and integer exponent n.
     *
     * Uses the efficient "exponentiation by squaring" algorithm. O(log(n)) complexity.
     *
     * Called by two functions that represent time in units of minutes:
     * 1) TroveManager._calcDecayedBaseRate
     * 2) CommunityIssuance._getCumulativeIssuanceFraction
     *
     * The exponent is capped to avoid reverting due to overflow. The cap 525600000 equals
     * "minutes in 1000 years": 60 * 24 * 365 * 1000
     *
     * If a period of > 1000 years is ever used as an exponent in either of the above functions, the result will be
     * negligibly different from just passing the cap, since:
     *
     * In function 1), the decayed base rate will be 0 for 1000 years or > 1000 years
     * In function 2), the difference in tokens issued at 1000 years and any time > 1000 years, will be negligible
     */
    function _decPow(uint256 _base, uint256 _minutes) internal pure returns (uint256) {
        if (_minutes > 525600000) {
            _minutes = 525600000;
        } // cap to avoid overflow

        if (_minutes == 0) {
            return DECIMAL_PRECISION;
        }

        uint256 y = DECIMAL_PRECISION;
        uint256 x = _base;
        uint256 n = _minutes;

        // Exponentiation-by-squaring
        while (n > 1) {
            if (n % 2 == 0) {
                x = decMul(x, x);
                n = n / 2;
            } else {
                // if (n % 2 != 0)
                y = decMul(x, y);
                x = decMul(x, x);
                n = (n - 1) / 2;
            }
        }

        return decMul(x, y);
    }

    function _getAbsoluteDifference(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return (_a >= _b) ? _a - _b : _b - _a;
    }

    function _computeNominalCR(uint256 _coll, uint256 _debt) internal pure returns (uint256) {
        if (_debt > 0) {
            return (_coll * NICR_PRECISION) / _debt;
        }
        // Return the maximal value for uint256 if the Trove has a debt of 0. Represents "infinite" CR.
        else {
            // if (_debt == 0)
            return 2 ** 256 - 1;
        }
    }

    function _computeCR(uint256 _coll, uint256 _debt, uint256 _price) internal pure returns (uint256) {
        if (_debt > 0) {
            uint256 newCollRatio = (_coll * _price) / _debt;

            return newCollRatio;
        }
        // Return the maximal value for uint256 if the Trove has a debt of 0. Represents "infinite" CR.
        else {
            // if (_debt == 0)
            return 2 ** 256 - 1;
        }
    }

    function _computeCR(uint256 _coll, uint256 _debt) internal pure returns (uint256) {
        if (_debt > 0) {
            uint256 newCollRatio = (_coll) / _debt;

            return newCollRatio;
        }
        // Return the maximal value for uint256 if the Trove has a debt of 0. Represents "infinite" CR.
        else {
            // if (_debt == 0)
            return 2 ** 256 - 1;
        }
    }
}

Settings
{
  "evmVersion": "paris",
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "libraries": {
    "MultiCollateralHintHelpers.sol": {}
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_borrowerOperationsAddress","type":"address"},{"internalType":"uint256","name":"_gasCompensation","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEBT_GAS_COMPENSATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowerOperations","outputs":[{"internalType":"contract IBorrowerOperations","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_coll","type":"uint256"},{"internalType":"uint256","name":"_debt","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"computeCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_coll","type":"uint256"},{"internalType":"uint256","name":"_debt","type":"uint256"}],"name":"computeNominalCR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract ITroveManager","name":"troveManager","type":"address"},{"internalType":"uint256","name":"_CR","type":"uint256"},{"internalType":"uint256","name":"_numTrials","type":"uint256"},{"internalType":"uint256","name":"_inputRandomSeed","type":"uint256"}],"name":"getApproxHint","outputs":[{"internalType":"address","name":"hintAddress","type":"address"},{"internalType":"uint256","name":"diff","type":"uint256"},{"internalType":"uint256","name":"latestRandomSeed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ITroveManager","name":"troveManager","type":"address"},{"internalType":"uint256","name":"_debtAmount","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_maxIterations","type":"uint256"}],"name":"getRedemptionHints","outputs":[{"internalType":"address","name":"firstRedemptionHint","type":"address"},{"internalType":"uint256","name":"partialRedemptionHintNICR","type":"uint256"},{"internalType":"uint256","name":"truncatedDebtAmount","type":"uint256"}],"stateMutability":"view","type":"function"}]

60c060405234801561001057600080fd5b50604051610d66380380610d6683398101604081905261002f91610043565b6080526001600160a01b031660a05261007d565b6000806040838503121561005657600080fd5b82516001600160a01b038116811461006d57600080fd5b6020939093015192949293505050565b60805160a051610cb06100b66000396000818161014c01526103f801526000818160f0015281816109bb01526109fd0152610cb06000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80635733d58f116100665780635733d58f14610125578063701526b41461013457806377553ad414610147578063a20baee614610186578063c394a7fa1461019557600080fd5b8063301be459146100985780634870dd9a146100d55780634ba4a28b146100eb578063525acdbb14610112575b600080fd5b6100ab6100a6366004610ac4565b6101a8565b604080516001600160a01b0390941684526020840192909252908201526060015b60405180910390f35b6100dd60c881565b6040519081526020016100cc565b6100dd7f000000000000000000000000000000000000000000000000000000000000000081565b6100dd610120366004610aff565b610660565b6100dd6714d1120d7b16000081565b6100ab610142366004610ac4565b610677565b61016e7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100cc565b6100dd670de0b6b3a764000081565b6100dd6101a3366004610b2b565b61099f565b600080600080876001600160a01b031663ae9187546040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102109190610b4d565b905060008790506000826001600160a01b0316634d6228316040518163ffffffff1660e01b8152600401602060405180830381865afa158015610257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027b9190610b4d565b905060008a6001600160a01b031663794e57246040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e19190610b6a565b90505b6001600160a01b0382161580159061036d5750604051630d293c7160e41b81526001600160a01b038381166004830152602482018b90528291908d169063d293c71090604401602060405180830381865afa158015610347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061036b9190610b6a565b105b156103e357604051632dc9c0eb60e21b81526001600160a01b03838116600483015285169063b72703ac90602401602060405180830381865afa1580156103b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103dc9190610b4d565b91506102e4565b819650876000036103f45760001997505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663969c24526040518163ffffffff1660e01b8152600401602060405180830381865afa158015610454573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104789190610b6a565b90505b6001600160a01b038316158015906104935750600084115b80156104aa57506000896104a681610b99565b9a50115b1561064557604051632e46be5f60e21b81526001600160a01b03848116600483015260009182918f169063b91af97c90602401608060405180830381865afa1580156104fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051e9190610bb0565b505091509150600061052f836109b4565b9050868111156105c357838111156105bb576000610556886105518785610be6565b6109e0565b905060008e61056d670de0b6b3a764000084610bf9565b6105779190610c26565b6105819085610be6565b9050600061058f8385610be6565b9050600061059c826109f6565b90506105a88382610a22565b9d506105b4848c610be6565b9a50505050505b505050610645565b6105cd8188610be6565b604051632dc9c0eb60e21b81526001600160a01b0388811660048301529198509089169063b72703ac90602401602060405180830381865afa158015610617573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063b9190610b4d565b955050505061047b565b61064f848c610be6565b955050505050509450945094915050565b600061066d848484610a58565b90505b9392505050565b600080600080876001600160a01b031663ae9187546040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106df9190610b4d565b90506000886001600160a01b03166349eefeee6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610721573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107459190610b6a565b90508060000361076057600080879450945094505050610995565b816001600160a01b0316634d6228316040518163ffffffff1660e01b8152600401602060405180830381865afa15801561079e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c29190610b4d565b60405163b0d8e18160e01b81526001600160a01b03808316600483015291965061083b918a91908c169063b0d8e18190602401602060405180830381865afa158015610812573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108369190610b6a565b610a89565b935085925060015b878110156109915760408051602081018690520160408051601f1981840301815291905280516020909101209350600061087d8386610c3a565b604051633669c91160e21b8152600481018290529091506000906001600160a01b038d169063d9a7244490602401602060405180830381865afa1580156108c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ec9190610b4d565b60405163b0d8e18160e01b81526001600160a01b0380831660048301529192506000918e169063b0d8e18190602401602060405180830381865afa158015610938573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095c9190610b6a565b9050600061096a828e610a89565b90508881101561097b578098508299505b8461098581610c4e565b95505050505050610843565b5050505b9450945094915050565b60006109ab8383610a22565b90505b92915050565b60006109ae7f000000000000000000000000000000000000000000000000000000000000000083610be6565b60008183106109ef57816109ab565b5090919050565b60006109ae7f000000000000000000000000000000000000000000000000000000000000000083610c67565b60008115610a4f5781610a3e68056bc75e2d6310000085610bf9565b610a489190610c26565b90506109ae565b506000196109ae565b60008215610a8057600083610a6d8487610bf9565b610a779190610c26565b91506106709050565b50600019610670565b600081831015610aa257610a9d8383610be6565b6109ab565b6109ab8284610be6565b6001600160a01b0381168114610ac157600080fd5b50565b60008060008060808587031215610ada57600080fd5b8435610ae581610aac565b966020860135965060408601359560600135945092505050565b600080600060608486031215610b1457600080fd5b505081359360208301359350604090920135919050565b60008060408385031215610b3e57600080fd5b50508035926020909101359150565b600060208284031215610b5f57600080fd5b815161067081610aac565b600060208284031215610b7c57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600081610ba857610ba8610b83565b506000190190565b60008060008060808587031215610bc657600080fd5b505082516020840151604085015160609095015191969095509092509050565b818103818111156109ae576109ae610b83565b80820281158282048414176109ae576109ae610b83565b634e487b7160e01b600052601260045260246000fd5b600082610c3557610c35610c10565b500490565b600082610c4957610c49610c10565b500690565b600060018201610c6057610c60610b83565b5060010190565b808201808211156109ae576109ae610b8356fea2646970667358221220505806aec1aac1dc78e43c12b7fadf3a11c9f780ce1fb75def454af2c9fe6fb564736f6c6343000813003300000000000000000000000072c590349535ad52e6953744cb2a36b40954271900000000000000000000000000000000000000000000000ad78ebc5ac6200000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100935760003560e01c80635733d58f116100665780635733d58f14610125578063701526b41461013457806377553ad414610147578063a20baee614610186578063c394a7fa1461019557600080fd5b8063301be459146100985780634870dd9a146100d55780634ba4a28b146100eb578063525acdbb14610112575b600080fd5b6100ab6100a6366004610ac4565b6101a8565b604080516001600160a01b0390941684526020840192909252908201526060015b60405180910390f35b6100dd60c881565b6040519081526020016100cc565b6100dd7f00000000000000000000000000000000000000000000000ad78ebc5ac620000081565b6100dd610120366004610aff565b610660565b6100dd6714d1120d7b16000081565b6100ab610142366004610ac4565b610677565b61016e7f00000000000000000000000072c590349535ad52e6953744cb2a36b40954271981565b6040516001600160a01b0390911681526020016100cc565b6100dd670de0b6b3a764000081565b6100dd6101a3366004610b2b565b61099f565b600080600080876001600160a01b031663ae9187546040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102109190610b4d565b905060008790506000826001600160a01b0316634d6228316040518163ffffffff1660e01b8152600401602060405180830381865afa158015610257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027b9190610b4d565b905060008a6001600160a01b031663794e57246040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e19190610b6a565b90505b6001600160a01b0382161580159061036d5750604051630d293c7160e41b81526001600160a01b038381166004830152602482018b90528291908d169063d293c71090604401602060405180830381865afa158015610347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061036b9190610b6a565b105b156103e357604051632dc9c0eb60e21b81526001600160a01b03838116600483015285169063b72703ac90602401602060405180830381865afa1580156103b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103dc9190610b4d565b91506102e4565b819650876000036103f45760001997505b60007f00000000000000000000000072c590349535ad52e6953744cb2a36b4095427196001600160a01b031663969c24526040518163ffffffff1660e01b8152600401602060405180830381865afa158015610454573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104789190610b6a565b90505b6001600160a01b038316158015906104935750600084115b80156104aa57506000896104a681610b99565b9a50115b1561064557604051632e46be5f60e21b81526001600160a01b03848116600483015260009182918f169063b91af97c90602401608060405180830381865afa1580156104fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051e9190610bb0565b505091509150600061052f836109b4565b9050868111156105c357838111156105bb576000610556886105518785610be6565b6109e0565b905060008e61056d670de0b6b3a764000084610bf9565b6105779190610c26565b6105819085610be6565b9050600061058f8385610be6565b9050600061059c826109f6565b90506105a88382610a22565b9d506105b4848c610be6565b9a50505050505b505050610645565b6105cd8188610be6565b604051632dc9c0eb60e21b81526001600160a01b0388811660048301529198509089169063b72703ac90602401602060405180830381865afa158015610617573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063b9190610b4d565b955050505061047b565b61064f848c610be6565b955050505050509450945094915050565b600061066d848484610a58565b90505b9392505050565b600080600080876001600160a01b031663ae9187546040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106df9190610b4d565b90506000886001600160a01b03166349eefeee6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610721573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107459190610b6a565b90508060000361076057600080879450945094505050610995565b816001600160a01b0316634d6228316040518163ffffffff1660e01b8152600401602060405180830381865afa15801561079e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c29190610b4d565b60405163b0d8e18160e01b81526001600160a01b03808316600483015291965061083b918a91908c169063b0d8e18190602401602060405180830381865afa158015610812573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108369190610b6a565b610a89565b935085925060015b878110156109915760408051602081018690520160408051601f1981840301815291905280516020909101209350600061087d8386610c3a565b604051633669c91160e21b8152600481018290529091506000906001600160a01b038d169063d9a7244490602401602060405180830381865afa1580156108c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ec9190610b4d565b60405163b0d8e18160e01b81526001600160a01b0380831660048301529192506000918e169063b0d8e18190602401602060405180830381865afa158015610938573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095c9190610b6a565b9050600061096a828e610a89565b90508881101561097b578098508299505b8461098581610c4e565b95505050505050610843565b5050505b9450945094915050565b60006109ab8383610a22565b90505b92915050565b60006109ae7f00000000000000000000000000000000000000000000000ad78ebc5ac620000083610be6565b60008183106109ef57816109ab565b5090919050565b60006109ae7f00000000000000000000000000000000000000000000000ad78ebc5ac620000083610c67565b60008115610a4f5781610a3e68056bc75e2d6310000085610bf9565b610a489190610c26565b90506109ae565b506000196109ae565b60008215610a8057600083610a6d8487610bf9565b610a779190610c26565b91506106709050565b50600019610670565b600081831015610aa257610a9d8383610be6565b6109ab565b6109ab8284610be6565b6001600160a01b0381168114610ac157600080fd5b50565b60008060008060808587031215610ada57600080fd5b8435610ae581610aac565b966020860135965060408601359560600135945092505050565b600080600060608486031215610b1457600080fd5b505081359360208301359350604090920135919050565b60008060408385031215610b3e57600080fd5b50508035926020909101359150565b600060208284031215610b5f57600080fd5b815161067081610aac565b600060208284031215610b7c57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600081610ba857610ba8610b83565b506000190190565b60008060008060808587031215610bc657600080fd5b505082516020840151604085015160609095015191969095509092509050565b818103818111156109ae576109ae610b83565b80820281158282048414176109ae576109ae610b83565b634e487b7160e01b600052601260045260246000fd5b600082610c3557610c35610c10565b500490565b600082610c4957610c49610c10565b500690565b600060018201610c6057610c60610b83565b5060010190565b808201808211156109ae576109ae610b8356fea2646970667358221220505806aec1aac1dc78e43c12b7fadf3a11c9f780ce1fb75def454af2c9fe6fb564736f6c63430008130033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000072c590349535ad52e6953744cb2a36b40954271900000000000000000000000000000000000000000000000ad78ebc5ac6200000

-----Decoded View---------------
Arg [0] : _borrowerOperationsAddress (address): 0x72c590349535AD52e6953744cb2A36B409542719
Arg [1] : _gasCompensation (uint256): 200000000000000000000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000072c590349535ad52e6953744cb2a36b409542719
Arg [1] : 00000000000000000000000000000000000000000000000ad78ebc5ac6200000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.