HYPE Price: $37.19 (-3.64%)

Contract

0xb22f7B5d5724B1a454d6811456C85491C1BB249b
Transaction Hash
Method
Block
From
To
Withdraw78209112025-07-08 1:51:081 hr ago1751939468IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000043210.11
Deposit78109142025-07-07 23:07:154 hrs ago1751929635IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000025980.1
Deposit78056372025-07-07 21:40:455 hrs ago1751924445IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000121730.79
Deposit78035122025-07-07 21:05:556 hrs ago1751922355IN
0xb22f7B5d...1C1BB249b
0 HYPE0.0061921518.27705854
Deposit78012122025-07-07 20:28:126 hrs ago1751920092IN
0xb22f7B5d...1C1BB249b
0 HYPE0.00002040.13242385
Deposit77999162025-07-07 20:06:587 hrs ago1751918818IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000049310.32
Withdraw77986252025-07-07 19:45:487 hrs ago1751917548IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000067170.2243784
Deposit77982952025-07-07 19:40:237 hrs ago1751917223IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000031180.12
Withdraw77978812025-07-07 19:33:367 hrs ago1751916816IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000021070.12
Withdraw77941352025-07-07 18:32:118 hrs ago1751913131IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000685445
Withdraw77894652025-07-07 17:15:389 hrs ago1751908538IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000016640.10500271
Deposit77894122025-07-07 17:14:4610 hrs ago1751908486IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000015880.1
Deposit77893922025-07-07 17:14:2610 hrs ago1751908466IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000016190.10195907
Withdraw77851942025-07-07 16:05:3711 hrs ago1751904337IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000039170.1
Withdraw77828642025-07-07 15:27:2511 hrs ago1751902045IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000022820.13
Deposit77809872025-07-07 14:56:3912 hrs ago1751900199IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000040210.13
Deposit77720352025-07-07 12:29:5414 hrs ago1751891394IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000018490.12
Withdraw77712582025-07-07 12:17:0914 hrs ago1751890629IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000052670.3
Deposit77702572025-07-07 12:00:4515 hrs ago1751889645IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000028580.11
Deposit77692352025-07-07 11:44:0015 hrs ago1751888640IN
0xb22f7B5d...1C1BB249b
0 HYPE0.00002910.11
Deposit77688122025-07-07 11:37:0315 hrs ago1751888223IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000028580.11
Deposit77662012025-07-07 10:54:1516 hrs ago1751885655IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000027780.1
Deposit77593922025-07-07 9:02:3818 hrs ago1751878958IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000013880.1
Deposit77593862025-07-07 9:02:3218 hrs ago1751878952IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000013880.1
Deposit77593822025-07-07 9:02:2818 hrs ago1751878948IN
0xb22f7B5d...1C1BB249b
0 HYPE0.000025980.1
View all transactions

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

Contract Source Code Verified (Exact Match)

Contract Name:
StabilityPool

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;

import "./dependencies/IERC20.sol";
import "./interfaces/IStabilityPool.sol";
import "./dependencies/VaultMath.sol";
import "./interfaces/IVaultManager.sol";
import "./AddressBook.sol";

import "forge-std/console.sol";

contract StabilityPool is AddressBook, IStabilityPool {

    // Tracker for debtToken held in the pool. Changes when users deposit/withdraw, and when Vessel debt is offset.
    uint256 public totalDebtTokenDeposits;
    address[] public validCollaterals;
    mapping(address => uint256) public deposits; // depositor address -> deposit amount

    /*
     * that tracks P, S, G, scale, and epoch.
     * depositor's snapshot is updated only when they
     * deposit or withdraw from stability pool
     * depositSnapshots are used to allocate GRVT rewards, calculate compoundedDepositAmount
     * and to calculate how much Collateral amount the depositor is entitled to
     */
    mapping(address => Snapshots) public depositSnapshots; // depositor address -> snapshots struct

    /*  Product 'P': Running product by which to multiply an initial deposit, in order to find the current compounded deposit,
     * after a series of liquidations have occurred, each of which cancel some debt tokens debt with the deposit.
     *
     * During its lifetime, a deposit's value evolves from d_t to d_t * P / P_t , where P_t
     * is the snapshot of P taken at the instant the deposit was made. 18-digit decimal.
     */
    uint256 public P = 1e18;
    uint256 public constant SCALE_FACTOR = 1e9;

    // Each time the scale of P shifts by SCALE_FACTOR, the scale is incremented by 1
    uint128 public currentScale;

    // With each offset that fully empties the Pool, the epoch is incremented by 1
    uint128 public currentEpoch;

    /* Collateral amount Gain sum 'S': During its lifetime, each deposit d_t earns an Collateral amount gain of ( d_t * [S - S_t] )/P_t,
     * where S_t is the depositor's snapshot of S taken at the time t when the deposit was made.
     *
     * The 'S' sums are stored in a nested mapping (epoch => scale => sum):
     *
     * - The inner mapping records the (scale => sum)
     * - The middle mapping records (epoch => (scale => sum))
     * - The outer mapping records (collateralType => (epoch => (scale => sum)))
     */
    mapping(address => mapping(uint128 => mapping(uint128 => uint256))) public epochToScaleToSum;

    /*
     * Similarly, the sum 'G' is used to calculate GRVT gains. During it's lifetime, each deposit d_t earns a GRVT gain of
     *  ( d_t * [G - G_t] )/P_t, where G_t is the depositor's snapshot of G taken at time t when  the deposit was made.
     *
     *  GRVT reward events occur are triggered by depositor operations (new deposit, topup, withdrawal), and liquidations.
     *  In each case, the GRVT reward is issued (i.e. G is updated), before other state changes are made.
     */
    mapping(uint128 => mapping(uint128 => uint256)) public epochToScaleToG;

    // Error trackers for the error correction in the offset calculation
    uint256[] public lastAssetError_Offset;
    uint256 public lastDebtTokenLossError_Offset;

    /**
     * @notice add a collateral
     * @dev should be called anytime a collateral is added to controller
     * keeps all arrays the correct length
     * @param _collateral address of collateral to add
     */
    function addCollateralType(address _collateral) external onlyOwner {
        lastAssetError_Offset.push(0);
        validCollaterals.push(_collateral);
    }

    /**
     * @notice getter function
     * @dev gets total debtToken from deposits
     * @return totalDebtTokenDeposits
     */
    function getTotalDebtTokenDeposits() external view override returns (uint256) {
        return totalDebtTokenDeposits;
    }

    // --- External Depositor Functions ---

    /**
     * @notice Used to provide debt tokens to the stability Pool
     * @param _amount amount of debtToken provided
     * @param _assets an array of collaterals to be claimed. 
     * Skipping a collateral forfeits the available rewards (can be useful for gas optimizations)
     */
    function deposit(uint256 _amount, address[] calldata _assets) external {
        require(_amount != 0, "StabilityPool: Amount must be non-zero");

        uint256 initialDeposit = deposits[msg.sender];
        (address[] memory gainAssets, uint256[] memory gainAmounts) = getDepositorGains(msg.sender, _assets);
        uint256 compoundedDeposit = getCompoundedDebtTokenDeposits(msg.sender);
        uint256 loss = initialDeposit - compoundedDeposit; // Needed only for event log
        uint256 newTotalDeposits = totalDebtTokenDeposits + _amount;
        uint256 newDeposit = compoundedDeposit + _amount;
        totalDebtTokenDeposits = newTotalDeposits;

        _updateDepositAndSnapshots(msg.sender, newDeposit);
        _sendGainsToDepositor(msg.sender, gainAssets, gainAmounts); // send any collateral gains accrued to the depositor

        IERC20(debtToken).transferFrom(msg.sender, address(this), _amount);

        emit StabilityPoolDebtTokenBalanceUpdated(newTotalDeposits);
        emit UserDepositChanged(msg.sender, newDeposit);
        emit GainsWithdrawn(msg.sender, gainAssets, gainAmounts, loss); // loss required for event log
    }
    /** 
    * @param _amount amount of debtToken to withdraw
    * @param _assets an array of collaterals to be claimed.
    */

    function withdraw(uint256 _amount, address[] calldata _assets) external {
        (address[] memory assets, uint256[] memory amounts) = _withdrawFromSP(_amount, _assets);
        _sendGainsToDepositor(msg.sender, assets, amounts);

        emit UserWithdrawal(msg.sender, _amount);
    }

    /**
     * @notice withdraw from the stability pool
     * @param _amount debtToken amount to withdraw
     * @param _assets an array of collaterals to be claimed. 
     * @return assets address of assets withdrawn, amount of asset withdrawn
     */
    function _withdrawFromSP(
        uint256 _amount,
        address[] calldata _assets
    ) internal returns (address[] memory assets, uint256[] memory amounts) {
        uint256 initialDeposit = deposits[msg.sender];
        require(initialDeposit != 0, "StabilityPool: User must have a non-zero deposit");

        (assets, amounts) = getDepositorGains(msg.sender, _assets);

        uint256 compoundedDeposit = getCompoundedDebtTokenDeposits(msg.sender);
        uint256 debtTokensToWithdraw = VaultMath._min(_amount, compoundedDeposit);
        uint256 loss = initialDeposit - compoundedDeposit; // Needed only for event log

        _sendToDepositor(msg.sender, debtTokensToWithdraw);

        // Update deposit
        uint256 newDeposit = compoundedDeposit - debtTokensToWithdraw;
        _updateDepositAndSnapshots(msg.sender, newDeposit);

        emit UserDepositChanged(msg.sender, newDeposit);
        emit GainsWithdrawn(msg.sender, assets, amounts, loss); // loss required for event log
    }

    // --- Liquidation functions ---

    /**
     * @notice sets the offset for liquidation
     * @dev Cancels out the specified debt against the debtTokens contained in the Stability Pool (as far as possible)
     * and transfers the Vessel's collateral from ActivePool to StabilityPool.
     * Only called by liquidation functions in the VesselManager.
     * @param _debtToOffset how much debt to offset
     * @param _asset token address
     * @param _amountAdded token amount as uint256
     */
    function offsetDebt(uint256 _debtToOffset, address _asset, uint256 _amountAdded) external onlyVaultOperations {
        uint256 cachedTotalDebtTokenDeposits = totalDebtTokenDeposits; // cached to save an SLOAD

        if (cachedTotalDebtTokenDeposits == 0 || _debtToOffset == 0) {
            return;
        }
        
        (uint256 collGainPerUnitStaked, uint256 debtLossPerUnitStaked) = _computeRewardsPerUnitStaked(
            _asset,
            _amountAdded,
            _debtToOffset,
            cachedTotalDebtTokenDeposits
        );

        _updateRewardSumAndProduct(_asset, collGainPerUnitStaked, debtLossPerUnitStaked); // updates S and P
        _decreaseDebtTokens(_debtToOffset);

        IERC20(debtToken).burn(address(this), _debtToOffset);
        IERC20(_asset).transferFrom(msg.sender, address(this), _amountAdded);
    }

    // --- Offset helper functions ---

    /**
     * @notice Compute the debtToken and Collateral amount rewards. Uses a "feedback" error correction, to keep
     * the cumulative error in the P and S state variables low:
     *
     * @dev 1) Form numerators which compensate for the floor division errors that occurred the last time this
     * function was called.
     * 2) Calculate "per-unit-staked" ratios.
     * 3) Multiply each ratio back by its denominator, to reveal the current floor division error.
     * 4) Store these errors for use in the next correction when this function is called.
     * 5) Note: static analysis tools complain about this "division before multiplication", however, it is intended.
     * @param _asset Address of token
     * @param _amountAdded amount as uint256
     * @param _debtToOffset amount of debt to offset
     * @param _totalDeposits How much user has deposited
     */
    function _computeRewardsPerUnitStaked(
        address _asset,
        uint256 _amountAdded,
        uint256 _debtToOffset,
        uint256 _totalDeposits
    ) internal returns (uint256 collGainPerUnitStaked, uint256 debtLossPerUnitStaked) {
        uint256 assetIndex = IVaultManager(vaultManager).getIndex(_asset);
        uint256 collateralNumerator = (_amountAdded * VaultMath.DECIMAL_PRECISION) + lastAssetError_Offset[assetIndex];
        require(_debtToOffset <= _totalDeposits, "StabilityPool: Debt is larger than totalDeposits");
        if (_debtToOffset == _totalDeposits) {
            debtLossPerUnitStaked = VaultMath.DECIMAL_PRECISION; // When the Pool depletes to 0, so does each deposit
            lastDebtTokenLossError_Offset = 0;
        } else {
            uint256 lossNumerator = (_debtToOffset * VaultMath.DECIMAL_PRECISION) - lastDebtTokenLossError_Offset;
            /*
             * Add 1 to make error in quotient positive. We want "slightly too much" loss,
             * which ensures the error in any given compoundedDeposit favors the Stability Pool.
             */
            debtLossPerUnitStaked = (lossNumerator / _totalDeposits) + 1;
            lastDebtTokenLossError_Offset = (debtLossPerUnitStaked * _totalDeposits) - lossNumerator;
        }
        collGainPerUnitStaked = collateralNumerator / _totalDeposits;
        lastAssetError_Offset[assetIndex] = collateralNumerator - (collGainPerUnitStaked * _totalDeposits);
    }

    function _updateRewardSumAndProduct(
        address _asset,
        uint256 _collGainPerUnitStaked,
        uint256 _debtLossPerUnitStaked
    ) internal {
        require(_debtLossPerUnitStaked <= VaultMath.DECIMAL_PRECISION, "StabilityPool: Loss < 1");
        uint256 currentP = P;
        uint256 newP;

        /*
         * The newProductFactor is the factor by which to change all deposits, due to the depletion of Stability Pool debt tokens in the liquidation.
         * We make the product factor 0 if there was a pool-emptying. Otherwise, it is (1 - _debtLossPerUnitStaked)
         */
        uint256 newProductFactor = VaultMath.DECIMAL_PRECISION - _debtLossPerUnitStaked;
        uint128 currentScaleCached = currentScale;
        uint128 currentEpochCached = currentEpoch;
        uint256 currentS = epochToScaleToSum[_asset][currentEpochCached][currentScaleCached];

        /*
         * Calculate the new S first, before we update P.
         * The asset gain for any given depositor from a liquidation depends on the value of their deposit
         * (and the value of totalDeposits) prior to the Stability being depleted by the debt in the liquidation.
         *
         * Since S corresponds to asset gain, and P to deposit loss, we update S first.
         */
        uint256 marginalAssetGain = _collGainPerUnitStaked * currentP;
        uint256 newS = currentS + marginalAssetGain;
        epochToScaleToSum[_asset][currentEpochCached][currentScaleCached] = newS;
        emit S_Updated(_asset, newS, currentEpochCached, currentScaleCached);

        // If the Stability Pool was emptied, increment the epoch, and reset the scale and product P
        if (newProductFactor == 0) {
            currentEpochCached += 1;
            currentEpoch = currentEpochCached;
            emit EpochUpdated(currentEpochCached);
            currentScale = 0;
            emit ScaleUpdated(0);
            newP = VaultMath.DECIMAL_PRECISION;

            // If multiplying P by a non-zero product factor would reduce P below the scale boundary, increment the scale
        } else {
            uint256 mulCached = currentP * newProductFactor;
            uint256 mulDivCached = mulCached / VaultMath.DECIMAL_PRECISION;

            if (mulDivCached < SCALE_FACTOR) {
                newP = (mulCached * SCALE_FACTOR) / VaultMath.DECIMAL_PRECISION;
                currentScaleCached += 1;
                currentScale = currentScaleCached;
                emit ScaleUpdated(currentScaleCached);
            } else {
                newP = mulDivCached;
            }
        }

        require(newP != 0, "StabilityPool: P = 0");
        P = newP;
        emit P_Updated(newP);
    }

    function _decreaseDebtTokens(uint256 _amount) internal {
        uint256 newTotalDeposits = totalDebtTokenDeposits - _amount;
        totalDebtTokenDeposits = newTotalDeposits;
        emit StabilityPoolDebtTokenBalanceUpdated(newTotalDeposits);
    }

    // --- Reward calculator functions for depositor ---

    /**
     * @notice Calculates the gains earned by the deposit since its last snapshots were taken for selected assets.
     * @dev Given by the formula:  E = d0 * (S - S(0))/P(0)
     * where S(0) and P(0) are the depositor's snapshots of the sum S and product P, respectively.
     * d0 is the last recorded deposit value.
     * @param _depositor address of depositor in question
     * @param _assets array of assets to check gains for
     * @return assets, amounts
     */
    function getDepositorGains(
        address _depositor,
        address[] memory _assets
    ) public view returns (address[] memory, uint256[] memory) {
        uint256 initialDeposit = deposits[_depositor];

        if (initialDeposit == 0) {
            address[] memory emptyAddress = new address[](0);
            uint256[] memory emptyUint = new uint256[](0);
            return (emptyAddress, emptyUint);
        }

        Snapshots storage snapshots = depositSnapshots[_depositor];

        uint256[] memory amountsFromNewGains = _calculateNewGains(initialDeposit, snapshots, _assets);
        return (_assets, amountsFromNewGains);
    }

    /**
     * @notice get gains on each possible asset by looping through
     * @dev assets with _getGainFromSnapshots function
     * @param initialDeposit Amount of initial deposit
     * @param snapshots struct snapshots
     * @param _assets ascending ordered array of assets to calculate and claim gains
     */
    function _calculateNewGains(
        uint256 initialDeposit,
        Snapshots storage snapshots,
        address[] memory _assets
    ) internal view returns (uint256[] memory amounts) {
        uint256 assetsLen = _assets.length;
        // asset list must be on ascending order - used to avoid any repeated elements
        unchecked {
            for (uint256 i = 1; i < assetsLen; i++) {
                if (_assets[i] <= _assets[i-1]) {
                    revert StabilityPool__ArrayNotInAscendingOrder();
                }
            }
        }
        amounts = new uint256[](assetsLen);
        for (uint256 i = 0; i < assetsLen; ) {
            amounts[i] = _getGainFromSnapshots(initialDeposit, snapshots, _assets[i]);
            unchecked {
                i++;
            }
        }
    }

    /**
     * @notice gets the gain in S for a given asset
     * @dev for a user who deposited initialDeposit
     * @param initialDeposit Amount of initialDeposit
     * @param snapshots struct snapshots
     * @param asset asset to gain snapshot
     * @return uint256 the gain
     */
    function _getGainFromSnapshots(
        uint256 initialDeposit,
        Snapshots storage snapshots,
        address asset
    ) internal view returns (uint256) {
        /*
         * Grab the sum 'S' from the epoch at which the stake was made. The Collateral amount gain may span up to one scale change.
         * If it does, the second portion of the Collateral amount gain is scaled by 1e9.
         * If the gain spans no scale change, the second portion will be 0.
         */
        uint256 S_Snapshot = snapshots.S[asset];
        uint256 P_Snapshot = snapshots.P;

        mapping(uint128 => uint256) storage scaleToSum = epochToScaleToSum[asset][snapshots.epoch];
        uint256 firstPortion = scaleToSum[snapshots.scale] - S_Snapshot;
        uint256 secondPortion = scaleToSum[snapshots.scale + 1] / SCALE_FACTOR;

        uint256 assetGain = (initialDeposit * (firstPortion + secondPortion)) / P_Snapshot / VaultMath.DECIMAL_PRECISION;

        return assetGain;
    }

    // --- Compounded deposit and compounded System stake ---

    /*
     * Return the user's compounded deposit. Given by the formula:  d = d0 * P/P(0)
     * where P(0) is the depositor's snapshot of the product P, taken when they last updated their deposit.
     */
    function getCompoundedDebtTokenDeposits(address _depositor) public view override returns (uint256) {
        uint256 initialDeposit = deposits[_depositor];
        if (initialDeposit == 0) {
            return 0;
        }

        return _getCompoundedStakeFromSnapshots(initialDeposit, depositSnapshots[_depositor]);
    }

    // Internal function, used to calculate compounded deposits and compounded stakes.
    function _getCompoundedStakeFromSnapshots(
        uint256 initialStake,
        Snapshots storage snapshots
    ) internal view returns (uint256) {
        uint256 snapshot_P = snapshots.P;
        uint128 scaleSnapshot = snapshots.scale;
        uint128 epochSnapshot = snapshots.epoch;

        // If stake was made before a pool-emptying event, then it has been fully cancelled with debt -- so, return 0
        if (epochSnapshot < currentEpoch) {
            return 0;
        }

        uint256 compoundedStake;
        uint128 scaleDiff = currentScale - scaleSnapshot;

        /* Compute the compounded stake. If a scale change in P was made during the stake's lifetime,
         * account for it. If more than one scale change was made, then the stake has decreased by a factor of
         * at least 1e-9 -- so return 0.
         */
        if (scaleDiff == 0) {
            compoundedStake = (initialStake * P) / snapshot_P;
        } else if (scaleDiff == 1) {
            compoundedStake = (initialStake * P) / snapshot_P / SCALE_FACTOR;
        } else {
            compoundedStake = 0;
        }

        /*
         * If compounded deposit is less than a billionth of the initial deposit, return 0.
         *
         * NOTE: originally, this line was in place to stop rounding errors making the deposit too large. However, the error
         * corrections should ensure the error in P "favors the Pool", i.e. any given compounded deposit should slightly less
         * than it's theoretical value.
         *
         * Thus it's unclear whether this line is still really needed.
         */
        if (compoundedStake < initialStake / 1e9) {
            return 0;
        }

        return compoundedStake;
    }

    /**
     * @notice transfer collateral gains to the depositor
     * @dev this function also unwraps wrapped assets
     * before sending to depositor
     * @param _to address
     * @param assets array of address
     * @param amounts array of uint256. Includes pending collaterals since that was added in previous steps
     */
    function _sendGainsToDepositor(address _to, address[] memory assets, uint256[] memory amounts) internal {
        uint256 assetsLen = assets.length;
        require(assetsLen == amounts.length, "StabilityPool: Length mismatch");
        for (uint256 i = 0; i < assetsLen; ) {
            uint256 amount = amounts[i];
            if (amount == 0) {
                unchecked {
                    i++;
                }
                continue;
            }
            address asset = assets[i];
            // Assumes we're internally working only with the wrapped version of ERC20 tokens
            IERC20(asset).transfer(_to, amount);
            unchecked {
                i++;
            }
        }
    }

    // Send debt tokens to user and decrease deposits in Pool
    function _sendToDepositor(address _depositor, uint256 debtTokenWithdrawal) internal {
        if (debtTokenWithdrawal == 0) {
            return;
        }

        IERC20(debtToken).transfer(_depositor, debtTokenWithdrawal);
        _decreaseDebtTokens(debtTokenWithdrawal);
    }

    // --- Stability Pool Deposit Functionality ---

    /**
     * @notice updates deposit and snapshots internally
     * @dev if _newValue is zero, delete snapshot for given _depositor and emit event
     * otherwise, add an entry or update existing entry for _depositor in the depositSnapshots
     * with current values for P, S, G, scale and epoch and then emit event.
     * @param _depositor address
     * @param _newValue uint256
     */
    function _updateDepositAndSnapshots(address _depositor, uint256 _newValue) internal {
        deposits[_depositor] = _newValue;
        address[] memory colls = getValidCollateral();
        uint256 collsLen = colls.length;

        Snapshots storage depositorSnapshots = depositSnapshots[_depositor];
        if (_newValue == 0) {
            for (uint256 i = 0; i < collsLen; ) {
                depositSnapshots[_depositor].S[colls[i]] = 0;
                unchecked {
                    i++;
                }
            }
            depositorSnapshots.P = 0;
            depositorSnapshots.G = 0;
            depositorSnapshots.epoch = 0;
            depositorSnapshots.scale = 0;
            emit DepositSnapshotUpdated(_depositor, 0, 0);
            return;
        }
        uint128 currentScaleCached = currentScale;
        uint128 currentEpochCached = currentEpoch;
        uint256 currentP = P;

        for (uint256 i = 0; i < collsLen; ) {
            address asset = colls[i];
            uint256 currentS = epochToScaleToSum[asset][currentEpochCached][currentScaleCached];
            depositSnapshots[_depositor].S[asset] = currentS;
            unchecked {
                i++;
            }
        }

        uint256 currentG = epochToScaleToG[currentEpochCached][currentScaleCached];
        depositorSnapshots.P = currentP;
        depositorSnapshots.G = currentG;
        depositorSnapshots.scale = currentScaleCached;
        depositorSnapshots.epoch = currentEpochCached;

        emit DepositSnapshotUpdated(_depositor, currentP, currentG);
    }

    function getValidCollateral() public view returns(address[] memory) {
        return validCollaterals;
    }

    function S(address _depositor, address _asset) external view returns (uint256) {
        return depositSnapshots[_depositor].S[_asset];
    }
}

File 2 of 9 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

library console {
    address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

    function _sendLogPayload(bytes memory payload) private view {
        uint256 payloadLength = payload.length;
        address consoleAddress = CONSOLE_ADDRESS;
        /// @solidity memory-safe-assembly
        assembly {
            let payloadStart := add(payload, 32)
            let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
        }
    }

    function log() internal view {
        _sendLogPayload(abi.encodeWithSignature("log()"));
    }

    function logInt(int p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(int)", p0));
    }

    function logUint(uint p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
    }

    function logString(string memory p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
    }

    function logBool(bool p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
    }

    function logAddress(address p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
    }

    function logBytes(bytes memory p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
    }

    function logBytes1(bytes1 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
    }

    function logBytes2(bytes2 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
    }

    function logBytes3(bytes3 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
    }

    function logBytes4(bytes4 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
    }

    function logBytes5(bytes5 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
    }

    function logBytes6(bytes6 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
    }

    function logBytes7(bytes7 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
    }

    function logBytes8(bytes8 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
    }

    function logBytes9(bytes9 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
    }

    function logBytes10(bytes10 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
    }

    function logBytes11(bytes11 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
    }

    function logBytes12(bytes12 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
    }

    function logBytes13(bytes13 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
    }

    function logBytes14(bytes14 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
    }

    function logBytes15(bytes15 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
    }

    function logBytes16(bytes16 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
    }

    function logBytes17(bytes17 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
    }

    function logBytes18(bytes18 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
    }

    function logBytes19(bytes19 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
    }

    function logBytes20(bytes20 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
    }

    function logBytes21(bytes21 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
    }

    function logBytes22(bytes22 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
    }

    function logBytes23(bytes23 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
    }

    function logBytes24(bytes24 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
    }

    function logBytes25(bytes25 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
    }

    function logBytes26(bytes26 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
    }

    function logBytes27(bytes27 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
    }

    function logBytes28(bytes28 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
    }

    function logBytes29(bytes29 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
    }

    function logBytes30(bytes30 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
    }

    function logBytes31(bytes31 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
    }

    function logBytes32(bytes32 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
    }

    function log(uint p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
    }

    function log(string memory p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
    }

    function log(bool p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
    }

    function log(address p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
    }

    function log(uint p0, uint p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
    }

    function log(uint p0, string memory p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
    }

    function log(uint p0, bool p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
    }

    function log(uint p0, address p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
    }

    function log(string memory p0, uint p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
    }

    function log(string memory p0, string memory p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
    }

    function log(string memory p0, bool p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
    }

    function log(string memory p0, address p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
    }

    function log(bool p0, uint p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
    }

    function log(bool p0, string memory p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
    }

    function log(bool p0, bool p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
    }

    function log(bool p0, address p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
    }

    function log(address p0, uint p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
    }

    function log(address p0, string memory p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
    }

    function log(address p0, bool p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
    }

    function log(address p0, address p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
    }

    function log(uint p0, uint p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
    }

    function log(uint p0, uint p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
    }

    function log(uint p0, uint p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
    }

    function log(uint p0, uint p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
    }

    function log(uint p0, string memory p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
    }

    function log(uint p0, string memory p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
    }

    function log(uint p0, string memory p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
    }

    function log(uint p0, string memory p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
    }

    function log(uint p0, bool p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
    }

    function log(uint p0, bool p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
    }

    function log(uint p0, bool p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
    }

    function log(uint p0, bool p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
    }

    function log(uint p0, address p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
    }

    function log(uint p0, address p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
    }

    function log(uint p0, address p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
    }

    function log(uint p0, address p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
    }

    function log(string memory p0, uint p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
    }

    function log(string memory p0, uint p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
    }

    function log(string memory p0, uint p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
    }

    function log(string memory p0, uint p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
    }

    function log(string memory p0, address p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
    }

    function log(string memory p0, address p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
    }

    function log(string memory p0, address p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
    }

    function log(string memory p0, address p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
    }

    function log(bool p0, uint p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
    }

    function log(bool p0, uint p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
    }

    function log(bool p0, uint p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
    }

    function log(bool p0, uint p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
    }

    function log(bool p0, bool p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
    }

    function log(bool p0, bool p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
    }

    function log(bool p0, bool p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
    }

    function log(bool p0, bool p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
    }

    function log(bool p0, address p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
    }

    function log(bool p0, address p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
    }

    function log(bool p0, address p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
    }

    function log(bool p0, address p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
    }

    function log(address p0, uint p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
    }

    function log(address p0, uint p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
    }

    function log(address p0, uint p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
    }

    function log(address p0, uint p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
    }

    function log(address p0, string memory p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
    }

    function log(address p0, string memory p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
    }

    function log(address p0, string memory p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
    }

    function log(address p0, string memory p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
    }

    function log(address p0, bool p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
    }

    function log(address p0, bool p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
    }

    function log(address p0, bool p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
    }

    function log(address p0, bool p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
    }

    function log(address p0, address p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
    }

    function log(address p0, address p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
    }

    function log(address p0, address p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
    }

    function log(address p0, address p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
    }

    function log(uint p0, uint p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
    }

}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./dependencies/Ownable.sol";
import "./dependencies/VaultMath.sol";

contract AddressBook is Ownable {
    address public debtToken;
    address public priceFeed;
    address public vaultSorter;
    address public stabilityPool;
    address public vaultManager;
    address public vaultOperations;
    address public keikoDeployer;
    
    bool public isAddressSetupInitialized;
    bool public canUpdatePriceFeed;

    event PriceFeedUpdated(address oldPriceFeed, address newPriceFeed);
    event PriceFeedUpdateabilityRenounced();

    function setAddresses(address[] calldata _addresses) external onlyOwner {
        require(!isAddressSetupInitialized, "Setup is already initialized");
        require(_addresses.length == 6, "Invalid addresses length"); // Changed from 7 to 6
        
        debtToken = _addresses[0];
        priceFeed = _addresses[1];
        vaultSorter = _addresses[2];
        stabilityPool = _addresses[3];
        vaultManager = _addresses[4];
        vaultOperations = _addresses[5];
        keikoDeployer = msg.sender;

        isAddressSetupInitialized = true;
        canUpdatePriceFeed = true;  // Enable price feed updates by default
    }

    function updatePriceFeed(address _newPriceFeed) external onlyOwner {
        require(_newPriceFeed != address(0), "Invalid price feed address");
        require(isAddressSetupInitialized, "Setup not initialized");
        require(canUpdatePriceFeed, "Price feed updates are renounced");
        
        address oldPriceFeed = priceFeed;
        priceFeed = _newPriceFeed;
        
        emit PriceFeedUpdated(oldPriceFeed, _newPriceFeed);
    }

    function renouncePriceFeedUpdateability() external onlyOwner {
        require(canUpdatePriceFeed, "Already renounced");
        canUpdatePriceFeed = false;
        emit PriceFeedUpdateabilityRenounced();
    }

    modifier onlyVaultOperations() {
        require(msg.sender == vaultOperations, "Only callable by VaultOperations");
        _;
    }

    modifier onlyVaultManager() {
        require(msg.sender == vaultManager, "Only callable by VaultManager");
        _;
    }

    modifier onlyStabilityPool() {
        require(msg.sender == stabilityPool, "Only callable by SP");
        _;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.19;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.19;

interface IERC20 {

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
    function burn(address from, uint256 amount) external;
    function mint(address to, uint256 amount) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.19;

import "./Context.sol";

abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

library VaultMath {
	uint256 internal constant DECIMAL_PRECISION = 1 ether;
	uint256 internal constant EXPONENT_CAP = 525_600_000;

	/*
	 * _decPow: Exponentiation function for 18-digit decimal base, and integer exponent n.
	 *
	 * Uses the efficient "exponentiation by squaring" algorithm. O(log(n)) complexity.
	 *
	 *
	 * 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) external pure returns (uint256) {
		if (_minutes > EXPONENT_CAP) {
			_minutes = EXPONENT_CAP;
		} // 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 _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;
	}
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;

interface IStabilityPool {
    // --- Structs ---

    struct Snapshots {
        mapping(address => uint256) S;
        uint256 P;
        uint256 G;
        uint128 scale;
        uint128 epoch;
    }

    // --- Events ---

    event DepositSnapshotUpdated(address indexed _depositor, uint256 _P, uint256 _G);
    event SystemSnapshotUpdated(uint256 _P, uint256 _G);

    event AssetSent(address _asset, address _to, uint256 _amount);
    event GainsWithdrawn(address indexed _depositor, address[] _collaterals, uint256[] _amounts, uint256 _debtTokenLoss);
    event StabilityPoolAssetBalanceUpdated(address _asset, uint256 _newBalance);
    event StabilityPoolDebtTokenBalanceUpdated(uint256 _newBalance);
    event StakeChanged(uint256 _newSystemStake, address _depositor);
    event UserDepositChanged(address indexed _depositor, uint256 _newDeposit);
    event UserWithdrawal(address indexed _user, uint256 _amount);

    event P_Updated(uint256 _P);
    event S_Updated(address _asset, uint256 _S, uint128 _epoch, uint128 _scale);
    event G_Updated(uint256 _G, uint128 _epoch, uint128 _scale);
    event EpochUpdated(uint128 _currentEpoch);
    event ScaleUpdated(uint128 _currentScale);

    // --- Errors ---

    error StabilityPool__ActivePoolOnly(address sender, address expected);
    error StabilityPool__AdminContractOnly(address sender, address expected);
    error StabilityPool__VesselManagerOnly(address sender, address expected);
    error StabilityPool__ArrayNotInAscendingOrder();

    // --- Functions ---

    function addCollateralType(address _collateral) external;

    /*
     * Initial checks:
     * - _amount is not zero
     * - Sends depositor's accumulated gains (GRVT, assets) to depositor
     */
    function deposit(uint256 _amount, address[] calldata _assets) external;

    /*
     * Initial checks:
     * - _amount is zero or there are no under collateralized vessels left in the system
     * - User has a non zero deposit
     * ---
     * - Decreases deposit's stake, and takes new snapshots.
     *
     * If _amount > userDeposit, the user withdraws all of their compounded deposit.
     */
    function withdraw(uint256 _amount, address[] calldata _assets) external;

    /*
    Initial checks:
     * - Caller is VesselManager
     * ---
     * Cancels out the specified debt against the debt token contained in the Stability Pool (as far as possible)
     * and transfers the Vessel's collateral from ActivePool to StabilityPool.
     * Only called by liquidation functions in the VesselManager.
     */
    function offsetDebt(uint256 _debt, address _asset, uint256 _coll) external;

    /*
     * Returns debt tokens held in the pool. Changes when users deposit/withdraw, and when Vessel debt is offset.
     */
    function getTotalDebtTokenDeposits() external view returns (uint256);

    /*
     * Calculates the asset gains earned by the deposit since its last snapshots were taken.
     */
    function getDepositorGains(
        address _depositor,
        address[] calldata _assets
    ) external view returns (address[] memory, uint256[] memory);

    /*
     * Return the user's compounded deposits.
     */
    function getCompoundedDebtTokenDeposits(address _depositor) external view returns (uint256);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

interface IVaultManager {
    // Events
    event CollateralAdded(address indexed collateral);
    event MinRangeUpdated(address _collateral, uint256 _mcr);
    event MCRFactorSet(address _collateral, uint256 _mcrFactor);
    event BaseFeeSet(address _collateral, uint256 _baseFee);
    event MaxFeeSet(address _collateral, uint256 _maxFee);
    event MaxRangeSet(address _collateral, uint256 _maxRange);
    event RedemptionFeeSet(uint256 _fee);
    event IsActiveSet(address indexed _collateral, bool _active);
    event MinNetDebtChanged(uint256 oldMinNetDebt, uint256 newMinNetDebt);
    event MintCapChanged(uint256 oldMintCap, uint256 newMintCap);
    event LiquidationPenaltyChanged(uint256 oldPenalty, uint256 newPenalty);
    event CollateralParamsSet(address indexed _collateral, uint256 mcr, uint256 maxRange, uint256 baseFee, uint256 minNetDebt, uint256 mintCap, uint256 liquidationPenalty);

    // Default Paramaters
    function MIN_NET_DEBT_DEFAULT() external view returns (uint256);
    function MINT_CAP_DEFAULT() external view returns (uint256);
    function MIN_CR_RANGE() external view returns (uint256);
    function MAX_CR_RANGE() external view returns (uint256);
    function MCR_FACTOR() external view returns (uint256);
    function LIQUIDATION_PENALTY() external view returns (uint256);
    function MAX_FEE() external view returns (uint256);
    function BASE_FEE() external view returns (uint256);
    function REDEMPTION_FEE() external view returns (uint256);

    // Functions
    function validCollateral(uint256) external view returns (address);
    function adjustVaultData(address vaultCollateral, address vaultOwner, uint256 collateralAmount, uint256 debtAmount, uint256 mcr) external;
    function getVaultData(address vaultCollateral, address vaultOwner) external view returns (uint256, uint256, uint256);
    function getVaultInterestRate(address vaultCollateral, address vaultOwner) external view returns (uint256);
    function isAddressValid(address _address) external view returns (bool);
    function checkVaultState(address vaultCollateral, address vaultOwner) external view returns (bool);

    function calculateCR(address vaultCollateral, address vaultOwner) external view returns (uint256);
    function calculateARS(address vaultCollateral, address vaultOwner) external returns (uint256);

    function getMinNetDebt(address _collateral) external view returns (uint256);
    function getIsActive(address _collateral) external view returns (bool);
    function getDecimals(address _collateral) external view returns (uint256);
    function getMinRange(address _collateral) external view returns (uint256);
    function getMCRFactor(address _collateral) external view returns (uint256);
    function getBaseFee(address _collateral) external view returns (uint256);
    function getMaxRange(address _collateral) external view returns (uint256);
    function getMaxFee(address _collateral) external view returns (uint256);
    function getMintCap(address _collateral) external view returns (uint256);
    function getLiquidationPenalty(address _collateral) external view returns (uint256);
    function getIndex(address _collateral) external view returns (uint256);
    function getValidCollateral() external view returns (address[] memory);
    function getRedemptionFee() external view returns (uint256);
}

Settings
{
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "appendCBOR": false,
    "bytecodeHash": "none",
    "useLiteralContent": false
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/"
  ],
  "viaIR": true
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"expected","type":"address"}],"name":"StabilityPool__ActivePoolOnly","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"expected","type":"address"}],"name":"StabilityPool__AdminContractOnly","type":"error"},{"inputs":[],"name":"StabilityPool__ArrayNotInAscendingOrder","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"expected","type":"address"}],"name":"StabilityPool__VesselManagerOnly","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"AssetSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"_P","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_G","type":"uint256"}],"name":"DepositSnapshotUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"_currentEpoch","type":"uint128"}],"name":"EpochUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_G","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"_epoch","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"_scale","type":"uint128"}],"name":"G_Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_depositor","type":"address"},{"indexed":false,"internalType":"address[]","name":"_collaterals","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"_debtTokenLoss","type":"uint256"}],"name":"GainsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_P","type":"uint256"}],"name":"P_Updated","type":"event"},{"anonymous":false,"inputs":[],"name":"PriceFeedUpdateabilityRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPriceFeed","type":"address"},{"indexed":false,"internalType":"address","name":"newPriceFeed","type":"address"}],"name":"PriceFeedUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_S","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"_epoch","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"_scale","type":"uint128"}],"name":"S_Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"_currentScale","type":"uint128"}],"name":"ScaleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_newBalance","type":"uint256"}],"name":"StabilityPoolAssetBalanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newBalance","type":"uint256"}],"name":"StabilityPoolDebtTokenBalanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newSystemStake","type":"uint256"},{"indexed":false,"internalType":"address","name":"_depositor","type":"address"}],"name":"StakeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_P","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_G","type":"uint256"}],"name":"SystemSnapshotUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"_newDeposit","type":"uint256"}],"name":"UserDepositChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"UserWithdrawal","type":"event"},{"inputs":[],"name":"P","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"},{"internalType":"address","name":"_asset","type":"address"}],"name":"S","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"}],"name":"addCollateralType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"canUpdatePriceFeed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentScale","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"depositSnapshots","outputs":[{"internalType":"uint256","name":"P","type":"uint256"},{"internalType":"uint256","name":"G","type":"uint256"},{"internalType":"uint128","name":"scale","type":"uint128"},{"internalType":"uint128","name":"epoch","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"}],"name":"epochToScaleToG","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"}],"name":"epochToScaleToSum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"getCompoundedDebtTokenDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"},{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"getDepositorGains","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDebtTokenDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidCollateral","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isAddressSetupInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keikoDeployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastAssetError_Offset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastDebtTokenLossError_Offset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debtToOffset","type":"uint256"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amountAdded","type":"uint256"}],"name":"offsetDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renouncePriceFeedUpdateability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stabilityPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebtTokenDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPriceFeed","type":"address"}],"name":"updatePriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"validCollaterals","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultOperations","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultSorter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608080604052346100675760008054336001600160a01b0319821681178355916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3670de0b6b3a7640000600c556120cd908161006d8239f35b600080fdfe608060408181526004918236101561001657600080fd5b600092833560e01c918263048c661d14611130575081630a68f2d7146111115781630d9a6b3514611111578163121f2b26146110e457816313afb188146110a35781633178fe3f146110035781634e8338eb14610fba57816359caa99614610f34578163715018a614610ed6578163741bef1a14610ead5781637667180814610e8b5781637ee4196b14610e1b57816382e0a57414610dcf578163841f0ebb14610da657816385d7cf8614610bc157816386da082414610b5e5781638a4adf2414610b355781638b8fbd9214610b165781638da5cb5b14610aee57816395877f78146109895781639718cf591461096057816399eca69f146107ed5781639d6aea0a14610758578163a4e59ac814610730578163a4f9255b14610709578163a7a48884146106ea578163ad3018f014610668578163b95717211461044c578163be35d3bd14610410578163c8564c62146103e9578163ce4b5bbe146103ca578163ea8db462146103a1578163ec0d5e0c146102de578163f2fde38b1461021357508063f8d89898146101eb5763fc7e286d146101b157600080fd5b346101e75760203660031901126101e75760209181906001600160a01b036101d7611154565b168152600a845220549051908152f35b5080fd5b50346101e757816003193601126101e75760015490516001600160a01b039091168152602090f35b9050346102da5760203660031901126102da5761022e611154565b83546001600160a01b038082169391926102493386146113bf565b169384156102885750506001600160a01b031916821783557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b906020608492519162461bcd60e51b8352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152fd5b8280fd5b8390346101e75760203660031901126101e7576102f9611154565b82546001600160a01b03929061031290841633146113bf565b6010549068010000000000000000918281101561038e5780600161033992016010556111d2565b8154906000199060031b1b191690556009549182101561037b57508060016103649201600955611185565b90928084549260031b9316831b921b191617905580f35b634e487b7160e01b855260419052602484fd5b634e487b7160e01b865260418252602486fd5b5050346101e757816003193601126101e75760075490516001600160a01b039091168152602090f35b5050346101e757816003193601126101e75760209051633b9aca008152f35b5050346101e757816003193601126101e75760209060ff60075460a01c1690519015158152f35b9050346102da5760203660031901126102da573591601054831015610449575061043b6020926111d2565b91905490519160031b1c8152f35b80fd5b919050346102da5760203660031901126102da57813567ffffffffffffffff81116106645761047e903690840161121f565b845490936001600160a01b03929161049990841633146113bf565b6007549460ff8660a01c1661062157600681036105de5780156105b857836104c08461140a565b16946bffffffffffffffffffffffff60a01b9586600154161760015581600110156105cb57846104f26020860161140a565b1686600254161760025581600210156105cb576105118591850161140a565b1685600354161760035580600310156105b857836105316060850161140a565b1685835416178255808210156105b8578361054e6080850161140a565b16856005541617600555600510156105a5575060a061056d910161140a565b6006805490931691161790556001600160a81b0319163360ff60a01b191617600160a01b1760ff60a81b1916600160a81b1760075580f35b634e487b7160e01b865260329052602485fd5b634e487b7160e01b875260328252602487fd5b634e487b7160e01b885260328352602488fd5b845162461bcd60e51b8152602081840152601860248201527f496e76616c696420616464726573736573206c656e67746800000000000000006044820152606490fd5b845162461bcd60e51b8152602081840152601c60248201527f536574757020697320616c726561647920696e697469616c697a6564000000006044820152606490fd5b8380fd5b9050346102da57816003193601126102da57610682611154565b926024359067ffffffffffffffff821161044957366023830112156104495750926106bc6106c2928560246106e69736930135910161132d565b90611a91565b6106d88394929451948486958652850190611284565b90838203602085015261138b565b0390f35b5050346101e757816003193601126101e7576020906011549051908152f35b5050346101e757816003193601126101e75760209060ff60075460a81c1690519015158152f35b5050346101e757816003193601126101e7576020906001600160801b03600d54169051908152f35b5050346101e757816003193601126101e75780519081809360095490818552602080950191600982527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af915b868282106107cd5785906106e6886107be848903856112f3565b51928284938452830190611284565b83546001600160a01b0316855288955090930192600192830192016107a4565b919050346102da576107fe36611250565b338652600a602052838620549294831561090457506108266108cc939261082c92369161132d565b33611a91565b9161085d61083933611c5b565b91828810156108f95761084d83899261141e565b926108588233611e60565b61141e565b6108678133611ee5565b85519081527fbce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c960203392a27ff20651f7c9cd4e1c112f77cbf2a13a44f79d4165dd781c41b52052bfc888174a8551806108c33394878784611466565b0390a233611d42565b519081527fc7c8ab309277169a63ed070feed2a9c7de84e71be9d50f6f06c898458562561c60203392a280f35b61084d83809261141e565b608490602086519162461bcd60e51b8352820152603060248201527f53746162696c697479506f6f6c3a2055736572206d757374206861766520612060448201526f1b9bdb8b5e995c9bc819195c1bdcda5d60821b6064820152fd5b5050346101e757816003193601126101e75760065490516001600160a01b039091168152602090f35b8383346101e757602092836003193601126102da576109a6611154565b83546001600160a01b03929183916109c190831633146113bf565b16908115610aab5760075460ff8160a01c1615610a705760a81c60ff1615610a2f57507fa8abe0398416476db5b05737cd4da3b3cbde5012d978a6a6c3fd49d321753536939460025492826bffffffffffffffffffffffff60a01b851617600255845193168352820152a180f35b606490868086519262461bcd60e51b845283015260248201527f507269636520666565642075706461746573206172652072656e6f756e6365646044820152fd5b845162461bcd60e51b8152808301889052601560248201527414d95d1d5c081b9bdd081a5b9a5d1a585b1a5e9959605a1b6044820152606490fd5b835162461bcd60e51b8152908101869052601a60248201527f496e76616c6964207072696365206665656420616464726573730000000000006044820152606490fd5b5050346101e757816003193601126101e757905490516001600160a01b039091168152602090f35b5050346101e757816003193601126101e757602090600c549051908152f35b5050346101e757816003193601126101e75760055490516001600160a01b039091168152602090f35b5050346101e75760203660031901126101e75760809181906001600160a01b03610b86611154565b168152600b602052206001810154916003600283015492015491815193845260208401526001600160801b03821690830152821c6060820152f35b9050346102da57610bd136611250565b928215610d5457338652610bf4610826602093600a85528789205496369161132d565b929094610c7f82610c0e610c0733611c5b565b809461141e565b96610c2581610c1f81600854611441565b95611441565b9584600855610c348733611ee5565b610c3f888b33611d42565b6001548b516323b872dd60e01b8152339281019283523060208401526040830193909352919384926001600160a01b03169183918e918391606090910190565b03925af18015610d4a57927f8c9268469ff6265448f46f8119962e815f393b25b87bb55bda5e709a412b85d781610d1796947fbce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c9947ff20651f7c9cd4e1c112f77cbf2a13a44f79d4165dd781c41b52052bfc888174a9b9c97610d1d575b508651908152a183519283523392a251928392339684611466565b0390a280f35b610d3c90833d8511610d43575b610d3481836112f3565b81019061144e565b5038610cfc565b503d610d2a565b88513d8b823e3d90fd5b608490602086519162461bcd60e51b8352820152602660248201527f53746162696c697479506f6f6c3a20416d6f756e74206d757374206265206e6f6044820152656e2d7a65726f60d01b6064820152fd5b5050346101e757816003193601126101e75760035490516001600160a01b039091168152602090f35b9050346102da57816003193601126102da57356001600160801b0380821680920361066457928291602094610e02611209565b918352600f865283832091168252845220549051908152f35b5050346101e75760603660031901126101e757610e36611154565b610e3e611209565b604435916001600160801b0390818416809403610e87576001600160a01b03168552600e6020908152848620919092168552815282842091845290815291819020549051908152f35b8580fd5b5050346101e757816003193601126101e757602090600d5460801c9051908152f35b5050346101e757816003193601126101e75760025490516001600160a01b039091168152602090f35b8334610449578060031936011261044957805481906001600160a01b03811690610f013383146113bf565b6001600160a01b03191682557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b919050346102da5760603660031901126102da57610f5061116f565b6006549091906001600160a01b03163303610f78575090610f75916044359135611494565b80f35b5162461bcd60e51b8152602081840181905260248201527f4f6e6c792063616c6c61626c65206279205661756c744f7065726174696f6e736044820152606490fd5b5050346101e757806003193601126101e75780602092610fd8611154565b610fe061116f565b6001600160a01b039182168352600b865283832091168252845220549051908152f35b9050346102da57826003193601126102da5761102960018060a01b0384541633146113bf565b6007549160ff8360a81c161561106c57505060ff60a81b19166007557fe089be21ed139679e3a679d4042319a859a3225e8edbd0c5d6ba087a4b7b2a0c8180a180f35b906020606492519162461bcd60e51b83528201526011602482015270105b1c9958591e481c995b9bdd5b98d959607a1b6044820152fd5b9050346102da5760203660031901126102da57359160095483101561044957506110ce602092611185565b905491519160018060a01b039160031b1c168152f35b5050346101e75760203660031901126101e75760209061110a611105611154565b611c5b565b9051908152f35b5050346101e757816003193601126101e7576020906008549051908152f35b8491346102da57826003193601126102da57546001600160a01b0316815260209150f35b600435906001600160a01b038216820361116a57565b600080fd5b602435906001600160a01b038216820361116a57565b6009548110156111bc5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b634e487b7160e01b600052603260045260246000fd5b6010548110156111bc5760106000527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720190600090565b602435906001600160801b038216820361116a57565b9181601f8401121561116a5782359167ffffffffffffffff831161116a576020808501948460051b01011161116a57565b90604060031983011261116a57600435916024359067ffffffffffffffff821161116a576112809160040161121f565b9091565b90815180825260208080930193019160005b8281106112a4575050505090565b83516001600160a01b031685529381019392810192600101611296565b6020810190811067ffffffffffffffff8211176112dd57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176112dd57604052565b67ffffffffffffffff81116112dd5760051b60200190565b929161133882611315565b9161134660405193846112f3565b829481845260208094019160051b810192831161116a57905b82821061136c5750505050565b81356001600160a01b038116810361116a57815290830190830161135f565b90815180825260208080930193019160005b8281106113ab575050505090565b83518552938101939281019260010161139d565b156113c657565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b356001600160a01b038116810361116a5790565b9190820391821161142b57565b634e487b7160e01b600052601160045260246000fd5b9190820180921161142b57565b9081602091031261116a5751801515810361116a5790565b93929161148f90611481604093606088526060880190611284565b90868203602088015261138b565b930152565b6008549260009084158015611a02575b6119fb5760018060a01b039485600554166040948786518099819963b31610db60e01b83521694600494868684015260209b8c9160249c8d915afa9182156119f15788926119be575b50670de0b6b3a76400009182880288810484148915171561188f5761152290611515836111d2565b90549060031b1c90611441565b90828611611962578583036119005761155e61155885938c6011555b61155261154b8783611a1d565b9687611a0a565b9061141e565b916111d2565b819291549060031b91821b91600019901b19161790558281116118be57600c5490808403928484116118ac578b938e936115fd937fe799d8213ffd47c58af0bad222f3f83a7bacf689130d897017d6c2cb9346e8cb60808f958e908a600d548b6001600160801b039d8e83169b8c93881c9d8e96888352600e8552838320888452855283832086845285526115f78d8585205492611a0a565b90611441565b938493888352600e8152838320888452815283832091835252205581519384528b840152820152866060820152a18703611811575050509061165f7fb50f0f59e7cb5b421dc77581c3a9919e3806e076e5fa78a874c3f120cb7d874d92611a3d565b928b519084168152a16001600160801b03199060801b16600d557f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe8a8951898152a15b80156117d85789817fc1a9618cb59ebca77cbdbc2949f126823c407ff13edb285fd0262519a9c18e8c92600c558951908152a16116de82611a55565b6001541690813b15610e87578651632770a7eb60e21b815230848201908152602081019290925291869183919082908490829060400103925af180156117ce57908894939291611792575b5085516323b872dd60e01b815233918101918252306020830152604082019390935291955085918290859082906060015b03925af191821561178857505061176f575050565b8161178592903d10610d4357610d3481836112f3565b50565b51903d90823e3d90fd5b919350949567ffffffffffffffff82959395116117bd57509185949391879361175a97529338611729565b634e487b7160e01b83526041865282fd5b86513d87823e3d90fd5b875162461bcd60e51b81528085018b90526014818b015273053746162696c697479506f6f6c3a2050203d20360641b6044820152606490fd5b90919593506118209250611a0a565b633b9aca0090828104828110156118a1575081810291818304149015171561188f57916118718d927f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe940494611a3d565b16806001600160801b0319600d541617600d558a51908152a16116a2565b634e487b7160e01b8a52601187528b8afd5b9450505050506116a2565b634e487b7160e01b8b52601188528c8bfd5b895162461bcd60e51b81528087018d90526017818d01527f53746162696c697479506f6f6c3a204c6f7373203c20310000000000000000006044820152606490fd5b8386028681048514871517156118ac5760115461191c9161141e565b916119278484611a1d565b92600184018094116119505761155e91611948611558926108588888611a0a565b60115561153e565b634e487b7160e01b8c52601189528d8cfd5b50895162461bcd60e51b81528087018d90526030818d01527f53746162696c697479506f6f6c3a2044656274206973206c617267657220746860448201526f616e20746f74616c4465706f7369747360801b6064820152608490fd5b9091508a81813d83116119ea575b6119d681836112f3565b810103126119e6575190386114ed565b8780fd5b503d6119cc565b89513d8a823e3d90fd5b5050505050565b5082156114a4565b8181029291811591840414171561142b57565b8115611a27570490565b634e487b7160e01b600052601260045260246000fd5b9060016001600160801b038093160191821161142b57565b6020611a847f8c9268469ff6265448f46f8119962e815f393b25b87bb55bda5e709a412b85d79260085461141e565b80600855604051908152a1565b919060018060a01b03809316600090808252602090600a825260409081842054908115611c1c578493929352600b825282842091855193600195865b868110611bda5750611aee99611ae287611315565b9383519b8c95866112f3565b878552601f19611afd89611315565b013682870137829189880154976003810154918c8360801c956001600160801b03809516995b8d8210611b3d575050505050505050505050505050509190565b611bcf8f93670de0b6b3a76400008f8f908f8f928f8f928f8f968f938f96633b9aca00938f9c9a611bbd97611bc39a8f611b7a90611bc89f611c47565b5116855282528484205492600e83528585209085528252611bb0611baa868620948987528585528787205461141e565b97611a3d565b1683525220540490611441565b90611a0a565b611a1d565b0492611c47565b52018f908e91611b23565b8a611be8828b999699611c47565b51168b611bf960001984018c611c47565b51161015611c0b578701959295611acd565b8251637243bc1760e11b8152600490fd5b50509250509250805190611c2f826112c1565b8382525192611c3d846112c1565b8084523681379190565b80518210156111bc5760209160051b010190565b6001600160a01b03166000908152600a60205260409020548015611c8f57600b6020526040600020611c8c91611c95565b90565b50600090565b9190916003600184015493015492600d548060801c8560801c10611d39576000906001600160801b038080971691160394808611611d2557633b9aca00939495168015600014611cfd575050611cf190611bc3600c5485611a0a565b915b048110611c8f5790565b600103611d1d5750611d168291611bc3600c5486611a0a565b0491611cf3565b905091611cf3565b634e487b7160e01b82526011600452602482fd5b50600093505050565b9080519183518303611e1b57600093845b848110611d6257505050505050565b611d6c8183611c47565b518015611e1157611dc8906001600160a01b03611d898488611c47565b516040805163a9059cbb60e01b81526001600160a01b0389166004820152602481019490945260209490928592859291169082908d9082906044820190565b03925af1908115611e085750906001939291611dea575b505001935b93611d53565b81611e0092903d10610d4357610d3481836112f3565b503880611ddf565b513d8a823e3d90fd5b5060010193611de4565b60405162461bcd60e51b815260206004820152601e60248201527f53746162696c697479506f6f6c3a204c656e677468206d69736d6174636800006044820152606490fd5b908015611ee15760015460405163a9059cbb60e01b81526001600160a01b039384166004820152602481018390529260209184916044918391600091165af1918215611ed557611eb592611eb7575b50611a55565b565b611ece9060203d8111610d4357610d3481836112f3565b5038611eaf565b6040513d6000823e3d90fd5b5050565b91909160018060a01b0380911690600090828252602091600a835260409286848320558351968788836009549283815201600986527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af92865b868282106120b557505050611f55925003896112f3565b8751868452600b93848452868120921561203657600d54946001600160801b038616928660801c91600c5498845b838110611fef57505050507fc48943df4095f4f20d171fd2872eafdc0eed4d9014ac3672f3bde7fd425449d598999a508188916003949352600f865281812083825286522054948660018501558560028501556001600160801b031916179101558351928352820152a2565b808f8d8f916120016001958792611c47565b511690818a52600e8d52808a20898b528d52808a208b8b528d52808a2054928a52868d5289209089528b528d88205501611f83565b98919389959193955b84811061208d57505050505094806003878260017fc48943df4095f4f20d171fd2872eafdc0eed4d9014ac3672f3bde7fd425449d598999a01558260028201550155825191818352820152a2565b600190898c52828852888c20846120a48388611c47565b51168d5288528b898120550161203f565b85548a1684526001958601958e955093019201611f3e56

Deployed Bytecode

0x608060408181526004918236101561001657600080fd5b600092833560e01c918263048c661d14611130575081630a68f2d7146111115781630d9a6b3514611111578163121f2b26146110e457816313afb188146110a35781633178fe3f146110035781634e8338eb14610fba57816359caa99614610f34578163715018a614610ed6578163741bef1a14610ead5781637667180814610e8b5781637ee4196b14610e1b57816382e0a57414610dcf578163841f0ebb14610da657816385d7cf8614610bc157816386da082414610b5e5781638a4adf2414610b355781638b8fbd9214610b165781638da5cb5b14610aee57816395877f78146109895781639718cf591461096057816399eca69f146107ed5781639d6aea0a14610758578163a4e59ac814610730578163a4f9255b14610709578163a7a48884146106ea578163ad3018f014610668578163b95717211461044c578163be35d3bd14610410578163c8564c62146103e9578163ce4b5bbe146103ca578163ea8db462146103a1578163ec0d5e0c146102de578163f2fde38b1461021357508063f8d89898146101eb5763fc7e286d146101b157600080fd5b346101e75760203660031901126101e75760209181906001600160a01b036101d7611154565b168152600a845220549051908152f35b5080fd5b50346101e757816003193601126101e75760015490516001600160a01b039091168152602090f35b9050346102da5760203660031901126102da5761022e611154565b83546001600160a01b038082169391926102493386146113bf565b169384156102885750506001600160a01b031916821783557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b906020608492519162461bcd60e51b8352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152fd5b8280fd5b8390346101e75760203660031901126101e7576102f9611154565b82546001600160a01b03929061031290841633146113bf565b6010549068010000000000000000918281101561038e5780600161033992016010556111d2565b8154906000199060031b1b191690556009549182101561037b57508060016103649201600955611185565b90928084549260031b9316831b921b191617905580f35b634e487b7160e01b855260419052602484fd5b634e487b7160e01b865260418252602486fd5b5050346101e757816003193601126101e75760075490516001600160a01b039091168152602090f35b5050346101e757816003193601126101e75760209051633b9aca008152f35b5050346101e757816003193601126101e75760209060ff60075460a01c1690519015158152f35b9050346102da5760203660031901126102da573591601054831015610449575061043b6020926111d2565b91905490519160031b1c8152f35b80fd5b919050346102da5760203660031901126102da57813567ffffffffffffffff81116106645761047e903690840161121f565b845490936001600160a01b03929161049990841633146113bf565b6007549460ff8660a01c1661062157600681036105de5780156105b857836104c08461140a565b16946bffffffffffffffffffffffff60a01b9586600154161760015581600110156105cb57846104f26020860161140a565b1686600254161760025581600210156105cb576105118591850161140a565b1685600354161760035580600310156105b857836105316060850161140a565b1685835416178255808210156105b8578361054e6080850161140a565b16856005541617600555600510156105a5575060a061056d910161140a565b6006805490931691161790556001600160a81b0319163360ff60a01b191617600160a01b1760ff60a81b1916600160a81b1760075580f35b634e487b7160e01b865260329052602485fd5b634e487b7160e01b875260328252602487fd5b634e487b7160e01b885260328352602488fd5b845162461bcd60e51b8152602081840152601860248201527f496e76616c696420616464726573736573206c656e67746800000000000000006044820152606490fd5b845162461bcd60e51b8152602081840152601c60248201527f536574757020697320616c726561647920696e697469616c697a6564000000006044820152606490fd5b8380fd5b9050346102da57816003193601126102da57610682611154565b926024359067ffffffffffffffff821161044957366023830112156104495750926106bc6106c2928560246106e69736930135910161132d565b90611a91565b6106d88394929451948486958652850190611284565b90838203602085015261138b565b0390f35b5050346101e757816003193601126101e7576020906011549051908152f35b5050346101e757816003193601126101e75760209060ff60075460a81c1690519015158152f35b5050346101e757816003193601126101e7576020906001600160801b03600d54169051908152f35b5050346101e757816003193601126101e75780519081809360095490818552602080950191600982527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af915b868282106107cd5785906106e6886107be848903856112f3565b51928284938452830190611284565b83546001600160a01b0316855288955090930192600192830192016107a4565b919050346102da576107fe36611250565b338652600a602052838620549294831561090457506108266108cc939261082c92369161132d565b33611a91565b9161085d61083933611c5b565b91828810156108f95761084d83899261141e565b926108588233611e60565b61141e565b6108678133611ee5565b85519081527fbce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c960203392a27ff20651f7c9cd4e1c112f77cbf2a13a44f79d4165dd781c41b52052bfc888174a8551806108c33394878784611466565b0390a233611d42565b519081527fc7c8ab309277169a63ed070feed2a9c7de84e71be9d50f6f06c898458562561c60203392a280f35b61084d83809261141e565b608490602086519162461bcd60e51b8352820152603060248201527f53746162696c697479506f6f6c3a2055736572206d757374206861766520612060448201526f1b9bdb8b5e995c9bc819195c1bdcda5d60821b6064820152fd5b5050346101e757816003193601126101e75760065490516001600160a01b039091168152602090f35b8383346101e757602092836003193601126102da576109a6611154565b83546001600160a01b03929183916109c190831633146113bf565b16908115610aab5760075460ff8160a01c1615610a705760a81c60ff1615610a2f57507fa8abe0398416476db5b05737cd4da3b3cbde5012d978a6a6c3fd49d321753536939460025492826bffffffffffffffffffffffff60a01b851617600255845193168352820152a180f35b606490868086519262461bcd60e51b845283015260248201527f507269636520666565642075706461746573206172652072656e6f756e6365646044820152fd5b845162461bcd60e51b8152808301889052601560248201527414d95d1d5c081b9bdd081a5b9a5d1a585b1a5e9959605a1b6044820152606490fd5b835162461bcd60e51b8152908101869052601a60248201527f496e76616c6964207072696365206665656420616464726573730000000000006044820152606490fd5b5050346101e757816003193601126101e757905490516001600160a01b039091168152602090f35b5050346101e757816003193601126101e757602090600c549051908152f35b5050346101e757816003193601126101e75760055490516001600160a01b039091168152602090f35b5050346101e75760203660031901126101e75760809181906001600160a01b03610b86611154565b168152600b602052206001810154916003600283015492015491815193845260208401526001600160801b03821690830152821c6060820152f35b9050346102da57610bd136611250565b928215610d5457338652610bf4610826602093600a85528789205496369161132d565b929094610c7f82610c0e610c0733611c5b565b809461141e565b96610c2581610c1f81600854611441565b95611441565b9584600855610c348733611ee5565b610c3f888b33611d42565b6001548b516323b872dd60e01b8152339281019283523060208401526040830193909352919384926001600160a01b03169183918e918391606090910190565b03925af18015610d4a57927f8c9268469ff6265448f46f8119962e815f393b25b87bb55bda5e709a412b85d781610d1796947fbce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c9947ff20651f7c9cd4e1c112f77cbf2a13a44f79d4165dd781c41b52052bfc888174a9b9c97610d1d575b508651908152a183519283523392a251928392339684611466565b0390a280f35b610d3c90833d8511610d43575b610d3481836112f3565b81019061144e565b5038610cfc565b503d610d2a565b88513d8b823e3d90fd5b608490602086519162461bcd60e51b8352820152602660248201527f53746162696c697479506f6f6c3a20416d6f756e74206d757374206265206e6f6044820152656e2d7a65726f60d01b6064820152fd5b5050346101e757816003193601126101e75760035490516001600160a01b039091168152602090f35b9050346102da57816003193601126102da57356001600160801b0380821680920361066457928291602094610e02611209565b918352600f865283832091168252845220549051908152f35b5050346101e75760603660031901126101e757610e36611154565b610e3e611209565b604435916001600160801b0390818416809403610e87576001600160a01b03168552600e6020908152848620919092168552815282842091845290815291819020549051908152f35b8580fd5b5050346101e757816003193601126101e757602090600d5460801c9051908152f35b5050346101e757816003193601126101e75760025490516001600160a01b039091168152602090f35b8334610449578060031936011261044957805481906001600160a01b03811690610f013383146113bf565b6001600160a01b03191682557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b919050346102da5760603660031901126102da57610f5061116f565b6006549091906001600160a01b03163303610f78575090610f75916044359135611494565b80f35b5162461bcd60e51b8152602081840181905260248201527f4f6e6c792063616c6c61626c65206279205661756c744f7065726174696f6e736044820152606490fd5b5050346101e757806003193601126101e75780602092610fd8611154565b610fe061116f565b6001600160a01b039182168352600b865283832091168252845220549051908152f35b9050346102da57826003193601126102da5761102960018060a01b0384541633146113bf565b6007549160ff8360a81c161561106c57505060ff60a81b19166007557fe089be21ed139679e3a679d4042319a859a3225e8edbd0c5d6ba087a4b7b2a0c8180a180f35b906020606492519162461bcd60e51b83528201526011602482015270105b1c9958591e481c995b9bdd5b98d959607a1b6044820152fd5b9050346102da5760203660031901126102da57359160095483101561044957506110ce602092611185565b905491519160018060a01b039160031b1c168152f35b5050346101e75760203660031901126101e75760209061110a611105611154565b611c5b565b9051908152f35b5050346101e757816003193601126101e7576020906008549051908152f35b8491346102da57826003193601126102da57546001600160a01b0316815260209150f35b600435906001600160a01b038216820361116a57565b600080fd5b602435906001600160a01b038216820361116a57565b6009548110156111bc5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b634e487b7160e01b600052603260045260246000fd5b6010548110156111bc5760106000527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720190600090565b602435906001600160801b038216820361116a57565b9181601f8401121561116a5782359167ffffffffffffffff831161116a576020808501948460051b01011161116a57565b90604060031983011261116a57600435916024359067ffffffffffffffff821161116a576112809160040161121f565b9091565b90815180825260208080930193019160005b8281106112a4575050505090565b83516001600160a01b031685529381019392810192600101611296565b6020810190811067ffffffffffffffff8211176112dd57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176112dd57604052565b67ffffffffffffffff81116112dd5760051b60200190565b929161133882611315565b9161134660405193846112f3565b829481845260208094019160051b810192831161116a57905b82821061136c5750505050565b81356001600160a01b038116810361116a57815290830190830161135f565b90815180825260208080930193019160005b8281106113ab575050505090565b83518552938101939281019260010161139d565b156113c657565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b356001600160a01b038116810361116a5790565b9190820391821161142b57565b634e487b7160e01b600052601160045260246000fd5b9190820180921161142b57565b9081602091031261116a5751801515810361116a5790565b93929161148f90611481604093606088526060880190611284565b90868203602088015261138b565b930152565b6008549260009084158015611a02575b6119fb5760018060a01b039485600554166040948786518099819963b31610db60e01b83521694600494868684015260209b8c9160249c8d915afa9182156119f15788926119be575b50670de0b6b3a76400009182880288810484148915171561188f5761152290611515836111d2565b90549060031b1c90611441565b90828611611962578583036119005761155e61155885938c6011555b61155261154b8783611a1d565b9687611a0a565b9061141e565b916111d2565b819291549060031b91821b91600019901b19161790558281116118be57600c5490808403928484116118ac578b938e936115fd937fe799d8213ffd47c58af0bad222f3f83a7bacf689130d897017d6c2cb9346e8cb60808f958e908a600d548b6001600160801b039d8e83169b8c93881c9d8e96888352600e8552838320888452855283832086845285526115f78d8585205492611a0a565b90611441565b938493888352600e8152838320888452815283832091835252205581519384528b840152820152866060820152a18703611811575050509061165f7fb50f0f59e7cb5b421dc77581c3a9919e3806e076e5fa78a874c3f120cb7d874d92611a3d565b928b519084168152a16001600160801b03199060801b16600d557f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe8a8951898152a15b80156117d85789817fc1a9618cb59ebca77cbdbc2949f126823c407ff13edb285fd0262519a9c18e8c92600c558951908152a16116de82611a55565b6001541690813b15610e87578651632770a7eb60e21b815230848201908152602081019290925291869183919082908490829060400103925af180156117ce57908894939291611792575b5085516323b872dd60e01b815233918101918252306020830152604082019390935291955085918290859082906060015b03925af191821561178857505061176f575050565b8161178592903d10610d4357610d3481836112f3565b50565b51903d90823e3d90fd5b919350949567ffffffffffffffff82959395116117bd57509185949391879361175a97529338611729565b634e487b7160e01b83526041865282fd5b86513d87823e3d90fd5b875162461bcd60e51b81528085018b90526014818b015273053746162696c697479506f6f6c3a2050203d20360641b6044820152606490fd5b90919593506118209250611a0a565b633b9aca0090828104828110156118a1575081810291818304149015171561188f57916118718d927f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe940494611a3d565b16806001600160801b0319600d541617600d558a51908152a16116a2565b634e487b7160e01b8a52601187528b8afd5b9450505050506116a2565b634e487b7160e01b8b52601188528c8bfd5b895162461bcd60e51b81528087018d90526017818d01527f53746162696c697479506f6f6c3a204c6f7373203c20310000000000000000006044820152606490fd5b8386028681048514871517156118ac5760115461191c9161141e565b916119278484611a1d565b92600184018094116119505761155e91611948611558926108588888611a0a565b60115561153e565b634e487b7160e01b8c52601189528d8cfd5b50895162461bcd60e51b81528087018d90526030818d01527f53746162696c697479506f6f6c3a2044656274206973206c617267657220746860448201526f616e20746f74616c4465706f7369747360801b6064820152608490fd5b9091508a81813d83116119ea575b6119d681836112f3565b810103126119e6575190386114ed565b8780fd5b503d6119cc565b89513d8a823e3d90fd5b5050505050565b5082156114a4565b8181029291811591840414171561142b57565b8115611a27570490565b634e487b7160e01b600052601260045260246000fd5b9060016001600160801b038093160191821161142b57565b6020611a847f8c9268469ff6265448f46f8119962e815f393b25b87bb55bda5e709a412b85d79260085461141e565b80600855604051908152a1565b919060018060a01b03809316600090808252602090600a825260409081842054908115611c1c578493929352600b825282842091855193600195865b868110611bda5750611aee99611ae287611315565b9383519b8c95866112f3565b878552601f19611afd89611315565b013682870137829189880154976003810154918c8360801c956001600160801b03809516995b8d8210611b3d575050505050505050505050505050509190565b611bcf8f93670de0b6b3a76400008f8f908f8f928f8f928f8f968f938f96633b9aca00938f9c9a611bbd97611bc39a8f611b7a90611bc89f611c47565b5116855282528484205492600e83528585209085528252611bb0611baa868620948987528585528787205461141e565b97611a3d565b1683525220540490611441565b90611a0a565b611a1d565b0492611c47565b52018f908e91611b23565b8a611be8828b999699611c47565b51168b611bf960001984018c611c47565b51161015611c0b578701959295611acd565b8251637243bc1760e11b8152600490fd5b50509250509250805190611c2f826112c1565b8382525192611c3d846112c1565b8084523681379190565b80518210156111bc5760209160051b010190565b6001600160a01b03166000908152600a60205260409020548015611c8f57600b6020526040600020611c8c91611c95565b90565b50600090565b9190916003600184015493015492600d548060801c8560801c10611d39576000906001600160801b038080971691160394808611611d2557633b9aca00939495168015600014611cfd575050611cf190611bc3600c5485611a0a565b915b048110611c8f5790565b600103611d1d5750611d168291611bc3600c5486611a0a565b0491611cf3565b905091611cf3565b634e487b7160e01b82526011600452602482fd5b50600093505050565b9080519183518303611e1b57600093845b848110611d6257505050505050565b611d6c8183611c47565b518015611e1157611dc8906001600160a01b03611d898488611c47565b516040805163a9059cbb60e01b81526001600160a01b0389166004820152602481019490945260209490928592859291169082908d9082906044820190565b03925af1908115611e085750906001939291611dea575b505001935b93611d53565b81611e0092903d10610d4357610d3481836112f3565b503880611ddf565b513d8a823e3d90fd5b5060010193611de4565b60405162461bcd60e51b815260206004820152601e60248201527f53746162696c697479506f6f6c3a204c656e677468206d69736d6174636800006044820152606490fd5b908015611ee15760015460405163a9059cbb60e01b81526001600160a01b039384166004820152602481018390529260209184916044918391600091165af1918215611ed557611eb592611eb7575b50611a55565b565b611ece9060203d8111610d4357610d3481836112f3565b5038611eaf565b6040513d6000823e3d90fd5b5050565b91909160018060a01b0380911690600090828252602091600a835260409286848320558351968788836009549283815201600986527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af92865b868282106120b557505050611f55925003896112f3565b8751868452600b93848452868120921561203657600d54946001600160801b038616928660801c91600c5498845b838110611fef57505050507fc48943df4095f4f20d171fd2872eafdc0eed4d9014ac3672f3bde7fd425449d598999a508188916003949352600f865281812083825286522054948660018501558560028501556001600160801b031916179101558351928352820152a2565b808f8d8f916120016001958792611c47565b511690818a52600e8d52808a20898b528d52808a208b8b528d52808a2054928a52868d5289209089528b528d88205501611f83565b98919389959193955b84811061208d57505050505094806003878260017fc48943df4095f4f20d171fd2872eafdc0eed4d9014ac3672f3bde7fd425449d598999a01558260028201550155825191818352820152a2565b600190898c52828852888c20846120a48388611c47565b51168d5288528b898120550161203f565b85548a1684526001958601958e955093019201611f3e56

Block Transaction 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
[ 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.