S Price: $0.658385 (-11.96%)

Contract

0x5eD2e91D451dCB4639D2057613Cc542C2264b28e

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Public Mint114289522025-03-03 16:14:3324 mins ago1741018473IN
0x5eD2e91D...C2264b28e
0 S0.0455662955
Public Mint114248292025-03-03 15:48:0150 mins ago1741016881IN
0x5eD2e91D...C2264b28e
0 S0.09945075105
Public Mint114243562025-03-03 15:45:0053 mins ago1741016700IN
0x5eD2e91D...C2264b28e
0 S0.0767280378.25
Public Mint114210502025-03-03 15:24:331 hr ago1741015473IN
0x5eD2e91D...C2264b28e
0 S0.089038791.25025
Public Mint114193012025-03-03 15:13:461 hr ago1741014826IN
0x5eD2e91D...C2264b28e
0 S0.0782256383.01
Public Mint114168002025-03-03 14:59:271 hr ago1741013967IN
0x5eD2e91D...C2264b28e
0 S0.0471329757.42
Public Mint114144302025-03-03 14:45:571 hr ago1741013157IN
0x5eD2e91D...C2264b28e
0 S0.0443624555
Public Mint114090122025-03-03 14:14:562 hrs ago1741011296IN
0x5eD2e91D...C2264b28e
0 S0.0467631255.01
Public Mint114002892025-03-03 13:18:173 hrs ago1741007897IN
0x5eD2e91D...C2264b28e
0 S0.0446429555
Public Mint113948682025-03-03 12:43:483 hrs ago1741005828IN
0x5eD2e91D...C2264b28e
0 S0.09894675105
Public Mint113941462025-03-03 12:38:564 hrs ago1741005536IN
0x5eD2e91D...C2264b28e
0 S0.0552797458.66071428
Public Mint113922232025-03-03 12:26:074 hrs ago1741004767IN
0x5eD2e91D...C2264b28e
0 S0.11753175150
Public Mint113889102025-03-03 12:04:454 hrs ago1741003485IN
0x5eD2e91D...C2264b28e
0 S0.09995475105
Public Mint113869392025-03-03 11:51:404 hrs ago1741002700IN
0x5eD2e91D...C2264b28e
0 S0.048001550
Public Mint113859682025-03-03 11:44:574 hrs ago1741002297IN
0x5eD2e91D...C2264b28e
0 S0.0425663155
Public Mint113858912025-03-03 11:44:264 hrs ago1741002266IN
0x5eD2e91D...C2264b28e
0 S0.0463226650.25
Public Mint113855732025-03-03 11:42:074 hrs ago1741002127IN
0x5eD2e91D...C2264b28e
0 S0.047597550
Public Mint113851702025-03-03 11:39:054 hrs ago1741001945IN
0x5eD2e91D...C2264b28e
0 S0.0430949755
Public Mint113841462025-03-03 11:31:395 hrs ago1741001499IN
0x5eD2e91D...C2264b28e
0 S0.0418911355
Public Mint113841132025-03-03 11:31:255 hrs ago1741001485IN
0x5eD2e91D...C2264b28e
0 S0.0430943155
Public Mint113841042025-03-03 11:31:215 hrs ago1741001481IN
0x5eD2e91D...C2264b28e
0 S0.0430949755
Public Mint113840782025-03-03 11:31:105 hrs ago1741001470IN
0x5eD2e91D...C2264b28e
0 S0.0451547355.01
Public Mint113840592025-03-03 11:31:015 hrs ago1741001461IN
0x5eD2e91D...C2264b28e
0 S0.0418911355
Public Mint113840372025-03-03 11:30:525 hrs ago1741001452IN
0x5eD2e91D...C2264b28e
0 S0.0430949755
Public Mint113839142025-03-03 11:29:585 hrs ago1741001398IN
0x5eD2e91D...C2264b28e
0 S0.0418911355
View all transactions

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

Contract Source Code Verified (Exact Match)

Contract Name:
Minter

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
No with 200 runs

Other Settings:
paris EvmVersion
File 1 of 33 : Minter.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {Ownable} from "./abstract/Ownable.sol";
import {ReentrancyGuard} from "./abstract/ReentrancyGuard.sol";
import {IBaseContracts} from "./interface/IBaseContracts.sol";
import {IERC20Custom} from "./interface/IERC20Custom.sol";
import {IERC20Token} from "./interface/IERC20Token.sol";
import {IERC20TokenRebase} from "./interface/IERC20TokenRebase.sol";
import {IFloor} from "./interface/IFloor.sol";
import {IMiscHelper} from "./interface/IMiscHelper.sol";
import {IPSM} from "./interface/IPSM.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20 as IERC20Safe} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/**
 * @title Minter
 * @dev Token minting controller with phased distribution
 * @notice Manages token issuance through whitelist and public phases
 */
contract Minter is Ownable, ReentrancyGuard {
    /// @notice Protocol helper contract
    /// @dev Facilitates cross-contract interactions
    IMiscHelper public helper;
    /// @notice Core protocol tokens
    IERC20Token public immutable dusx;
    IERC20TokenRebase public immutable sttx;
    IFloor public immutable floor;
    /// @notice Stablecoins and PSMs
    IERC20Custom[] public stables;
    IPSM[] public pegStabilityModules;
    /// @notice Treasury configuration
    address public immutable treasury;
    uint256 public immutable maxMintAmount;
    uint256 public constant TREASURY_ALLOCATION = 10;
    /// @notice Minting rates and state
    uint256 private constant RATES_LENGTH = 10;
    uint256[RATES_LENGTH] public rates;
    uint256 public currentRatio;
    uint256 public supplyMinted;
    bool public whitelistMintActive;
    bool public publicMintActive;
    mapping(address => bool) public whitelistedWallets;
    /// @notice Events
    event WhitelistMintEnabled();
    event PublicMintEnabled();
    event WalletWhitelisted(address indexed wallet);
    event TokensMinted(address indexed user, uint256 amount);
    /// @notice Custom errors
    error ApproveFailed();
    error EmptyArray();
    error InvalidMintAmount();
    error MintAlreadyActive();
    error MintNotActive();
    error TokenReserveIsNotLowEnough();
    error UnsupportedStablecoin();
    error WalletNotWhitelisted();
    error ZeroAddress();
    error MintAmountCalculationFailed(uint256 stableAmount, uint256 rate);
    error MaxStableRangeCalculationFailed(uint256 supply, uint256 rate);
    modifier onlyWhitelisted() {
        if (!whitelistedWallets[_msgSender()]) revert WalletNotWhitelisted();
        _;
    }

    /**
     * @notice Initializes the minting contract
     * @param baseContracts_ Base contracts instance for protocol integration
     * @param treasury_ Treasury address for fee collection
     */
    constructor(IBaseContracts baseContracts_, address treasury_) {
        _ensureNonzeroAddress(address(baseContracts_));
        _ensureNonzeroAddress(treasury_);
        // Get immutable contracts from BaseContracts
        helper = baseContracts_.helper();
        dusx = baseContracts_.dusx();
        sttx = baseContracts_.sttx();
        floor = baseContracts_.floor();
        _ensureNonzeroAddress(address(helper));
        _ensureNonzeroAddress(address(dusx));
        _ensureNonzeroAddress(address(sttx));
        _ensureNonzeroAddress(address(floor));
        // Initialize PSMs and get their stablecoins
        IPSM[] memory psms_ = new IPSM[](2);
        psms_[0] = baseContracts_.psmCircle();
        psms_[1] = baseContracts_.psmTether();
        if (address(psms_[0]) == address(0) || address(psms_[1]) == address(0))
            revert ZeroAddress();
        pegStabilityModules = psms_;
        // Get stablecoins from PSMs
        IERC20Custom[] memory stables_ = new IERC20Custom[](2);
        stables_[0] = psms_[0].stableToken(); // Circle PSM -> USDC
        stables_[1] = psms_[1].stableToken(); // Tether PSM -> USDT
        if (
            address(stables_[0]) == address(0) ||
            address(stables_[1]) == address(0)
        ) revert ZeroAddress();
        stables = stables_;
        treasury = treasury_;
        rates = [4380, 4380, 4175, 4175, 4008, 4008, 4008, 4008, 4008, 4008];
        maxMintAmount = ((73_146_000 * 25) / 10) * 10 ** sttx.decimals();
        _setupApprovals(stables, pegStabilityModules);
    }

    /**
     * @notice Adds a wallet to whitelist
     * @param wallet Address to whitelist
     */
    function addWallet(address wallet) external onlyOwner {
        whitelistedWallets[wallet] = true;
        emit WalletWhitelisted(wallet);
    }

    /**
     * @notice Adds multiple wallets to whitelist
     * @param wallets Array of addresses to whitelist
     */
    function addWalletBatch(address[] memory wallets) external onlyOwner {
        uint256 length = wallets.length;
        for (uint256 i; i < length; i++) {
            whitelistedWallets[wallets[i]] = true;
            emit WalletWhitelisted(wallets[i]);
        }
    }

    /**
     * @notice Enables whitelist minting phase
     */
    function enableWhitelistMint() external onlyOwner {
        if (whitelistMintActive) revert MintAlreadyActive();
        whitelistMintActive = true;
        emit WhitelistMintEnabled();
    }

    /**
     * @notice Enables public minting phase
     */
    function enablePublicMint() external onlyOwner {
        if (publicMintActive) revert MintAlreadyActive();
        publicMintActive = true;
        emit PublicMintEnabled();
    }

    /**
     * @notice Mints tokens during whitelist phase
     * @param stablecoin Stablecoin used for minting
     * @param stableAmount Amount of stablecoin to mint against
     */
    function whitelistMint(
        IERC20Custom stablecoin,
        uint256 stableAmount
    ) external nonReentrant onlyWhitelisted {
        if (!whitelistMintActive) revert MintNotActive();
        _mint(stablecoin, stableAmount);
    }

    /**
     * @notice Mints tokens during public phase
     * @param stablecoin Stablecoin used for minting
     * @param stableAmount Amount of stablecoin to mint against
     */
    function publicMint(
        IERC20Custom stablecoin,
        uint256 stableAmount
    ) external nonReentrant {
        if (!publicMintActive) revert MintNotActive();
        _mint(stablecoin, stableAmount);
    }

    /**
     * @notice Mints remaining token supply
     * @param stablecoin Stablecoin used for minting
     */
    function mintRemainingSupply(
        IERC20Custom stablecoin
    ) external nonReentrant {
        if (!publicMintActive) revert MintNotActive();
        if (tokenReserve() >= sttx.maxSupply() / 100)
            revert TokenReserveIsNotLowEnough();
        uint256 decimalsDifference = 10 **
            (sttx.decimals() - stablecoin.decimals());
        uint256 stableAmount = (tokenReserve() / (rates[rates.length - 1])) /
            decimalsDifference;
        _mint(stablecoin, stableAmount);
    }

    /**
     * @notice Sends accumulated DUSX to floor contract
     */
    function sendToFloorDUSX() external nonReentrant {
        _sendToFloorDUSX();
    }

    /**
     * @notice Verifies if a wallet is whitelisted
     * @param wallet Address to verify
     * @return bool Whitelist status
     */
    function verifyWallet(address wallet) external view returns (bool) {
        return whitelistedWallets[wallet];
    }

    /**
     * @notice Calculates mint amount for given stablecoin input
     * @param stablecoin Stablecoin used for calculation
     * @param stableAmount Amount of stablecoin
     * @return uint256 Calculated mint amount
     */
    function calcMintAmount(
        IERC20Custom stablecoin,
        uint256 stableAmount
    ) public view returns (uint256) {
        uint256[RATES_LENGTH] memory supplyRangeLeft;
        uint256[RATES_LENGTH] memory maxStablePerRange = [
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0)
        ];
        bool maxStablePerRangeUpdated = false;
        uint256 mintAmount = 0;
        uint256 decimalsDifference = 10 **
            (sttx.decimals() - stablecoin.decimals());
        for (uint256 i; i < RATES_LENGTH; i++) {
            supplyRangeLeft[i] = (sttx.maxSupply() / RATES_LENGTH);
            // Check for overflow in maxStablePerRange calculation
            uint256 maxStable = ((sttx.maxSupply() / RATES_LENGTH) / rates[i]) /
                decimalsDifference;
            if (maxStable == 0 && (sttx.maxSupply() / RATES_LENGTH) != 0) {
                revert MaxStableRangeCalculationFailed(
                    sttx.maxSupply() / RATES_LENGTH,
                    rates[i]
                );
            }
            maxStablePerRange[i] = maxStable;
        }
        for (uint256 i; i < RATES_LENGTH; i++) {
            if (currentRatio < ((i + 1) * 100) / RATES_LENGTH) {
                supplyRangeLeft[i] =
                    (sttx.maxSupply() / RATES_LENGTH) *
                    (i + 1) -
                    supplyMinted;
                if (!maxStablePerRangeUpdated) {
                    uint256 maxStable = (supplyRangeLeft[i] / rates[i]) /
                        decimalsDifference;
                    if (maxStable == 0 && supplyRangeLeft[i] != 0) {
                        revert MaxStableRangeCalculationFailed(
                            supplyRangeLeft[i],
                            rates[i]
                        );
                    }
                    maxStablePerRange[i] = maxStable;
                    maxStablePerRangeUpdated = true;
                }
                if (stableAmount <= maxStablePerRange[i]) {
                    uint256 amount = (stableAmount * rates[i]) *
                        decimalsDifference;
                    if (
                        amount / rates[i] / decimalsDifference != stableAmount
                    ) {
                        revert MintAmountCalculationFailed(
                            stableAmount,
                            rates[i]
                        );
                    }
                    mintAmount += amount;
                    break;
                } else {
                    uint256 amount = (maxStablePerRange[i] * rates[i]) *
                        decimalsDifference;
                    if (
                        amount / rates[i] / decimalsDifference !=
                        maxStablePerRange[i]
                    ) {
                        revert MintAmountCalculationFailed(
                            maxStablePerRange[i],
                            rates[i]
                        );
                    }
                    mintAmount += amount;
                    stableAmount -= maxStablePerRange[i];
                }
            } else {
                maxStablePerRangeUpdated = false;
            }
        }
        return mintAmount > tokenReserve() ? tokenReserve() : mintAmount;
    }

    function calcStableAmount(
        IERC20Custom stablecoin,
        uint256 mintAmount
    ) public view returns (uint256) {
        uint256[RATES_LENGTH] memory maxStablePerRange = [
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0),
            uint256(0)
        ];
        bool maxStablePerRangeUpdated = false;
        uint256 stableAmount = 0;
        uint256 decimalsDifference = 10 **
            (sttx.decimals() - stablecoin.decimals());
        for (uint256 i; i < RATES_LENGTH; i++) {
            maxStablePerRange[i] =
                ((sttx.maxSupply() / RATES_LENGTH) / rates[i]) /
                decimalsDifference;
        }
        for (uint256 i; i < RATES_LENGTH; i++) {
            if (currentRatio < ((i + 1) * 100) / RATES_LENGTH) {
                if (!maxStablePerRangeUpdated) {
                    maxStablePerRange[i] =
                        (((sttx.maxSupply() / RATES_LENGTH) *
                            (i + 1) -
                            supplyMinted) / rates[i]) /
                        decimalsDifference;
                    maxStablePerRangeUpdated = true;
                }
                if (
                    mintAmount <=
                    (maxStablePerRange[i] * rates[i]) * decimalsDifference
                ) {
                    stableAmount +=
                        mintAmount /
                        (rates[i] * decimalsDifference);
                    break;
                } else {
                    stableAmount += maxStablePerRange[i];
                    mintAmount -=
                        (maxStablePerRange[i] * rates[i]) *
                        decimalsDifference;
                }
            } else {
                maxStablePerRangeUpdated = false;
            }
        }
        return stableAmount;
    }

    function tokenReserve() public view returns (uint256) {
        return sttx.maxSupply() - supplyMinted;
    }

    function _mint(IERC20Custom stablecoin, uint256 stableAmount) private {
        if (!_checkStable(stablecoin)) revert UnsupportedStablecoin();
        uint256 toMint = calcMintAmount(stablecoin, stableAmount);
        if (toMint == 0 || toMint > tokenReserve() || toMint > maxMintAmount)
            revert InvalidMintAmount();
        uint256 floorAmount = (stableAmount * (100 - TREASURY_ALLOCATION)) /
            100;
        supplyMinted += toMint;
        currentRatio = (supplyMinted * 100) / sttx.maxSupply();
        SafeERC20.safeTransferFrom(
            IERC20Safe(address(stablecoin)),
            _msgSender(),
            address(this),
            stableAmount
        );
        IERC20TokenRebase(address(sttx)).rebase();
        IERC20TokenRebase(address(sttx)).mint(_msgSender(), toMint);
        uint256 length = stables.length;
        for (uint256 i; i < length; i++) {
            if (stablecoin == stables[i]) {
                helper.psmSwapStableForDUSX(
                    pegStabilityModules[i],
                    address(this),
                    floorAmount
                );
                break;
            }
        }
        SafeERC20.safeTransfer(
            IERC20Safe(address(stablecoin)),
            treasury,
            stablecoin.balanceOf(address(this))
        );
        _sendToFloorDUSX();
        emit TokensMinted(_msgSender(), toMint);
    }

    function _sendToFloorDUSX() private {
        uint256 dusxBalance = dusx.balanceOf(address(this));
        if (dusxBalance > 0) {
            helper.depositFloor(dusxBalance);
        }
    }

    function _setupApprovals(
        IERC20Custom[] memory stables_,
        IPSM[] memory psms_
    ) private {
        uint256 length = stables_.length;
        for (uint256 i; i < length; i++) {
            bool successStables = stables_[i].approve(
                address(psms_[i]),
                type(uint256).max
            );
            if (!successStables) {
                revert ApproveFailed();
            }
        }
        bool successDUSX = dusx.approve(address(floor), type(uint256).max);
        if (!successDUSX) {
            revert ApproveFailed();
        }
    }

    function _checkStable(IERC20Custom stablecoin) private view returns (bool) {
        uint256 length = stables.length;
        bool found = false;
        for (uint256 i; i < length; i++) {
            if (stablecoin == stables[i]) {
                found = true;
                break;
            }
        }
        return found;
    }

    // Validates that an address is not zero
    function _ensureNonzeroAddress(address addr) private pure {
        if (addr == address(0)) {
            revert ZeroAddress();
        }
    }
}

File 2 of 33 : IERC1363.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 3 of 33 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

File 4 of 33 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 5 of 33 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

File 6 of 33 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

File 7 of 33 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 8 of 33 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title Context
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, as when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 * @notice This contract is used through inheritance. It will make available the
 * modifier `_msgSender()`, which can be used to reference the account that
 * called a function within an implementing contract.
 */
abstract contract Context {
    /*//////////////////////////////////////////////////////////////
                            INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Gets the sender of the current call
     * @dev Provides a way to retrieve the message sender that supports meta-transactions
     * @return Sender address (msg.sender in the base implementation)
     */
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @notice Gets the complete calldata of the current call
     * @dev Provides a way to retrieve the message data that supports meta-transactions
     * @return Complete calldata bytes
     */
    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    /**
     * @notice Gets the length of any context-specific suffix in the message data
     * @dev Used in meta-transaction implementations to account for additional data
     * @return Length of the context suffix (0 in the base implementation)
     */
    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 9 of 33 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {Context} from "./Context.sol";

/**
 * @title Ownable
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 * @notice By default, the owner account will be the one that deploys the contract.
 * This can later be changed with {transferOwnership} and {renounceOwnership}.
 */
abstract contract Ownable is Context {
    /*//////////////////////////////////////////////////////////////
                            STATE VARIABLES
    //////////////////////////////////////////////////////////////*/
    /// @notice Address of the current owner
    address private _owner;
    /*//////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/
    /// @notice Emitted when ownership is transferred
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
    /*//////////////////////////////////////////////////////////////
                            CUSTOM ERRORS
    //////////////////////////////////////////////////////////////*/
    /// @notice Thrown when non-owner tries to call owner-only function
    error UnauthorizedAccount(address account);
    /// @notice Thrown when trying to transfer ownership to invalid address
    error InvalidOwner(address owner);
    /*//////////////////////////////////////////////////////////////
                                MODIFIERS
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Throws if called by any account other than the owner
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /*//////////////////////////////////////////////////////////////
                            PUBLIC FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Leaves the contract without owner
     * @dev 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));
    }

    /**
     * @notice Transfers ownership of the contract to a new account
     * @dev The new owner cannot be the zero address
     * @param newOwner The address that will become the new owner
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert InvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Returns the address of the current owner
     * @return Current owner address
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /*//////////////////////////////////////////////////////////////
                            INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @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);
    }

    /**
     * @dev Throws if the sender is not the owner
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert UnauthorizedAccount(_msgSender());
        }
    }
}

File 10 of 33 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title ReentrancyGuard
 * @dev Contract module that helps prevent reentrant calls to a function
 * @notice This module is used through inheritance. It will make available the modifier
 * `nonReentrant`, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 */
abstract contract ReentrancyGuard {
    /*//////////////////////////////////////////////////////////////
                            STATE VARIABLES
    //////////////////////////////////////////////////////////////*/
    /// @notice Guard state constants
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;
    /// @notice Current state of the guard
    uint256 private _status;
    /*//////////////////////////////////////////////////////////////
                            CUSTOM ERRORS
    //////////////////////////////////////////////////////////////*/
    error ReentrantCall();
    /*//////////////////////////////////////////////////////////////
                                MODIFIERS
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    /*//////////////////////////////////////////////////////////////
                            CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Initializes the contract by setting the initial reentrancy guard state
     */
    constructor() {
        _status = NOT_ENTERED;
    }

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Checks if a protected function is currently executing
     * @return True if the contract is in the entered state
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }

    /*//////////////////////////////////////////////////////////////
                            PRIVATE FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Sets guard state before protected function execution
     * @notice Reverts if a reentrant call is detected
     */
    function _nonReentrantBefore() private {
        if (_status == ENTERED) {
            revert ReentrantCall();
        }
        _status = ENTERED;
    }

    /**
     * @dev Resets guard state after protected function execution
     */
    function _nonReentrantAfter() private {
        _status = NOT_ENTERED;
    }
}

File 11 of 33 : IBaseContracts.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IDUSXProvider} from "./IDUSXProvider.sol";
import {IERC20Token} from "./IERC20Token.sol";
import {IERC20TokenRebase} from "./IERC20TokenRebase.sol";
import {IFeesDistributor} from "./IFees.sol";
import {IFeesWithdrawer} from "./IFees.sol";
import {IFloor} from "./IFloor.sol";
import {ILenderOwner} from "./ILenderOwner.sol";
import {ILiquidationHelper} from "./ILiquidationHelper.sol";
import {IMarketLens} from "./IMarketLens.sol";
import {IMiscHelper} from "./IMiscHelper.sol";
import {IOracle} from "./IOracle.sol";
import {IPSM} from "./IPSM.sol";
import {IRepayHelper} from "./IRepayHelper.sol";
import {IStableOwner} from "./IStableOwner.sol";
import {IStakedDUSX} from "./IStakedDUSX.sol";
import {ISupplyHangingCalculator} from "./ISupplyHangingCalculator.sol";
import {IVault} from "./IVault.sol";
import {IVoteEscrowedSTTX} from "./IVoteEscrowedSTTX.sol";
import {IDynamicInterestRate} from "./IDynamicInterestRate.sol";
import {IMinter} from "./IMinter.sol";

interface IBaseContracts {
    struct CoreTokens {
        IERC20Token dusx;
        IERC20TokenRebase sttx;
        IStakedDUSX stDUSX;
        IVoteEscrowedSTTX veSTTX;
    }
    struct PSMContracts {
        IPSM psmCircle;
        IPSM psmTether;
        IStableOwner stableOwner;
    }
    struct OracleContracts {
        IOracle oracleChainlink;
        IOracle oracleFloorPrice;
    }
    struct HelperContracts {
        IMiscHelper helper;
        ILiquidationHelper liquidationHelper;
        IRepayHelper repayHelper;
        IMarketLens marketLens;
    }
    error ZeroAddress();
    error ContractAlreadySet();

    // Struct getters
    function coreTokens() external view returns (CoreTokens memory);

    function psmContracts() external view returns (PSMContracts memory);

    function oracleContracts() external view returns (OracleContracts memory);

    function helperContracts() external view returns (HelperContracts memory);

    // Individual contract getters
    function dusxProvider() external view returns (IDUSXProvider);

    function feesDistributor() external view returns (IFeesDistributor);

    function feesWithdrawer() external view returns (IFeesWithdrawer);

    function floor() external view returns (IFloor);

    function lenderOwner() external view returns (ILenderOwner);

    function minter() external view returns (IMinter);

    function supplyCalculator()
        external
        view
        returns (ISupplyHangingCalculator);

    function vault() external view returns (IVault);

    function dynamicInterestRate() external view returns (IDynamicInterestRate);

    // Convenience getters for struct members
    function dusx() external view returns (IERC20Token);

    function sttx() external view returns (IERC20TokenRebase);

    function stDUSX() external view returns (IStakedDUSX);

    function veSTTX() external view returns (IVoteEscrowedSTTX);

    function psmCircle() external view returns (IPSM);

    function psmTether() external view returns (IPSM);

    function stableOwner() external view returns (IStableOwner);

    function oracleChainlink() external view returns (IOracle);

    function oracleFloorPrice() external view returns (IOracle);

    function helper() external view returns (IMiscHelper);

    function liquidationHelper() external view returns (ILiquidationHelper);

    function repayHelper() external view returns (IRepayHelper);

    function marketLens() external view returns (IMarketLens);
}

File 12 of 33 : IDUSXProvider.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IDUSXProvider
 * @dev Interface for DUSX token provision and distribution operations
 * @notice Defines functionality for:
 * 1. Token provision management
 * 2. Supply control
 * 3. Distribution tracking
 */
interface IDUSXProvider {
    /*//////////////////////////////////////////////////////////////
                        PROVISION OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Provides DUSX tokens to the requesting address
     * @param amount The quantity of DUSX tokens to provide in base units
     * @dev Handles:
     * · Token minting/transfer
     * · Supply tracking
     * · State updates
     *
     * Requirements:
     * · Caller is authorized
     * · Amount > 0
     * · Within supply limits
     *
     * Effects:
     * · Increases recipient balance
     * · Updates total supply
     * · Emits provision event
     */
    function provide(uint256 amount) external;
}

File 13 of 33 : IDynamicInterestRate.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IDynamicInterestRate
 * @dev Interface for dynamic interest rate calculations in the lending protocol
 * @notice Defines methods for retrieving time-based interest rates that:
 * 1. Adjust based on market conditions
 * 2. Support per-second and base rate calculations
 * 3. Maintain precision through proper scaling
 *
 * This interface is crucial for:
 * · Accurate interest accrual
 * · Dynamic market response
 * · Protocol yield calculations
 */
interface IDynamicInterestRate {
    /*//////////////////////////////////////////////////////////////
                        INTEREST RATE QUERIES
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves the current interest rate per second
     * @return uint256 Interest rate per second, scaled by 1e18
     * @dev Used for precise interest calculations over time periods
     */
    function getInterestPerSecond() external view returns (uint256);

    /**
     * @notice Retrieves the current base interest rate
     * @return uint256 Base interest rate, scaled by 1e18
     * @dev Represents the foundational rate before adjustments
     */
    function getInterestRate() external view returns (uint256);
}

File 14 of 33 : IERC20Custom.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IERC20Custom
 * @dev Interface for the ERC20 fungible token standard (EIP-20)
 * @notice Defines functionality for:
 * 1. Token transfers
 * 2. Allowance management
 * 3. Balance tracking
 * 4. Token metadata
 */
interface IERC20Custom {
    /*//////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Emitted on token transfer between addresses
     * @param from Source address (0x0 for mints)
     * @param to Destination address (0x0 for burns)
     * @param value Amount of tokens transferred
     * @notice Tracks:
     * · Regular transfers
     * · Minting operations
     * · Burning operations
     */
    event Transfer(address indexed from, address indexed to, uint256 value);
    /**
     * @dev Emitted when spending allowance is granted
     * @param owner Address granting permission
     * @param spender Address receiving permission
     * @param value Amount of tokens approved
     * @notice Records:
     * · New approvals
     * · Updated allowances
     * · Revoked permissions
     */
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    /*//////////////////////////////////////////////////////////////
                        TRANSFER OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Transfers tokens to specified recipient
     * @param to Recipient address
     * @param value Amount to transfer in base units
     * @return bool True if transfer succeeds
     * @dev Requirements:
     * · Caller has sufficient balance
     * · Recipient is valid
     * · Amount > 0
     *
     * Effects:
     * · Decreases caller balance
     * · Increases recipient balance
     * · Emits Transfer event
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @notice Executes transfer on behalf of token owner
     * @param from Source address
     * @param to Destination address
     * @param value Amount to transfer in base units
     * @return bool True if transfer succeeds
     * @dev Requirements:
     * · Caller has sufficient allowance
     * · Source has sufficient balance
     * · Valid addresses
     *
     * Effects:
     * · Decreases allowance
     * · Updates balances
     * · Emits Transfer event
     */
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    /*//////////////////////////////////////////////////////////////
                        APPROVAL OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Authorizes address to spend tokens
     * @param spender Address to authorize
     * @param value Amount to authorize in base units
     * @return bool True if approval succeeds
     * @dev Controls:
     * · Spending permissions
     * · Delegation limits
     * · Authorization levels
     *
     * Security:
     * · Overwrites previous allowance
     * · Requires explicit value
     * · Emits Approval event
     */
    function approve(address spender, uint256 value) external returns (bool);

    /*//////////////////////////////////////////////////////////////
                            TOKEN METADATA
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves human-readable token name
     * @return string Full token name
     */
    function name() external view returns (string memory);

    /**
     * @notice Retrieves token trading symbol
     * @return string Short token identifier
     */
    function symbol() external view returns (string memory);

    /**
     * @notice Retrieves token decimal precision
     * @return uint8 Number of decimal places
     * @dev Standard:
     * · 18 for most tokens
     * · Used for display formatting
     */
    function decimals() external view returns (uint8);

    /*//////////////////////////////////////////////////////////////
                            BALANCE QUERIES
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves total token supply
     * @return uint256 Current total supply
     * @dev Reflects:
     * · All minted tokens
     * · Minus burned tokens
     * · In base units
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice Retrieves account token balance
     * @param account Address to query
     * @return uint256 Current balance in base units
     * @dev Returns:
     * · Available balance
     * · Includes pending rewards
     * · Excludes locked tokens
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @notice Retrieves remaining spending allowance
     * @param owner Token owner address
     * @param spender Authorized spender address
     * @return uint256 Current allowance in base units
     * @dev Shows:
     * · Approved amount
     * · Remaining limit
     * · Delegation status
     */
    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);
}

File 15 of 33 : IERC20Token.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IERC20Custom} from "./IERC20Custom.sol";

/**
 * @title IERC20Token
 * @dev Extended interface for ERC20 tokens with supply control capabilities
 * @notice Defines functionality for:
 * 1. Token minting
 * 2. Token burning
 * 3. Supply management
 */
interface IERC20Token is IERC20Custom {
    /*//////////////////////////////////////////////////////////////
                        SUPPLY MANAGEMENT
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Mints new tokens to specified account
     * @param account Address to receive minted tokens
     * @param amount Quantity of tokens to mint in base units
     * @dev Controls:
     * · Supply expansion
     * · Balance updates
     * · Event emission
     *
     * Requirements:
     * · Caller is authorized
     * · Within maxSupply
     * · Valid recipient
     */
    function mint(address account, uint256 amount) external;

    /**
     * @notice Burns tokens from specified account
     * @param account Address to burn tokens from
     * @param amount Quantity of tokens to burn in base units
     * @dev Manages:
     * · Supply reduction
     * · Balance updates
     * · Event emission
     *
     * Requirements:
     * · Caller is authorized
     * · Sufficient balance
     * · Amount > 0
     */
    function burn(address account, uint256 amount) external;

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves maximum token supply limit
     * @return uint256 Maximum supply cap in base units
     * @dev Enforces:
     * · Supply ceiling
     * · Mint restrictions
     * · Protocol limits
     *
     * Note: This is an immutable value that
     * cannot be exceeded by minting operations
     */
    function maxSupply() external view returns (uint256);
}

File 16 of 33 : IERC20TokenRebase.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IERC20Custom} from "./IERC20Custom.sol";

/**
 * @title IERC20TokenRebase
 * @dev Extended interface for ERC20 tokens with elastic supply and safe management
 * @notice Defines functionality for:
 * 1. Supply elasticity (rebasing)
 * 2. Safe-based token management
 * 3. Supply control mechanisms
 * 4. Configuration management
 */
interface IERC20TokenRebase is IERC20Custom {
    /*//////////////////////////////////////////////////////////////
                        SUPPLY MANAGEMENT
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Mints new tokens to specified account
     * @param account Address to receive minted tokens
     * @param amount Quantity of tokens to mint in base units
     * @dev Requires:
     * · Caller is authorized minter
     * · Within maxSupply limits
     * · Valid recipient
     */
    function mint(address account, uint256 amount) external;

    /**
     * @notice Burns tokens from specified account
     * @param account Address to burn tokens from
     * @param amount Quantity of tokens to burn in base units
     * @dev Requires:
     * · Caller is authorized
     * · Account has sufficient balance
     * · Amount > 0
     */
    function burn(address account, uint256 amount) external;

    /*//////////////////////////////////////////////////////////////
                        REBASE OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Executes supply rebase based on current parameters
     * @dev Triggers:
     * · Supply adjustment
     * · Balance recalculation
     * · Event emission
     *
     * Considers:
     * · Rebase interval
     * · Basis points
     * · Supply limits
     */
    function rebase() external;

    /**
     * @notice Configures rebase parameters
     * @param rebaseInterval Time period between rebases (in seconds)
     * @param rebaseBasisPoints Scale factor for rebase (in basis points)
     * @dev Controls:
     * · Rebase frequency
     * · Rebase magnitude
     * · Supply elasticity
     */
    function setRebaseConfig(
        uint256 rebaseInterval,
        uint256 rebaseBasisPoints
    ) external;

    /*//////////////////////////////////////////////////////////////
                        SAFE MANAGEMENT
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Initializes new token management safe
     * @param safe Address of safe to create
     * @dev Establishes:
     * · Safe permissions
     * · Access controls
     * · Management capabilities
     */
    function createSafe(address safe) external;

    /**
     * @notice Removes existing token management safe
     * @param safe Address of safe to remove
     * @dev Handles:
     * · Permission revocation
     * · State cleanup
     * · Access termination
     */
    function destroySafe(address safe) external;

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves floor contract address
     * @return address Active floor contract
     * @dev Used for:
     * · Price stability
     * · Supply control
     */
    function floor() external view returns (address);

    /**
     * @notice Retrieves authorized minter address
     * @return address Active minter contract
     * @dev Controls:
     * · Mint permissions
     * · Supply expansion
     */
    function minter() external view returns (address);

    /**
     * @notice Returns absolute maximum token supply
     * @return uint256 Maximum supply cap in base units
     * @dev Enforces:
     * · Hard supply limit
     * · Mint restrictions
     */
    function maxSupply() external view returns (uint256);

    /**
     * @notice Calculates maximum supply after rebase
     * @return uint256 Post-rebase maximum supply in base units
     * @dev Considers:
     * · Current max supply
     * · Rebase parameters
     * · Supply caps
     */
    function maxSupplyRebased() external view returns (uint256);

    /**
     * @notice Calculates total supply after rebase
     * @return uint256 Post-rebase total supply in base units
     * @dev Reflects:
     * · Current supply
     * · Rebase effects
     * · Supply limits
     */
    function totalSupplyRebased() external view returns (uint256);
}

File 17 of 33 : IFees.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IFeesWithdrawer
 * @dev Interface for protocol fee withdrawal operations
 * @notice Defines functionality for:
 * 1. Secure fee withdrawal
 * 2. Access control for withdrawals
 * 3. Protocol revenue management
 *
 * This interface ensures:
 * · Controlled access to protocol fees
 * · Safe transfer of accumulated revenue
 * · Proper accounting of withdrawn amounts
 */
interface IFeesWithdrawer {
    /*//////////////////////////////////////////////////////////////
                        WITHDRAWAL OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Withdraws accumulated protocol fees to designated recipients
     * @dev Only callable by authorized withdrawers
     * Handles:
     * · Fee accounting updates
     * · Transfer of tokens
     * · Event emission for tracking
     */
    function withdraw() external;
}

/**
 * @title IFeesDistributor
 * @dev Interface for protocol fee distribution and allocation
 * @notice Defines functionality for:
 * 1. Fee distribution across protocol components
 * 2. Dynamic allocation management
 * 3. Floor token revenue sharing
 *
 * This interface manages:
 * · Revenue distribution logic
 * · Allocation percentages
 * · Protocol incentive mechanisms
 */
interface IFeesDistributor {
    /*//////////////////////////////////////////////////////////////
                        DISTRIBUTION OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Distributes accumulated protocol fees according to set allocations
     * @dev Handles the distribution of fees to:
     * · Floor token stakers
     * · Protocol treasury
     * · Other designated recipients
     */
    function distribute() external;

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Returns current percentage allocated to Floor token stakers
     * @return uint256 Floor allocation percentage, scaled by 1e18
     */
    function floorAllocation() external view returns (uint256);
}

File 18 of 33 : IFloor.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IFloor
 * @dev Interface for protocol floor price management and capital operations
 * @notice Defines functionality for:
 * 1. Token deposit management
 * 2. Refund processing
 * 3. Capital tracking
 */
interface IFloor {
    /*//////////////////////////////////////////////////////////////
                        DEPOSIT OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Processes token deposits into the floor contract
     * @param msgSender Address initiating the deposit
     * @param amount Quantity of tokens to deposit
     * @dev Handles:
     * · Token transfer validation
     * · Capital tracking updates
     * · Event emission
     */
    function deposit(address msgSender, uint256 amount) external;

    /*//////////////////////////////////////////////////////////////
                        REFUND OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Processes token refunds from the floor contract
     * @param msgSender Address receiving the refund
     * @param amount Quantity of tokens to refund
     * @dev Ensures:
     * · Sufficient contract balance
     * · Authorized withdrawal
     * · Capital accounting
     */
    function refund(address msgSender, uint256 amount) external;

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Returns current total capital held in the floor contract
     * @return uint256 Current capital amount in base units
     * @dev Used for:
     * · Floor price calculations
     * · Protocol health metrics
     * · Capital adequacy checks
     */
    function capital() external view returns (uint256);
}

File 19 of 33 : ILender.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {Rebase} from "../library/AuxRebase.sol";
import {IERC20Custom} from "./IERC20Custom.sol";
import {IOracle} from "./IOracle.sol";
import {IVault} from "./IVault.sol";

/**
 * @title ILender
 * @dev Interface for lending operations and management
 * @notice Defines the core lending protocol functionality including:
 * 1. Collateral management and borrowing operations
 * 2. Interest rate and fee management
 * 3. Liquidation handling
 * 4. Vault integration
 *
 * The interface is designed to support:
 * · Over-collateralized lending
 * · Dynamic interest rates
 * · Liquidation mechanisms
 * · Fee collection and distribution
 */
interface ILender {
    /*//////////////////////////////////////////////////////////////
                        ADMIN CONFIGURATION
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Updates the interest rate for borrowing
     * @param newInterestRate New interest rate (scaled by 1e18)
     */
    function changeInterestRate(uint256 newInterestRate) external;

    /**
     * @notice Sets global and per-address borrowing limits
     * @param newBorrowLimit Total borrowing limit for the protocol
     * @param perAddressPart Maximum borrow amount per address
     */
    function changeBorrowLimit(
        uint256 newBorrowLimit,
        uint256 perAddressPart
    ) external;

    /*//////////////////////////////////////////////////////////////
                        CORE LENDING OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Updates protocol state with accrued interest
     */
    function accrue() external;

    /**
     * @notice Updates the exchange rate from the oracle
     */
    function updateExchangeRate() external;

    /**
     * @notice Withdraws accumulated protocol fees
     * @param amountToProvide Amount of fees to withdraw
     */
    function withdrawFees(uint256 amountToProvide) external;

    /*//////////////////////////////////////////////////////////////
                        LIQUIDATION HANDLING
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Liquidates undercollateralized positions
     * @param liquidator Address performing the liquidation
     * @param users Array of user addresses to liquidate
     * @param maxBorrowParts Maximum borrow parts to liquidate per user
     * @param to Address to receive liquidated collateral
     */
    function liquidate(
        address liquidator,
        address[] memory users,
        uint256[] memory maxBorrowParts,
        address to
    ) external;

    /*//////////////////////////////////////////////////////////////
                        VAULT OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Deposits collateral into the vault
     * @param amount Amount of collateral to deposit
     */
    function vaultDepositAddCollateral(uint256 amount) external;

    /**
     * @notice Withdraws borrowed assets from the vault
     * @param msgSender Address initiating the withdrawal
     * @param amount Amount to withdraw
     * @return part Borrow part assigned
     * @return share Share of the vault
     */
    function borrowVaultWithdraw(
        address msgSender,
        uint256 amount
    ) external returns (uint256 part, uint256 share);

    /*//////////////////////////////////////////////////////////////
                        COLLATERAL MANAGEMENT
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Adds collateral to a lending position
     * @param to Address to credit the collateral
     * @param skim True to skim tokens from the contract
     * @param share Amount of shares to add as collateral
     */
    function addCollateral(address to, bool skim, uint256 share) external;

    /**
     * @notice Removes collateral from a lending position
     * @param to Address to receive the removed collateral
     * @param share Amount of shares to remove
     */
    function removeCollateral(address to, uint256 share) external;

    /*//////////////////////////////////////////////////////////////
                        BORROWING OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Borrows assets against deposited collateral
     * @param msgSender Address initiating the borrow
     * @param amount Amount to borrow
     * @return part Borrow part assigned
     * @return share Share of the borrowed amount
     */
    function borrow(
        address msgSender,
        uint256 amount
    ) external returns (uint256 part, uint256 share);

    /**
     * @notice Repays borrowed assets
     * @param payer Address paying the debt
     * @param to Address whose debt to repay
     * @param skim True to skim tokens from the contract
     * @param part Amount of borrow part to repay
     * @return amount Actual amount repaid
     */
    function repay(
        address payer,
        address to,
        bool skim,
        uint256 part
    ) external returns (uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Gets the oracle contract address
     * @return IOracle Oracle interface
     */
    function oracle() external view returns (IOracle);

    /**
     * @notice Gets interest accrual information
     * @return Last accrual timestamp, accumulated interest, interest per second
     */
    function accrueInfo() external view returns (uint256, uint256, uint256);

    /**
     * @notice Gets the required collateral ratio
     * @return uint256 Collateral ratio (scaled by 1e5)
     */
    function collateralRatio() external view returns (uint256);

    /**
     * @notice Gets the liquidation bonus multiplier
     * @return uint256 Liquidation multiplier (scaled by 1e5)
     */
    function liquidationMultiplier() external view returns (uint256);

    /**
     * @notice Gets total collateral shares in the protocol
     * @return uint256 Total collateral share amount
     */
    function totalCollateralShare() external view returns (uint256);

    /**
     * @notice Gets the vault contract address
     * @return IVault Vault interface
     */
    function vault() external view returns (IVault);

    /**
     * @notice Gets the fee recipient address
     * @return address Fee recipient
     */
    function feeTo() external view returns (address);

    /**
     * @notice Gets the collateral token address
     * @return IERC20Custom Collateral token interface
     */
    function collateral() external view returns (IERC20Custom);

    /**
     * @notice Gets total borrow state
     * @return Rebase Total borrow information
     */
    function totalBorrow() external view returns (Rebase memory);

    /**
     * @notice Gets user's borrow part
     * @param account User address
     * @return uint256 User's borrow part
     */
    function userBorrowPart(address account) external view returns (uint256);

    /**
     * @notice Gets user's collateral share
     * @param account User address
     * @return uint256 User's collateral share
     */
    function userCollateralShare(
        address account
    ) external view returns (uint256);

    /**
     * @notice Gets protocol borrowing limits
     * @return total Total protocol borrow limit
     * @return borrowPartPerAddress Per-address borrow limit
     */
    function borrowLimit()
        external
        view
        returns (uint256 total, uint256 borrowPartPerAddress);

    /**
     * @notice Gets the DUSX token address
     * @return IERC20Custom DUSX token interface
     */
    function dusx() external view returns (IERC20Custom);

    /**
     * @notice Gets all accounts with active positions
     * @return address[] Array of account addresses
     */
    function accounts() external view returns (address[] memory);

    /**
     * @notice Gets the collateral precision factor
     * @return uint256 Collateral precision
     */
    function collateralPrecision() external view returns (uint256);
}

File 20 of 33 : ILenderOwner.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {ILender} from "./ILender.sol";

/**
 * @title ILenderOwner
 * @dev Interface for protocol-level lender management and configuration
 * @notice Defines functionality for:
 * 1. Interest rate management
 * 2. Borrow limit control
 * 3. Risk parameter adjustment
 */
interface ILenderOwner {
    /*//////////////////////////////////////////////////////////////
                        INTEREST MANAGEMENT
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Updates lender's interest rate configuration
     * @param lender The lender contract to modify
     * @param newInterestRate New interest rate value in basis points
     * @dev Controls:
     * · Interest accrual
     * · Yield generation
     * · Protocol revenue
     *
     * Requirements:
     * · Caller is authorized
     * · Rate within bounds
     * · Valid lender contract
     */
    function changeInterestRate(
        ILender lender,
        uint256 newInterestRate
    ) external;

    /*//////////////////////////////////////////////////////////////
                        LIMIT MANAGEMENT
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Updates lender's borrowing constraints
     * @param lender The lender contract to modify
     * @param newBorrowLimit New total protocol borrow limit
     * @param perAddressPart Maximum borrow limit per address
     * @dev Manages:
     * · Protocol exposure
     * · Individual limits
     * · Risk thresholds
     *
     * Requirements:
     * · Caller is authorized
     * · Valid limits
     * · perAddressPart <= newBorrowLimit
     *
     * Security:
     * · Prevents overleveraging
     * · Controls risk exposure
     * · Ensures protocol stability
     */
    function changeBorrowLimit(
        ILender lender,
        uint256 newBorrowLimit,
        uint256 perAddressPart
    ) external;

    /*//////////////////////////////////////////////////////////////
                        DEPRECATION MANAGEMENT
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Checks if a lender contract is deprecated
     * @param lender The lender address to check
     * @return bool True if the lender is deprecated, false otherwise
     * @dev Used to:
     * · Prevent operations on deprecated markets
     * · Control market lifecycle
     * · Manage protocol upgrades
     *
     * Security:
     * · Read-only function
     * · No state modifications
     * · Access control not required
     */
    function deprecated(address lender) external view returns (bool);

    /**
     * @notice Checks if a lender contract is in manual mode
     * @param lender The lender address to check
     * @return bool True if the lender is in manual mode, false otherwise
     * @dev Used to:
     * · Determine if borrow limits are managed manually
     * · Control automatic interest rate adjustments
     *
     * Security:
     * · Read-only function
     * · No state modifications
     * · Access control not required
     */
    function manual(address lender) external view returns (bool);
}

File 21 of 33 : ILiquidationHelper.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IERC20Custom} from "./IERC20Custom.sol";
import {ILender} from "../interface/ILender.sol";
import {IMiscHelper} from "../interface/IMiscHelper.sol";

/**
 * @title ILiquidationHelper
 * @dev Interface for liquidation assistance operations
 * @notice Defines comprehensive liquidation functionality including:
 * 1. Direct liquidation execution
 * 2. Liquidation amount calculations
 * 3. Position health checks
 * 4. Preview and simulation functions
 *
 * The helper provides:
 * · Maximum and partial liquidation support
 * · Customizable recipient addresses
 * · Pre-execution liquidation simulations
 * · Automated DUSX amount calculations
 */
interface ILiquidationHelper {
    /*//////////////////////////////////////////////////////////////
                            CONFIGURATION
    //////////////////////////////////////////////////////////////*/
    /*//////////////////////////////////////////////////////////////
                        LIQUIDATION EXECUTION
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Liquidates maximum possible amount for an account
     * @param lender Address of the lending contract
     * @param account Address to be liquidated
     * @return collateralAmount Amount of collateral received
     * @return adjustedBorrowPart Adjusted borrow amount after liquidation
     * @return requiredDUSXAmount DUSX tokens needed to execute liquidation
     * @dev Automatically calculates maximum liquidatable amount
     */
    function liquidateMax(
        ILender lender,
        address account
    )
        external
        returns (
            uint256 collateralAmount,
            uint256 adjustedBorrowPart,
            uint256 requiredDUSXAmount
        );

    /**
     * @notice Liquidates specific amount for an account
     * @param lender Address of the lending contract
     * @param account Address to be liquidated
     * @param borrowPart Amount of borrow position to liquidate
     * @return collateralAmount Amount of collateral received
     * @return adjustedBorrowPart Adjusted borrow amount after liquidation
     * @return requiredDUSXAmount DUSX tokens needed to execute liquidation
     * @dev Validates borrowPart against maximum liquidatable amount
     */
    function liquidate(
        ILender lender,
        address account,
        uint256 borrowPart
    )
        external
        returns (
            uint256 collateralAmount,
            uint256 adjustedBorrowPart,
            uint256 requiredDUSXAmount
        );

    /*//////////////////////////////////////////////////////////////
                    LIQUIDATION WITH CUSTOM RECIPIENT
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Liquidates maximum amount and sends to specified recipient
     * @param lender Address of the lending contract
     * @param account Address to be liquidated
     * @param recipient Address to receive liquidated assets
     * @dev Combines max liquidation with custom recipient
     */
    function liquidateMaxTo(
        ILender lender,
        address account,
        address recipient
    ) external;

    /**
     * @notice Liquidates specific amount and sends to specified recipient
     * @param lender Address of the lending contract
     * @param account Address to be liquidated
     * @param recipient Address to receive liquidated assets
     * @param borrowPart Amount of borrow position to liquidate
     * @dev Combines partial liquidation with custom recipient
     */
    function liquidateTo(
        ILender lender,
        address account,
        address recipient,
        uint256 borrowPart
    ) external;

    /*//////////////////////////////////////////////////////////////
                        LIQUIDATION PREVIEWS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Previews maximum possible liquidation amounts
     * @param lender Address of the lending contract
     * @param account Address to check
     * @return liquidatable Whether the account can be liquidated
     * @return requiredDUSXAmount DUSX tokens needed for liquidation
     * @return adjustedBorrowPart Final borrow amount after liquidation
     * @return returnedCollateralAmount Collateral amount to be received
     * @dev Simulates liquidation without executing
     */
    function previewMaxLiquidation(
        ILender lender,
        address account
    )
        external
        view
        returns (
            bool liquidatable,
            uint256 requiredDUSXAmount,
            uint256 adjustedBorrowPart,
            uint256 returnedCollateralAmount
        );

    /**
     * @notice Previews specific liquidation amounts
     * @param lender Address of the lending contract
     * @param account Address to check
     * @param borrowPart Amount of borrow position to liquidate
     * @return liquidatable Whether the account can be liquidated
     * @return requiredDUSXAmount DUSX tokens needed for liquidation
     * @return adjustedBorrowPart Final borrow amount after liquidation
     * @return returnedCollateralAmount Collateral amount to be received
     * @dev Simulates partial liquidation without executing
     */
    function previewLiquidation(
        ILender lender,
        address account,
        uint256 borrowPart
    )
        external
        view
        returns (
            bool liquidatable,
            uint256 requiredDUSXAmount,
            uint256 adjustedBorrowPart,
            uint256 returnedCollateralAmount
        );

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Checks if an account is eligible for liquidation
     * @param lender Address of the lending contract
     * @param account Address to check
     * @return bool True if account can be liquidated
     * @dev Considers collateral ratio and position health
     */
    function isLiquidatable(
        ILender lender,
        address account
    ) external view returns (bool);

    /**
     * @notice Returns the DUSX token contract used for liquidations
     * @return IERC20Custom DUSX token interface
     * @dev DUSX is required to execute liquidations
     */
    function dusx() external view returns (IERC20Custom);

    /**
     * @notice Returns the helper utility contract
     * @return IMiscHelper Helper interface for additional functions
     * @dev Helper provides supporting calculations and checks
     */
    function helper() external view returns (IMiscHelper);
}

File 22 of 33 : IMarketLens.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {ILender} from "./ILender.sol";

/**
 * @title IMarketLens
 * @dev Interface for viewing and analyzing lending market data
 * @notice Provides functionality for:
 * 1. Market size analysis
 * 2. Borrowing metrics
 * 3. Risk assessment data
 */
interface IMarketLens {
    /*//////////////////////////////////////////////////////////////
                            MARKET METRICS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Calculates total borrowed amount from a specific lending market
     * @param lender Address of the lending market to analyze
     * @return uint256 Total borrowed amount in base units
     * @dev Aggregates:
     * · Active loan positions
     * · Accrued interest
     * · Pending liquidations
     *
     * Used for:
     * · Market size analysis
     * · Risk assessment
     * · Protocol health monitoring
     */
    function getTotalBorrowed(ILender lender) external view returns (uint256);
}

File 23 of 33 : IMinter.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IERC20Custom} from "./IERC20Custom.sol";

/**
 * @title IMinter
 * @dev Interface for the Minter contract
 */
interface IMinter {
    /**
     * @notice Enables whitelist minting phase
     */
    function enableWhitelistMint() external;

    /**
     * @notice Enables public minting phase
     */
    function enablePublicMint() external;

    /**
     * @notice Adds a wallet to the whitelist
     * @param wallet Wallet address to whitelist
     */
    function addToWhitelist(address wallet) external;

    /**
     * @notice Mints tokens during whitelist phase
     * @param stablecoin Stablecoin used for minting
     * @param stableAmount Amount of stablecoin to mint against
     */
    function whitelistMint(
        IERC20Custom stablecoin,
        uint256 stableAmount
    ) external;

    /**
     * @notice Mints tokens during public phase
     * @param stablecoin Stablecoin used for minting
     * @param stableAmount Amount of stablecoin to mint against
     */
    function publicMint(IERC20Custom stablecoin, uint256 stableAmount) external;

    /**
     * @notice Mints remaining token supply
     * @param stablecoin Stablecoin used for minting
     */
    function mintRemainingSupply(IERC20Custom stablecoin) external;

    /**
     * @notice Sends accumulated DUSX to floor contract
     */
    function sendToFloorDUSX() external;

    /**
     * @notice Verifies if a wallet is whitelisted
     * @param wallet Address to verify
     * @return bool Whitelist status
     */
    function verifyWallet(address wallet) external view returns (bool);

    /**
     * @notice Calculates mint amount for given stablecoin input
     * @param stablecoin Stablecoin used for calculation
     * @param stableAmount Amount of stablecoin
     * @return uint256 Calculated mint amount
     */
    function calcMintAmount(
        IERC20Custom stablecoin,
        uint256 stableAmount
    ) external view returns (uint256);

    /**
     * @notice Gets the current token reserve
     * @return uint256 Current token reserve
     */
    function tokenReserve() external view returns (uint256);

    /**
     * @notice Gets the current mint ratio
     * @return uint256 Current mint ratio
     */
    function getCurrentRatio() external view returns (uint256);

    /**
     * @notice Gets the current mint rate
     * @return uint256 Current mint rate
     */
    function getCurrentRate() external view returns (uint256);
}

File 24 of 33 : IMiscHelper.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IDynamicInterestRate} from "./IDynamicInterestRate.sol";
import {IFeesDistributor} from "./IFees.sol";
import {IFeesWithdrawer} from "./IFees.sol";
import {IFloor} from "./IFloor.sol";
import {ILender} from "./ILender.sol";
import {ILenderOwner} from "./ILenderOwner.sol";
import {ILiquidationHelper} from "./ILiquidationHelper.sol";
import {IMarketLens} from "./IMarketLens.sol";
import {IPSM} from "./IPSM.sol";
import {IRepayHelper} from "./IRepayHelper.sol";
import {IStakedDUSX} from "./IStakedDUSX.sol";
import {ISupplyHangingCalculator} from "./ISupplyHangingCalculator.sol";

/**
 * @title IMiscHelper
 * @dev Interface for miscellaneous helper functions across the protocol
 * @notice Provides comprehensive helper methods for:
 * 1. Protocol configuration and parameter management
 * 2. Floor token operations
 * 3. Staked DUSX token management
 * 4. PSM (Peg Stability Module) operations
 * 5. Lending operations including borrowing and repayment
 * 6. System-wide view functions
 *
 * This interface acts as a central utility hub for coordinating
 * various protocol components and simplifying complex operations
 */
interface IMiscHelper {
    /*//////////////////////////////////////////////////////////////
                        CONFIGURATION FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Sets the supply hanging calculator contract
     * @param supplyHangingCalculator_ New calculator contract address
     * @dev Used for calculating supply adjustments
     */
    function setSupplyHangingCalculator(
        ISupplyHangingCalculator supplyHangingCalculator_
    ) external;

    /**
     * @notice Sets core protocol parameters and contract addresses
     * @param repayHelper_ Repayment helper contract
     * @param liquidationHelper_ Liquidation helper contract
     * @param dynamicInterestRate_ Interest rate calculator
     * @param feesDistributor_ Fee distribution contract
     * @param feesWithdrawer_ Fee withdrawal contract
     * @param lenderOwner_ Lender owner contract
     * @param marketLens_ Market data viewer contract
     * @dev Updates all main protocol component addresses
     */
    function setParameters(
        IRepayHelper repayHelper_,
        ILiquidationHelper liquidationHelper_,
        IDynamicInterestRate dynamicInterestRate_,
        IFeesDistributor feesDistributor_,
        IFeesWithdrawer feesWithdrawer_,
        ILenderOwner lenderOwner_,
        IMarketLens marketLens_
    ) external;

    /**
     * @notice Sets the list of active lender contracts
     * @param lenders_ Array of lender addresses
     * @dev Updates the protocol's lending markets
     */
    function setLenders(ILender[] memory lenders_) external;

    /**
     * @notice Sets the list of PSM contracts
     * @param pegStabilityModules_ Array of PSM addresses
     * @dev Updates available stablecoin PSM modules
     */
    function setPegStabilityModules(
        IPSM[] memory pegStabilityModules_
    ) external;

    /*//////////////////////////////////////////////////////////////
                        FLOOR TOKEN OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Deposits Floor tokens into the protocol
     * @param amount Amount of Floor tokens to deposit
     */
    function depositFloor(uint256 amount) external;

    /**
     * @notice Refunds Floor tokens from the protocol
     * @param amount Amount of Floor tokens to refund
     */
    function refundFloor(uint256 amount) external;

    /*//////////////////////////////////////////////////////////////
                        STAKED DUSX OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Deposits DUSX tokens for staking
     * @param amount Amount of DUSX to stake
     */
    function depositStakedDUSX(uint256 amount) external;

    /**
     * @notice Withdraws staked DUSX tokens
     * @param amount Amount of staked DUSX to withdraw
     */
    function withdrawStakedDUSX(uint256 amount) external;

    /*//////////////////////////////////////////////////////////////
                            PSM OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Swaps DUSX for stablecoin through PSM
     * @param psm PSM contract to use for swap
     * @param receiver Address to receive stablecoins
     * @param amountDUSX Amount of DUSX to swap
     */
    function psmSwapDUSXForStable(
        IPSM psm,
        address receiver,
        uint256 amountDUSX
    ) external;

    /**
     * @notice Swaps stablecoin for DUSX through PSM
     * @param psm PSM contract to use for swap
     * @param receiver Address to receive DUSX
     * @param amountStable Amount of stablecoin to swap
     */
    function psmSwapStableForDUSX(
        IPSM psm,
        address receiver,
        uint256 amountStable
    ) external;

    /*//////////////////////////////////////////////////////////////
                        LENDING OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Withdraws borrowed tokens from vault
     * @param lender Lender contract to withdraw from
     * @param amount Amount to withdraw
     */
    function lenderBorrowVaultWithdraw(ILender lender, uint256 amount) external;

    /**
     * @notice Executes a borrow operation
     * @param lender Lender contract to borrow from
     * @param amount Amount to borrow
     */
    function lenderBorrow(ILender lender, uint256 amount) external;

    /**
     * @notice Repays borrowed tokens
     * @param lender Lender contract to repay to
     * @param payer Address paying the debt
     * @param to Address receiving any excess
     * @param skim Whether to skim tokens from contract
     * @param part Amount of borrow part to repay
     */
    function lenderRepay(
        ILender lender,
        address payer,
        address to,
        bool skim,
        uint256 part
    ) external;

    /**
     * @notice Executes liquidation for multiple users
     * @param lender Lender contract to liquidate from
     * @param liquidator Address performing liquidation
     * @param users Array of addresses to liquidate
     * @param maxBorrowParts Maximum borrow parts to liquidate per user
     * @param to Address to receive liquidated assets
     */
    function lenderLiquidate(
        ILender lender,
        address liquidator,
        address[] memory users,
        uint256[] memory maxBorrowParts,
        address to
    ) external;

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Returns current APR for staked DUSX
     * @return uint256 Annual percentage rate
     */
    function aprStakedDUSX() external view returns (uint256);

    /**
     * @notice Returns repayment helper contract
     */
    function repayHelper() external view returns (IRepayHelper);

    /**
     * @notice Returns liquidation helper contract
     */
    function liquidationHelper() external view returns (ILiquidationHelper);

    /**
     * @notice Returns dynamic interest rate calculator
     */
    function dynamicInterestRate() external view returns (IDynamicInterestRate);

    /**
     * @notice Returns floor token contract
     */
    function floor() external view returns (IFloor);

    /**
     * @notice Returns fees distributor contract
     */
    function feesDistributor() external view returns (IFeesDistributor);

    /**
     * @notice Returns fees withdrawer contract
     */
    function feesWithdrawer() external view returns (IFeesWithdrawer);

    /**
     * @notice Returns lender contract at specified index
     * @param index Position in lenders array
     */
    function lenders(uint256 index) external view returns (ILender);

    /**
     * @notice Returns total number of lender contracts
     */
    function lendersLength() external view returns (uint256);

    /**
     * @notice Returns lender owner contract
     */
    function lenderOwner() external view returns (ILenderOwner);

    /**
     * @notice Returns market lens contract
     */
    function marketLens() external view returns (IMarketLens);

    /**
     * @notice Returns PSM contract at specified index
     * @param index Position in PSM array
     */
    function pegStabilityModules(uint256 index) external view returns (IPSM);

    /**
     * @notice Returns total number of PSM contracts
     */
    function pegStabilityModulesLength() external view returns (uint256);

    /**
     * @notice Returns staked DUSX token contract
     */
    function stDUSX() external view returns (IStakedDUSX);

    /**
     * @notice Returns supply hanging calculator contract
     */
    function supplyHangingCalculator()
        external
        view
        returns (ISupplyHangingCalculator);
}

File 25 of 33 : IOracle.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IOracle
 * @dev Interface for basic price feed operations
 * @notice Defines functionality for:
 * 1. Asset price retrieval
 * 2. Price precision handling
 */
interface IOracle {
    /*//////////////////////////////////////////////////////////////
                            PRICE QUERIES
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves current asset price
     * @param asset Address of the asset to price
     * @return uint256 Current price in base units with precision
     * @dev Provides:
     * · Latest price data
     * · Standardized precision
     * · Asset valuation
     *
     * Note: Check implementation for specific precision details
     */
    function getPrice(address asset) external view returns (uint256);
}

/**
 * @title ITwapOracle
 * @dev Interface for time-weighted average price calculations
 * @notice Defines functionality for:
 * 1. TWAP updates
 * 2. Time-weighted calculations
 * 3. Price smoothing
 */
interface ITwapOracle {
    /*//////////////////////////////////////////////////////////////
                            TWAP OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Updates time-weighted average price
     * @param asset Address of the asset to update
     * @return uint256 New TWAP value in base units
     * @dev Calculates:
     * · Time-weighted price
     * · Cumulative values
     * · Price averages
     *
     * Features:
     * · Manipulation resistance
     * · Smoothing effect
     * · Historical tracking
     */
    function updateTwap(address asset) external returns (uint256);
}

File 26 of 33 : IPSM.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IERC20Custom} from "./IERC20Custom.sol";

/**
 * @title IPSM
 * @dev Interface for Peg Stability Module (PSM) operations
 * @notice Defines functionality for:
 * 1. Stablecoin/DUSX swaps
 * 2. Peg maintenance
 * 3. Supply tracking
 */
interface IPSM {
    /*//////////////////////////////////////////////////////////////
                            SWAP OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Executes stablecoin to DUSX swap
     * @param msgSender Address initiating the swap
     * @param receiver Address receiving the DUSX
     * @param stableTokenAmount Amount of stablecoins to swap
     * @dev Handles:
     * · Stablecoin deposit
     * · DUSX minting
     * · Supply tracking
     */
    function swapStableForDUSX(
        address msgSender,
        address receiver,
        uint256 stableTokenAmount
    ) external;

    /**
     * @notice Executes DUSX to stablecoin swap
     * @param msgSender Address initiating the swap
     * @param receiver Address receiving the stablecoins
     * @param stableTokenAmount Amount of stablecoins to receive
     * @dev Handles:
     * · DUSX burning
     * · Stablecoin release
     * · Supply adjustment
     */
    function swapDUSXForStable(
        address msgSender,
        address receiver,
        uint256 stableTokenAmount
    ) external;

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves the stablecoin token contract
     * @return IERC20Custom Stablecoin token interface
     * @dev Used for:
     * · Token transfers
     * · Balance checks
     * · Allowance verification
     */
    function stableToken() external view returns (IERC20Custom);

    /**
     * @notice Returns total DUSX tokens minted through PSM
     * @return uint256 Total minted amount in base units
     * @dev Tracks:
     * · Total supply impact
     * · PSM utilization
     * · Protocol growth metrics
     */
    function dusxMinted() external view returns (uint256);

    /**
     * @notice Returns the maximum amount of DUSX that can be minted through PSM
     * @return uint256 Maximum mintable amount in base units
     * @dev Used for:
     * · Supply control
     * · Risk management
     * · Protocol safety
     */
    function dusxMintCap() external view returns (uint256);
}

File 27 of 33 : IRepayHelper.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IERC20Custom} from "./IERC20Custom.sol";
import {ILender} from "./ILender.sol";
import {IMiscHelper} from "./IMiscHelper.sol";

/**
 * @title IRepayHelper
 * @dev Interface for streamlined loan repayment operations and management
 * @notice Defines functionality for:
 * 1. Loan repayment processing
 * 2. Multi-loan management
 * 3. Helper contract integration
 * 4. Token interactions
 */
interface IRepayHelper {
    /*//////////////////////////////////////////////////////////////
                        CONFIGURATION
    //////////////////////////////////////////////////////////////*/
    /*//////////////////////////////////////////////////////////////
                        REPAYMENT OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Processes partial loan repayment
     * @param lender Address of the lending contract
     * @param to Address whose loan is being repaid
     * @param amount Amount to repay in base units
     * @return part Share of the loan repaid
     * @dev Handles:
     * · Token transfers
     * · Loan accounting
     * · Share calculations
     *
     * Requirements:
     * · Amount > 0
     * · Sufficient balance
     * · Valid addresses
     */
    function repayAmount(
        ILender lender,
        address to,
        uint256 amount
    ) external returns (uint256 part);

    /**
     * @notice Processes complete loan repayment
     * @param lender Address of the lending contract
     * @param to Address whose loan is being repaid
     * @return amount Total amount repaid in base units
     * @dev Manages:
     * · Full debt calculation
     * · Complete repayment
     * · Account settlement
     *
     * Effects:
     * · Clears entire debt
     * · Updates balances
     * · Emits events
     */
    function repayTotal(
        ILender lender,
        address to
    ) external returns (uint256 amount);

    /**
     * @notice Processes multiple complete loan repayments
     * @param lender Address of the lending contract
     * @param tos Array of addresses whose loans are being repaid
     * @return amount Total amount repaid across all loans
     * @dev Executes:
     * · Batch processing
     * · Multiple settlements
     * · Aggregate accounting
     *
     * Optimizations:
     * · Gas efficient
     * · Bulk processing
     * · Single transaction
     */
    function repayTotalMultiple(
        ILender lender,
        address[] calldata tos
    ) external returns (uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves DUSX token contract
     * @return IERC20Custom Interface of the DUSX token
     * @dev Used for:
     * · Token operations
     * · Balance checks
     * · Allowance verification
     */
    function dusx() external view returns (IERC20Custom);

    /**
     * @notice Retrieves helper contract
     * @return IMiscHelper Interface of the helper contract
     * @dev Provides:
     * · Helper functionality
     * · Integration access
     * · Utility methods
     */
    function helper() external view returns (IMiscHelper);
}

File 28 of 33 : IStableOwner.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {IERC20Token} from "./IERC20Token.sol";

/**
 * @title IStableOwner Interface
 * @dev Interface for StableOwner contract that manages stable token supply
 * @notice Defines the external interface for stable token supply management
 */
interface IStableOwner {
    /*//////////////////////////////////////////////////////////////
                            EVENTS
    //////////////////////////////////////////////////////////////*/
    /// @notice Emitted when stable token contract is updated
    /// @param stable New stable token contract address
    event StableSet(IERC20Token indexed stable);
    /// @notice Emitted when new tokens are minted
    /// @param account Recipient of minted tokens
    /// @param amount Amount of tokens minted
    event TokensMinted(address indexed account, uint256 amount);
    /// @notice Emitted when tokens are burned
    /// @param account Account tokens were burned from
    /// @param amount Amount of tokens burned
    event TokensBurned(address indexed account, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /// @notice Updates the stable token contract address
    /// @param stable_ New stable token contract address
    function setStable(IERC20Token stable_) external;

    /// @notice Creates new stable tokens
    /// @param account Address to receive minted tokens
    /// @param amount Number of tokens to mint
    function mint(address account, uint256 amount) external;

    /// @notice Destroys existing stable tokens
    /// @param account Address to burn tokens from
    /// @param amount Number of tokens to burn
    function burn(address account, uint256 amount) external;

    /// @notice The managed stable token contract
    /// @return The IERC20Token interface of the stable token
    function stable() external view returns (IERC20Token);
}

File 29 of 33 : IStakedDUSX.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IStakedDUSX
 * @dev Interface for staked DUSX token operations and reward distribution
 * @notice Defines functionality for:
 * 1. DUSX token staking
 * 2. Reward distribution
 * 3. Position management
 */
interface IStakedDUSX {
    /*//////////////////////////////////////////////////////////////
                        REWARD DISTRIBUTION
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Distributes protocol fees as staking rewards
     * @param amount Amount of fees to distribute in base units
     * @dev Handles:
     * · Pro-rata distribution
     * · Reward accounting
     * · Distribution events
     *
     * Rewards are:
     * · Automatically calculated
     * · Immediately available
     * · Proportional to stake
     */
    function distributeFees(uint256 amount) external;

    /**
     * @notice Claims pending fee rewards for the caller
     * @return claimedAmount Amount of fees claimed
     * @dev Allows users to manually claim their accumulated fees
     */
    function claimFees() external returns (uint256 claimedAmount);

    /*//////////////////////////////////////////////////////////////
                        STAKING OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Processes DUSX token deposits for staking
     * @param from Address providing the tokens
     * @param to Address receiving the staked position
     * @param amount Quantity of tokens to stake in base units
     * @dev Manages:
     * · Token transfers
     * · Position creation
     * · Reward calculations
     *
     * Supports:
     * · Direct deposits
     * · Delegated deposits
     * · Position tracking
     */
    function deposit(address from, address to, uint256 amount) external;

    /**
     * @notice Initiates a withdrawal from staked DUSX
     * @param amount Amount of tokens to withdraw
     */
    function beginWithdrawal(uint256 amount) external;

    /**
     * @notice Processes withdrawal of staked DUSX tokens
     * @param account Address withdrawing tokens
     * @dev Handles:
     * · Position updates
     * · Reward claims
     * · Token transfers
     *
     * Ensures:
     * · Sufficient balance
     * · Reward distribution
     * · Clean exit
     */
    function withdraw(address account) external;

    /**
     * @notice Views pending unclaimed fees for an account
     * @param account Address to check for pending fees
     * @return pendingAmount Amount of pending fees available to claim
     * @dev Calculates based on the fee accumulator and account's last claimed value
     */
    function pendingFees(
        address account
    ) external view returns (uint256 pendingAmount);
}

File 30 of 33 : ISupplyHangingCalculator.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title ISupplyHangingCalculator
 * @dev Interface for calculating and managing token supply adjustments
 * @notice Defines functionality for:
 * 1. Supply hanging calculations
 * 2. Safety margin management
 * 3. Risk-adjusted metrics
 */
interface ISupplyHangingCalculator {
    /*//////////////////////////////////////////////////////////////
                        SAFETY PARAMETERS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves current safety margin for supply calculations
     * @return uint256 Safety margin percentage scaled by 1e18
     * @dev Used for:
     * · Risk adjustment
     * · Supply buffer
     * · Protocol protection
     */
    function safetyMargin() external view returns (uint256);

    /*//////////////////////////////////////////////////////////////
                    SUPPLY HANGING CALCULATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Calculates current supply hanging with safety margins
     * @return uint256 Risk-adjusted supply hanging in base units
     * @dev Includes:
     * · Safety margin application
     * · Risk adjustments
     * · Protocol constraints
     *
     * Used for:
     * · Safe supply management
     * · Conservative adjustments
     * · Risk-aware operations
     */
    function getSupplyHanging() external view returns (uint256);

    /**
     * @notice Calculates raw supply hanging without safety margins
     * @return uint256 Unadjusted supply hanging in base units
     * @dev Provides:
     * · Raw calculations
     * · No safety buffers
     * · Maximum theoretical values
     *
     * Used for:
     * · Analysis purposes
     * · Maximum bounds
     * · Stress testing
     */
    function getSupplyHangingUnsafe() external view returns (uint256);
}

File 31 of 33 : IVault.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {Rebase} from "../library/AuxRebase.sol";
import {IERC20Custom} from "./IERC20Custom.sol";

/**
 * @title IVault
 * @dev Interface for advanced vault operations with elastic share system
 * @notice Defines functionality for:
 * 1. Token custody and management
 * 2. Share-based accounting
 * 3. Elastic supply mechanics
 * 4. Amount/share conversions
 */
interface IVault {
    /*//////////////////////////////////////////////////////////////
                        DEPOSIT OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Processes token deposits into vault
     * @param token Token contract to deposit
     * @param from Source of tokens
     * @param to Recipient of shares
     * @param amount Token amount (in base units, 0 for share-based)
     * @param share Share amount (0 for amount-based)
     * @return amountIn Actual tokens deposited
     * @return shareIn Actual shares minted
     * @dev Handles:
     * · Token transfers
     * · Share minting
     * · Balance updates
     *
     * Requirements:
     * · Valid token contract
     * · Authorized caller
     * · Sufficient balance
     * · Either amount or share > 0
     *
     * Note: Only one of amount/share should be non-zero
     */
    function deposit(
        IERC20Custom token,
        address from,
        address to,
        uint256 amount,
        uint256 share
    ) external returns (uint256 amountIn, uint256 shareIn);

    /*//////////////////////////////////////////////////////////////
                        WITHDRAWAL OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Processes token withdrawals from vault
     * @param token Token contract to withdraw
     * @param from Source of shares
     * @param to Recipient of tokens
     * @param amount Token amount (in base units, 0 for share-based)
     * @param share Share amount (0 for amount-based)
     * @return amountOut Actual tokens withdrawn
     * @return shareOut Actual shares burned
     * @dev Manages:
     * · Share burning
     * · Token transfers
     * · Balance updates
     *
     * Requirements:
     * · Valid token contract
     * · Sufficient shares
     * · Either amount or share > 0
     * · Authorized withdrawal
     *
     * Security:
     * · Validates balances
     * · Checks permissions
     * · Updates state atomically
     */
    function withdraw(
        IERC20Custom token,
        address from,
        address to,
        uint256 amount,
        uint256 share
    ) external returns (uint256 amountOut, uint256 shareOut);

    /*//////////////////////////////////////////////////////////////
                        SHARE TRANSFERS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Transfers vault shares between accounts
     * @param token Associated token contract
     * @param from Source of shares
     * @param to Recipient of shares
     * @param share Amount of shares to transfer
     * @dev Executes:
     * · Direct share movement
     * · Balance updates
     * · Event emission
     *
     * Requirements:
     * · Sufficient share balance
     * · Valid addresses
     * · Share amount > 0
     *
     * Note: Bypasses amount calculations for efficiency
     */
    function transfer(
        IERC20Custom token,
        address from,
        address to,
        uint256 share
    ) external;

    /*//////////////////////////////////////////////////////////////
                        BALANCE QUERIES
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves account's vault share balance
     * @param token Token contract to query
     * @param account Address to check
     * @return uint256 Share balance
     * @dev Provides:
     * · Raw share balance
     * · Without conversion
     * · Current state
     *
     * Use toAmount() to convert to token amount
     */
    function balanceOf(
        IERC20Custom token,
        address account
    ) external view returns (uint256);

    /*//////////////////////////////////////////////////////////////
                        CONVERSION OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Converts token amount to vault shares
     * @param token Token contract for conversion
     * @param amount Amount of tokens to convert
     * @param roundUp Whether to round up result
     * @return share Equivalent share amount
     * @dev Calculates:
     * · Share equivalent
     * · Based on totals
     * · Handles precision
     *
     * Rounding:
     * true = ceiling (≥)
     * false = floor (≤)
     */
    function toShare(
        IERC20Custom token,
        uint256 amount,
        bool roundUp
    ) external view returns (uint256 share);

    /**
     * @notice Converts vault shares to token amount
     * @param token Token contract for conversion
     * @param share Amount of shares to convert
     * @param roundUp Whether to round up result
     * @return amount Equivalent token amount
     * @dev Calculates:
     * · Token equivalent
     * · Based on totals
     * · Handles precision
     *
     * Rounding:
     * true = ceiling (≥)
     * false = floor (≤)
     */
    function toAmount(
        IERC20Custom token,
        uint256 share,
        bool roundUp
    ) external view returns (uint256 amount);

    /**
     * @notice Gets the list of active controllers
     * @return Array of controller addresses
     */
    function getControllers() external view returns (address[] memory);

    /*//////////////////////////////////////////////////////////////
                            VAULT TOTALS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves vault's total supply tracking
     * @param token Token contract to query
     * @return vaultTotals Rebase struct containing:
     * · elastic: Total token amount
     * · base: Total shares
     * @dev Provides:
     * · Current vault state
     * · Supply tracking
     * · Conversion basis
     *
     * Used for:
     * · Share calculations
     * · Amount conversions
     * · State validation
     */
    function totals(
        IERC20Custom token
    ) external view returns (Rebase memory vaultTotals);
}

File 32 of 33 : IVoteEscrowedSTTX.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IVoteEscrowedSTTX
 * @dev Interface for vote-escrowed STTX (veSTTX) token operations
 * @notice Defines functionality for:
 * 1. Token withdrawal management
 * 2. Escrow position handling
 * 3. Voting power release
 */
interface IVoteEscrowedSTTX {
    /*//////////////////////////////////////////////////////////////
                        WITHDRAWAL OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Processes withdrawal of escrowed STTX tokens
     * @dev Handles:
     * · Lock period verification
     * · Position liquidation
     * · Token transfers
     *
     * Requirements:
     * · Lock period expired
     * · Active position exists
     * · Caller is position owner
     *
     * Effects:
     * · Releases locked tokens
     * · Removes voting power
     * · Clears escrow position
     */
    function withdraw() external;
}

File 33 of 33 : AuxRebase.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title Rebase Library
 * @dev Library for handling elastic supply token calculations and adjustments
 * @notice This library provides mathematical operations for elastic/base token conversions
 * and supply adjustments. It handles two key concepts:
 *
 * 1. Elastic Supply: The actual total supply that can expand or contract
 * 2. Base Supply: The underlying base amount that remains constant
 */
/*//////////////////////////////////////////////////////////////
                               TYPES
//////////////////////////////////////////////////////////////*/
/**
 * @dev Core data structure for elastic supply tracking
 * @param elastic Current elastic (rebased) supply
 * @param base Current base (non-rebased) supply
 */
struct Rebase {
    uint256 elastic;
    uint256 base;
}

/**
 * @title AuxRebase
 * @dev Auxiliary functions for elastic supply calculations
 * @notice Provides safe mathematical operations for elastic/base conversions
 * with optional rounding control
 */
library AuxRebase {
    /*//////////////////////////////////////////////////////////////
                         ELASTIC SUPPLY OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Increases the elastic supply
     * @param total Current total supply state
     * @param elastic Amount to add to elastic supply
     * @return newElastic Updated elastic supply after addition
     */
    function addElastic(
        Rebase storage total,
        uint256 elastic
    ) internal returns (uint256 newElastic) {
        newElastic = total.elastic += elastic;
    }

    /**
     * @notice Decreases the elastic supply
     * @param total Current total supply state
     * @param elastic Amount to subtract from elastic supply
     * @return newElastic Updated elastic supply after subtraction
     */
    function subElastic(
        Rebase storage total,
        uint256 elastic
    ) internal returns (uint256 newElastic) {
        newElastic = total.elastic -= elastic;
    }

    /*//////////////////////////////////////////////////////////////
                         CONVERSION OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Converts an elastic amount to its base amount
     * @param total Current total supply state
     * @param elastic Amount of elastic tokens to convert
     * @param roundUp If true, rounds up the result
     * @return base Equivalent amount in base units
     * @dev
     * · If elastic supply is 0, returns elastic amount as base
     * · Handles potential precision loss during conversion
     * · Rounding can cause slight variations in converted amounts
     * · Recommended for scenarios requiring precise supply tracking
     *
     * Rounding Behavior:
     * · roundUp = false: Always rounds down (truncates)
     * · roundUp = true: Rounds up if there's a fractional remainder
     *
     * Edge Cases:
     * · total.elastic == 0: Returns input elastic as base
     * · Potential for minimal precision differences
     */
    function toBase(
        Rebase memory total,
        uint256 elastic,
        bool roundUp
    ) internal pure returns (uint256 base) {
        if (total.elastic == 0) {
            base = elastic;
        } else {
            base = (elastic * total.base) / total.elastic;
            if (roundUp && (base * total.elastic) / total.base < elastic) {
                base++;
            }
        }
    }

    /**
     * @notice Converts a base amount to its elastic amount
     * @param total Current total supply state
     * @param base Amount of base tokens to convert
     * @param roundUp If true, rounds up the result
     * @return elastic Equivalent amount in elastic units
     * @dev
     * · If base supply is 0, returns base amount as elastic
     * · Handles potential precision loss during conversion
     * · Rounding can cause slight variations in converted amounts
     * · Recommended for scenarios requiring precise supply tracking
     *
     * Rounding Behavior:
     * · roundUp = false: Always rounds down (truncates)
     * · roundUp = true: Rounds up if there's a fractional remainder
     *
     * Edge Cases:
     * · total.base == 0: Returns input base as elastic
     * · Potential for minimal precision differences
     */
    function toElastic(
        Rebase memory total,
        uint256 base,
        bool roundUp
    ) internal pure returns (uint256 elastic) {
        if (total.base == 0) {
            elastic = base;
        } else {
            elastic = (base * total.elastic) / total.base;
            if (roundUp && (elastic * total.base) / total.elastic < base) {
                elastic++;
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                         COMBINED OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Adds elastic tokens and calculates corresponding base amount
     * @param total Current total supply state
     * @param elastic Amount of elastic tokens to add
     * @param roundUp If true, rounds up base conversion
     * @return (Rebase, uint256) Updated total supply and calculated base amount
     */
    function add(
        Rebase memory total,
        uint256 elastic,
        bool roundUp
    ) internal pure returns (Rebase memory, uint256 base) {
        base = toBase(total, elastic, roundUp);
        total.elastic += elastic;
        total.base += base;
        return (total, base);
    }

    /**
     * @notice Subtracts base tokens and calculates corresponding elastic amount
     * @param total Current total supply state
     * @param base Amount of base tokens to subtract
     * @param roundUp If true, rounds up elastic conversion
     * @return (Rebase, uint256) Updated total supply and calculated elastic amount
     */
    function sub(
        Rebase memory total,
        uint256 base,
        bool roundUp
    ) internal pure returns (Rebase memory, uint256 elastic) {
        elastic = toElastic(total, base, roundUp);
        total.elastic -= elastic;
        total.base -= base;
        return (total, elastic);
    }

    /**
     * @notice Adds specific amounts to both elastic and base supplies
     * @param total Current total supply state
     * @param elastic Amount of elastic tokens to add
     * @param base Amount of base tokens to add
     * @return Rebase Updated total supply after addition
     */
    function add(
        Rebase memory total,
        uint256 elastic,
        uint256 base
    ) internal pure returns (Rebase memory) {
        total.elastic += elastic;
        total.base += base;
        return total;
    }

    /**
     * @notice Subtracts specific amounts from both elastic and base supplies
     * @param total Current total supply state
     * @param elastic Amount of elastic tokens to subtract
     * @param base Amount of base tokens to subtract
     * @return Rebase Updated total supply after subtraction
     */
    function sub(
        Rebase memory total,
        uint256 elastic,
        uint256 base
    ) internal pure returns (Rebase memory) {
        total.elastic -= elastic;
        total.base -= base;
        return total;
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IBaseContracts","name":"baseContracts_","type":"address"},{"internalType":"address","name":"treasury_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApproveFailed","type":"error"},{"inputs":[],"name":"EmptyArray","type":"error"},{"inputs":[],"name":"InvalidMintAmount","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"InvalidOwner","type":"error"},{"inputs":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"MaxStableRangeCalculationFailed","type":"error"},{"inputs":[],"name":"MintAlreadyActive","type":"error"},{"inputs":[{"internalType":"uint256","name":"stableAmount","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"MintAmountCalculationFailed","type":"error"},{"inputs":[],"name":"MintNotActive","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TokenReserveIsNotLowEnough","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"UnauthorizedAccount","type":"error"},{"inputs":[],"name":"UnsupportedStablecoin","type":"error"},{"inputs":[],"name":"WalletNotWhitelisted","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"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":[],"name":"PublicMintEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"WalletWhitelisted","type":"event"},{"anonymous":false,"inputs":[],"name":"WhitelistMintEnabled","type":"event"},{"inputs":[],"name":"TREASURY_ALLOCATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"addWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"}],"name":"addWalletBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Custom","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"stableAmount","type":"uint256"}],"name":"calcMintAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Custom","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"calcStableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dusx","outputs":[{"internalType":"contract IERC20Token","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enablePublicMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableWhitelistMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"floor","outputs":[{"internalType":"contract IFloor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"helper","outputs":[{"internalType":"contract IMiscHelper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Custom","name":"stablecoin","type":"address"}],"name":"mintRemainingSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pegStabilityModules","outputs":[{"internalType":"contract IPSM","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Custom","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"stableAmount","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"publicMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rates","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sendToFloorDUSX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stables","outputs":[{"internalType":"contract IERC20Custom","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sttx","outputs":[{"internalType":"contract IERC20TokenRebase","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenReserve","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":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"verifyWallet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Custom","name":"stablecoin","type":"address"},{"internalType":"uint256","name":"stableAmount","type":"uint256"}],"name":"whitelistMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelistMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedWallets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

61012060405234620000e55762000020620000196200020c565b9062001036565b6200002a620000eb565b613a3962001ed782396080518181816108e30152613660015260a051818181610c47015281816111f1015281816112850152818161171801528181611803015281816118930152818161197901528181611a6101528181611c18015281816123220152818161240e015281816126a70152818161296a01528181613026015281816130d1015261314f015260c051816103d0015260e0518181816104b601526132cf0152610100518181816102c901526134e10152613a3990f35b620000f1565b60405190565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b906200012290620000f6565b810190811060018060401b038211176200013b57604052565b62000100565b906200015862000150620000eb565b928362000116565b565b600080fd5b60018060a01b031690565b62000175906200015f565b90565b62000183906200016a565b90565b620001918162000178565b036200019957565b600080fd5b90505190620001ad8262000186565b565b620001ba816200016a565b03620001c257565b600080fd5b90505190620001d682620001af565b565b9190604083820312620002065780620001f96200020392600086016200019e565b93602001620001c7565b90565b6200015a565b6200022f6200591080380380620002238162000141565b928339810190620001d8565b9091565b90565b6200024f6200024962000255926200015f565b62000233565b6200015f565b90565b620002639062000236565b90565b620002719062000258565b90565b60e01b90565b62000285906200016a565b90565b62000293816200027a565b036200029b57565b600080fd5b90505190620002af8262000288565b565b90602082820312620002ce57620002cb91600001620002a0565b90565b6200015a565b60000190565b620002e4620000eb565b3d6000823e3d90fd5b60001b90565b906200030660018060a01b0391620002ed565b9181191691161790565b6200031b9062000236565b90565b620003299062000310565b90565b90565b90620003496200034362000351926200031e565b6200032c565b8254620002f3565b9055565b62000360906200016a565b90565b6200036e8162000355565b036200037657565b600080fd5b905051906200038a8262000363565b565b90602082820312620003a957620003a6916000016200037b565b90565b6200015a565b620003ba906200016a565b90565b620003c881620003af565b03620003d057565b600080fd5b90505190620003e482620003bd565b565b9060208282031262000403576200040091600001620003d5565b90565b6200015a565b62000414906200016a565b90565b620004228162000409565b036200042a57565b600080fd5b905051906200043e8262000417565b565b906020828203126200045d576200045a916000016200042f565b90565b6200015a565b60001c90565b60018060a01b031690565b62000483620004899162000463565b62000469565b90565b62000498905462000474565b90565b620004a69062000258565b90565b620004b5905162000355565b90565b620004c39062000258565b90565b620004d29051620003af565b90565b620004e09062000258565b90565b620004ef905162000409565b90565b620004fd9062000258565b90565b90565b90565b6200051f62000519620005259262000500565b62000233565b62000503565b90565b60018060401b0381116200053f5760208091020190565b62000100565b906200055b620005558362000528565b62000141565b918252565b369037565b9062000590620005758362000545565b9260208062000585869362000528565b920191039062000560565b565b6200059d906200016a565b90565b620005ab8162000592565b03620005b357565b600080fd5b90505190620005c782620005a0565b565b90602082820312620005e657620005e391600001620005b8565b90565b6200015a565b634e487b7160e01b600052603260045260246000fd5b5190565b90620006128262000602565b81101562000624576020809102010190565b620005ec565b90565b62000646620006406200064c926200062a565b62000233565b62000503565b90565b906200065b9062000592565b9052565b90565b6200067b6200067562000681926200065f565b62000233565b62000503565b90565b62000690905162000592565b90565b6200069e9062000258565b90565b620006ba620006b4620006c0926200062a565b62000233565b6200015f565b90565b620006ce90620006a1565b90565b5490565b634e487b7160e01b600052601160045260246000fd5b620006fd620007049193929362000503565b9262000503565b916200071283820262000503565b9281840414901517156200072257565b620006d5565b600190818003010490565b600052602060002090565b1b90565b91906008620007629102916200075b600019846200073e565b926200073e565b9181191691161790565b620007856200077f6200078b9262000503565b62000233565b62000503565b90565b90565b9190620007ac620007a6620007b5936200076c565b6200078e565b90835462000742565b9055565b600090565b620007d491620007cd620007b9565b9162000791565b565b5b818110620007e3575050565b80620007f36000600193620007be565b01620007d7565b90918281106200080a575b505050565b6200082f62000828620008216200083b9562000728565b9262000728565b9262000733565b918201910190620007d6565b38808062000805565b90680100000000000000008111620008725781620008666200087093620006d1565b90828155620007fa565b565b62000100565b60200190565b60018060a01b031690565b90565b620008978262000602565b9160018060401b0383116200090657620008ca620008c3600192620008bd868662000844565b62000878565b9262000733565b92049160005b838110620008de5750505050565b6001906020620008f8620008f28662000684565b62000889565b9401938184015501620008d0565b62000100565b9062000918916200088c565b565b60018060401b038111620009315760208091020190565b62000100565b906200094d62000947836200091a565b62000141565b918252565b369037565b9062000982620009678362000937565b926020806200097786936200091a565b920191039062000952565b565b6200098f906200016a565b90565b6200099d8162000984565b03620009a557565b600080fd5b90505190620009b98262000992565b565b90602082820312620009d857620009d591600001620009aa565b90565b6200015a565b5190565b90620009ee82620009de565b81101562000a00576020809102010190565b620005ec565b9062000a129062000984565b9052565b62000a22905162000984565b90565b62000a309062000258565b90565b5490565b600190818003010490565b600052602060002090565b5b81811062000a5a575050565b8062000a6a6000600193620007be565b0162000a4e565b909182811062000a81575b505050565b62000aa662000a9f62000a9862000ab29562000a37565b9262000a37565b9262000a42565b91820191019062000a4d565b38808062000a7c565b9068010000000000000000811162000ae9578162000add62000ae79362000a33565b9082815562000a71565b565b62000100565b60200190565b60018060a01b031690565b90565b62000b0e82620009de565b9160018060401b03831162000b7d5762000b4162000b3a60019262000b34868662000abb565b62000aef565b9262000a42565b92049160005b83811062000b555750505050565b600190602062000b6f62000b698662000a16565b62000b00565b940193818401550162000b47565b62000100565b9062000b8f9162000b03565b565b60018060401b03811162000ba55760200290565b62000100565b62000bba62000bc09162000b91565b62000141565b90565b90565b61ffff1690565b62000be662000be062000bec9262000bc3565b62000233565b62000bc6565b90565b9062000bfb9062000bc6565b9052565b90565b62000c1b62000c1562000c219262000bff565b62000233565b62000bc6565b90565b90565b62000c4062000c3a62000c469262000c24565b62000233565b62000bc6565b90565b50600a90565b600190818003010490565b90565b5b81811062000c6a575050565b8062000c7a6000600193620007be565b0162000c5e565b909182811062000c91575b505050565b62000cb662000caf62000ca862000cc29562000c4f565b9262000c4f565b9262000c5a565b91820191019062000c5d565b38808062000c8c565b9068010000000000000000811162000cf6578162000ced62000cf49362000c49565b9062000c81565b565b62000100565b50600a90565b62000d0e905162000bc6565b90565b90565b62000d1f8262000cfc565b9160018060401b03831162000d8e5762000d5262000d4b60019262000d45868662000ccb565b62000d11565b9262000c5a565b92049160005b83811062000d665750505050565b600190602062000d8062000d7a8662000d02565b6200078e565b940193818401550162000d58565b62000100565b9062000da09162000d14565b565b60ff1690565b62000db38162000da2565b0362000dbb57565b600080fd5b9050519062000dcf8262000da8565b565b9060208282031262000dee5762000deb9160000162000dc0565b90565b6200015a565b62000dff9062000da2565b604d811162000e0e57600a0a90565b620006d5565b90565b62000e3062000e2a62000e369262000e14565b62000233565b62000503565b90565b60209181520190565b62000e4d9062000a25565b9052565b9062000e608160209362000e42565b0190565b62000e7362000e799162000463565b62000af5565b90565b62000e88905462000e64565b90565b60010190565b9062000eb462000ead62000ea58462000a33565b809362000e39565b9262000a42565b9060005b81811062000ec65750505090565b90919262000eec62000ee560019262000edf8762000e7c565b62000e51565b9462000e8b565b910191909162000eb8565b9062000f039162000e91565b90565b9062000f2c62000f249262000f1a620000eb565b9384809262000ef7565b038362000116565b565b62000f399062000f06565b90565b62000f479062000693565b9052565b9062000f5a8160209362000f3c565b0190565b62000f6d62000f739162000463565b6200087e565b90565b62000f82905462000f5e565b90565b60010190565b9062000fae62000fa762000f9f84620006d1565b809362000e39565b9262000733565b9060005b81811062000fc05750505090565b90919262000fe662000fdf60019262000fd98762000f76565b62000f4b565b9462000f85565b910191909162000fb2565b9062000ffd9162000f8b565b90565b90620010266200101e9262001014620000eb565b9384809262000ff1565b038362000116565b565b620010339062001000565b90565b6200104062001a7f565b620010556200104f8262000266565b62001ab7565b620010608262001ab7565b6200108a6020620010718362000266565b6363b0e66a9062001081620000eb565b93849262000274565b825281806200109c60048201620002d4565b03915afa801562001a2b57620010be91600091620019f6575b5060026200032f565b620010e86020620010cf8362000266565b6396df10c090620010df620000eb565b93849262000274565b82528180620010fa60048201620002d4565b03915afa908115620019f057600091620019bb575b506080526200113d6020620011248362000266565b63ec4d80199062001134620000eb565b93849262000274565b825281806200114f60048201620002d4565b03915afa908115620019b55760009162001980575b5060a052620011926020620011798362000266565b63406953639062001189620000eb565b93849262000274565b82528180620011a460048201620002d4565b03915afa9081156200197a5760009162001945575b5060c052620011dd620011d7620011d160026200048c565b6200049b565b62001ab7565b620011fd620011f7620011f16080620004a9565b620004b8565b62001ab7565b6200121d620012176200121160a0620004c6565b620004d5565b62001ab7565b6200123d620012376200123160c0620004e3565b620004f2565b62001ab7565b620012536200124d600262000506565b62000565565b906200127e6020620012658362000266565b63b5cab3629062001275620000eb565b93849262000274565b825281806200129060048201620002d4565b03915afa80156200193f57620012f392620012d4620012da926020946000916200190b575b50620012ce87620012c760006200062d565b9062000606565b6200064f565b62000266565b63d4aaf8b990620012ea620000eb565b93849262000274565b825281806200130560048201620002d4565b03915afa801562001905576200133d91600091620018d0575b50620013378362001330600162000662565b9062000606565b6200064f565b62001369620013636200135d836200135660006200062d565b9062000606565b62000684565b62000693565b6200138a620013836200137d6000620006c3565b6200016a565b916200016a565b1480156200187b575b6200185457620013a58160046200090c565b62001407620013bf620013b9600262000506565b62000957565b916020620013ee620013e8620013e284620013db60006200062d565b9062000606565b62000684565b62000693565b63a9d75b2b90620013fe620000eb565b94859262000274565b825281806200141960048201620002d4565b03915afa9081156200184e576200147f620014796200148592620014666020956200149e976000916200181a575b5062001460896200145960006200062d565b90620009e2565b62000a06565b62001472600162000662565b9062000606565b62000684565b62000693565b63a9d75b2b9062001495620000eb565b93849262000274565b82528180620014b060048201620002d4565b03915afa80156200181457620014e891600091620017df575b50620014e283620014db600162000662565b90620009e2565b62000a06565b620015146200150e62001508836200150160006200062d565b90620009e2565b62000a16565b62000a25565b620015356200152e620015286000620006c3565b6200016a565b916200016a565b1480156200178a575b62001763576200155090600362000b83565b60e0526200167b62001563600a62000bab565b6200157e6200157461111c62000bcd565b6000830162000bef565b620015996200158f61111c62000bcd565b6020830162000bef565b620015b4620015aa61104f62000c02565b6040830162000bef565b620015cf620015c561104f62000c02565b6060830162000bef565b620015ea620015e0610fa862000c27565b6080830162000bef565b62001605620015fb610fa862000c27565b60a0830162000bef565b6200162062001616610fa862000c27565b60c0830162000bef565b6200163b62001631610fa862000c27565b60e0830162000bef565b620016576200164c610fa862000c27565b610100830162000bef565b6200167362001668610fa862000c27565b610120830162000bef565b600562000d94565b620016b5630ae64c6860206200169c6200169660a0620004c6565b620004d5565b63313ce56790620016ac620000eb565b94859262000274565b82528180620016c760048201620002d4565b03915afa80156200175d57620016f0620016f791620016fd9460009162001728575b5062000df4565b9162000e17565b620006eb565b610100526200172660036200171f6200171860049262000f2e565b9162001028565b9062001baf565b565b6200174e915060203d811162001755575b62001745818362000116565b81019062000dd1565b38620016e9565b503d62001739565b620002da565b6200176d620000eb565b63d92e233d60e01b8152806200178660048201620002d4565b0390fd5b50620017b7620017b1620017ab83620017a4600162000662565b90620009e2565b62000a16565b62000a25565b620017d8620017d1620017cb6000620006c3565b6200016a565b916200016a565b146200153e565b62001805915060203d81116200180c575b620017fc818362000116565b810190620009bb565b38620014c9565b503d620017f0565b620002da565b6200183f9150873d811162001846575b62001836818362000116565b810190620009bb565b3862001447565b503d6200182a565b620002da565b6200185e620000eb565b63d92e233d60e01b8152806200187760048201620002d4565b0390fd5b50620018a8620018a26200189c8362001895600162000662565b9062000606565b62000684565b62000693565b620018c9620018c2620018bc6000620006c3565b6200016a565b916200016a565b1462001393565b620018f6915060203d8111620018fd575b620018ed818362000116565b810190620005c9565b386200131e565b503d620018e1565b620002da565b620019309150853d811162001937575b62001927818362000116565b810190620005c9565b38620012b5565b503d6200191b565b620002da565b6200196b915060203d811162001972575b62001962818362000116565b81019062000440565b38620011b9565b503d62001956565b620002da565b620019a6915060203d8111620019ad575b6200199d818362000116565b810190620003e6565b3862001164565b503d62001991565b620002da565b620019e1915060203d8111620019e8575b620019d8818362000116565b8101906200038c565b386200110f565b503d620019cc565b620002da565b62001a1c915060203d811162001a23575b62001a13818362000116565b810190620002b1565b38620010b5565b503d62001a07565b620002da565b62001a3d600162000662565b90565b9062001a4f60001991620002ed565b9181191691161790565b9062001a7362001a6d62001a7b926200076c565b6200078e565b825462001a40565b9055565b62001a8962001aa1565b62001a9f62001a9762001a31565b600162001a59565b565b62001ab562001aaf62001df1565b62001e69565b565b62001ad862001ad162001acb6000620006c3565b6200016a565b916200016a565b1462001ae057565b62001aea620000eb565b63d92e233d60e01b81528062001b0360048201620002d4565b0390fd5b600162001b15910162000503565b90565b151590565b62001b288162001b18565b0362001b3057565b600080fd5b9050519062001b448262001b1d565b565b9060208282031262001b635762001b609160000162001b35565b90565b6200015a565b62001b74906200016a565b9052565b62001b839062000503565b9052565b91602062001bad92949362001ba56040820196600083019062001b69565b019062001b78565b565b62001bba81620009de565b9262001bc5620007b9565b5b8062001bdd62001bd68762000503565b9162000503565b101562001cf85762001c0562001bff62001bf9858490620009e2565b62000a16565b62000a25565b602063095ea7b39162001c2e62001c2862001c2289879062000606565b62000684565b62000693565b9062001c53600080199562001c5f62001c46620000eb565b9788968795869462000274565b84526004840162001b87565b03925af1801562001cf25762001c809160009162001cbd575b501562001b18565b62001c965762001c909062001b07565b62001bc6565b62001ca0620000eb565b633e3f8f7360e01b81528062001cb960048201620002d4565b0390fd5b62001ce3915060203d811162001cea575b62001cda818362000116565b81019062001b46565b3862001c78565b503d62001cce565b620002da565b509250505062001d1362001d0d6080620004a9565b620004b8565b602063095ea7b39162001d3162001d2b60c0620004e3565b620004f2565b9062001d56600080199562001d6262001d49620000eb565b9788968795869462000274565b84526004840162001b87565b03925af1801562001de65762001d839160009162001db1575b501562001b18565b62001d8a57565b62001d94620000eb565b633e3f8f7360e01b81528062001dad60048201620002d4565b0390fd5b62001dd7915060203d811162001dde575b62001dce818362000116565b81019062001b46565b3862001d7b565b503d62001dc2565b620002da565b600090565b62001dfb62001dec565b503390565b60018060a01b031690565b62001e1a62001e209162000463565b62001e00565b90565b62001e2f905462001e0b565b90565b62001e3d9062000258565b90565b90565b9062001e5d62001e5762001e659262001e32565b62001e40565b8254620002f3565b9055565b62001e75600062001e23565b62001e8282600062001e43565b9062001eba62001eb37f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09362001e32565b9162001e32565b9162001ec5620000eb565b8062001ed181620002d4565b0390a356fe60806040526004361015610013575b610ffd565b61001e6000356101fd565b80630e23d25c146101f8578063239c70ae146101f357806335f0bbd7146101ee57806340695363146101e95780634fee1290146101e457806361d027b3146101df57806363b0e66a146101da578063643aadb7146101d557806364de1e85146101d0578063715018a6146101cb5780637e9845f5146101c657806387674f33146101c15780638da5cb5b146101bc57806395799388146101b757806396df10c0146101b2578063a80dcfee146101ad578063b131da40146101a8578063b67c25a3146101a3578063bf1ad7e01461019e578063cbcb317114610199578063ce6df2b914610194578063d62f3b1c1461018f578063dd418ae21461018a578063ec4d801914610185578063ed987a0814610180578063efeb5f1f1461017b578063f2fde38b14610176578063f810de6714610171578063fc399c791461016c5763febf25bc0361000e57610fca565b610f95565b610f62565b610dfa565b610dc7565b610d92565b610c98565b610c10565b610b7e565b610b4a565b610b15565b610ae0565b610a74565b610a2f565b6109ea565b610934565b6108ad565b610878565b610842565b61080d565b6107a1565b61076c565b6106d3565b6105a4565b6104fb565b610481565b61044c565b610398565b610311565b610284565b60e01c90565b60405190565b600080fd5b600080fd5b600080fd5b60018060a01b031690565b61022c90610218565b90565b61023890610223565b90565b6102448161022f565b0361024b57565b600080fd5b9050359061025d8261023b565b565b906020828203126102795761027691600001610250565b90565b61020e565b60000190565b346102b25761029c61029736600461025f565b611474565b6102a4610203565b806102ae8161027e565b0390f35b610209565b60009103126102c257565b61020e565b7f000000000000000000000000000000000000000000000000000000000000000090565b90565b6102f7906102eb565b9052565b919061030f906000602085019401906102ee565b565b34610341576103213660046102b7565b61033d61032c6102c7565b610334610203565b918291826102fb565b0390f35b610209565b61034f816102eb565b0361035657565b600080fd5b9050359061036882610346565b565b919060408382031261039357806103876103909260008601610250565b9360200161035b565b90565b61020e565b346103c9576103c56103b46103ae36600461036a565b90611602565b6103bc610203565b918291826102fb565b0390f35b610209565b7f000000000000000000000000000000000000000000000000000000000000000090565b90565b61040961040461040e92610218565b6103f2565b610218565b90565b61041a906103f5565b90565b61042690610411565b90565b6104329061041d565b9052565b919061044a90600060208501940190610429565b565b3461047c5761045c3660046102b7565b6104786104676103ce565b61046f610203565b91829182610436565b0390f35b610209565b346104af576104913660046102b7565b6104996121b7565b6104a1610203565b806104ab8161027e565b0390f35b610209565b7f000000000000000000000000000000000000000000000000000000000000000090565b6104e190610223565b9052565b91906104f9906000602085019401906104d8565b565b3461052b5761050b3660046102b7565b6105276105166104b4565b61051e610203565b918291826104e5565b0390f35b610209565b1c90565b60018060a01b031690565b61054f9060086105549302610530565b610534565b90565b90610562915461053f565b90565b6105726002600090610557565b90565b61057e90610411565b90565b61058a90610575565b9052565b91906105a290600060208501940190610581565b565b346105d4576105b43660046102b7565b6105d06105bf610565565b6105c7610203565b9182918261058e565b0390f35b610209565b906020828203126105f3576105f09160000161035b565b90565b61020e565b634e487b7160e01b600052603260045260246000fd5b5490565b600052602060002090565b6106268161060e565b82101561064157610638600191610612565b91020190600090565b6105f8565b60018060a01b031690565b6106619060086106669302610530565b610646565b90565b906106749154610651565b90565b60036106828161060e565b82101561069f5761069c916106969161061d565b90610669565b90565b600080fd5b6106ad90610411565b90565b6106b9906106a4565b9052565b91906106d1906000602085019401906106b0565b565b34610703576106ff6106ee6106e93660046105d9565b610677565b6106f6610203565b918291826106bd565b0390f35b610209565b60ff1690565b61071e9060086107239302610530565b610708565b90565b90610731915461070e565b90565b6107416011600090610726565b90565b151590565b61075290610744565b9052565b919061076a90600060208501940190610749565b565b3461079c5761077c3660046102b7565b610798610787610734565b61078f610203565b91829182610756565b0390f35b610209565b346107cf576107b13660046102b7565b6107b961220f565b6107c1610203565b806107cb8161027e565b0390f35b610209565b90565b6107e79060086107ec9302610530565b6107d4565b90565b906107fa91546107d7565b90565b61080a60106000906107ef565b90565b3461083d5761081d3660046102b7565b6108396108286107fd565b610830610203565b918291826102fb565b0390f35b610209565b346108735761086f61085e61085836600461036a565b90612219565b610866610203565b918291826102fb565b0390f35b610209565b346108a8576108883660046102b7565b6108a461089361287c565b61089b610203565b918291826104e5565b0390f35b610209565b346108dc576108c66108c036600461036a565b9061294b565b6108ce610203565b806108d88161027e565b0390f35b610209565b7f000000000000000000000000000000000000000000000000000000000000000090565b61090e90610411565b90565b61091a90610905565b9052565b919061093290600060208501940190610911565b565b34610964576109443660046102b7565b61096061094f6108e1565b610957610203565b9182918261091e565b0390f35b610209565b61097281610223565b0361097957565b600080fd5b9050359061098b82610969565b565b906020828203126109a7576109a49160000161097e565b90565b61020e565b6109b590610411565b90565b906109c2906109ac565b600052602052604060002090565b6109e7906109e26012916000926109b8565b610726565b90565b34610a1a57610a16610a05610a0036600461098d565b6109d0565b610a0d610203565b91829182610756565b0390f35b610209565b610a2c600f6000906107ef565b90565b34610a5f57610a3f3660046102b7565b610a5b610a4a610a1f565b610a52610203565b918291826102fb565b0390f35b610209565b610a716011600190610726565b90565b34610aa457610a843660046102b7565b610aa0610a8f610a64565b610a97610203565b91829182610756565b0390f35b610209565b90565b610ac0610abb610ac592610aa9565b6103f2565b6102eb565b90565b610ad2600a610aac565b90565b610add610ac8565b90565b34610b1057610af03660046102b7565b610b0c610afb610ad5565b610b03610203565b918291826102fb565b0390f35b610209565b34610b4557610b253660046102b7565b610b41610b30612957565b610b38610203565b918291826102fb565b0390f35b610209565b34610b7957610b63610b5d36600461036a565b90612a73565b610b6b610203565b80610b758161027e565b0390f35b610209565b34610bac57610b8e3660046102b7565b610b96612b43565b610b9e610203565b80610ba88161027e565b0390f35b610209565b50600a90565b90565b610bc381610bb1565b821015610bde57610bd5600191610bb7565b91020190600090565b6105f8565b6005610bee81610bb1565b821015610c0b57610c0891610c0291610bba565b906107ef565b90565b600080fd5b34610c4057610c3c610c2b610c263660046105d9565b610be3565b610c33610203565b918291826102fb565b0390f35b610209565b7f000000000000000000000000000000000000000000000000000000000000000090565b610c7290610411565b90565b610c7e90610c69565b9052565b9190610c9690600060208501940190610c75565b565b34610cc857610ca83660046102b7565b610cc4610cb3610c45565b610cbb610203565b91829182610c82565b0390f35b610209565b5490565b600052602060002090565b610ce581610ccd565b821015610d0057610cf7600191610cd1565b91020190600090565b6105f8565b60018060a01b031690565b610d20906008610d259302610530565b610d05565b90565b90610d339154610d10565b90565b6004610d4181610ccd565b821015610d5e57610d5b91610d5591610cdc565b90610d28565b90565b600080fd5b610d6c90610411565b90565b610d7890610d63565b9052565b9190610d9090600060208501940190610d6f565b565b34610dc257610dbe610dad610da83660046105d9565b610d36565b610db5610203565b91829182610d7c565b0390f35b610209565b34610df557610ddf610dda36600461098d565b612bb8565b610de7610203565b80610df18161027e565b0390f35b610209565b34610e2857610e12610e0d36600461098d565b612c31565b610e1a610203565b80610e248161027e565b0390f35b610209565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b90610e5c90610e32565b810190811067ffffffffffffffff821117610e7657604052565b610e3c565b90610e8e610e87610203565b9283610e52565b565b67ffffffffffffffff8111610ea85760208091020190565b610e3c565b600080fd5b90929192610ec7610ec282610e90565b610e7b565b9381855260208086019202830192818411610f0457915b838310610eeb5750505050565b60208091610ef9848661097e565b815201920191610ede565b610ead565b9080601f83011215610f2757816020610f2493359101610eb2565b90565b610e2d565b90602082820312610f5d57600082013567ffffffffffffffff8111610f5857610f559201610f09565b90565b610213565b61020e565b34610f9057610f7a610f75366004610f2c565b612d3c565b610f82610203565b80610f8c8161027e565b0390f35b610209565b34610fc557610fc1610fb0610fab36600461098d565b612d4c565b610fb8610203565b91829182610756565b0390f35b610209565b34610ff857610fda3660046102b7565b610fe2612d8f565b610fea610203565b80610ff48161027e565b0390f35b610209565b600080fd5b6110139061100e612e1b565b6111c8565b61101b612e87565b565b60081c90565b61102f6110349161101d565b610708565b90565b6110419054611023565b90565b600080fd5b60e01b90565b9050519061105c82610346565b565b90602082820312611078576110759160000161104f565b90565b61020e565b611085610203565b3d6000823e3d90fd5b90565b6110a56110a06110aa9261108e565b6103f2565b6102eb565b90565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6110e56110eb916102eb565b916102eb565b9081156110f6570490565b6110ad565b60ff1690565b61110a816110fb565b0361111157565b600080fd5b9050519061112382611101565b565b9060208282031261113f5761113c91600001611116565b90565b61020e565b611150611156916110fb565b916110fb565b90039060ff821161116357565b6110c3565b611171906110fb565b604d811161117f57600a0a90565b6110c3565b90565b61119b6111966111a092611184565b6103f2565b6102eb565b90565b6111b26111b8919392936102eb565b926102eb565b82039182116111c357565b6110c3565b6111db6111d56011611037565b15610744565b611451576111e7612957565b61122b60206112157f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb0190611223610203565b938492611049565b8252818061123b6004820161027e565b03915afa801561144c5761126961126e916112749360009161141e575b506112636064611091565b906110d9565b6102eb565b916102eb565b10156113fb576112bf9060206112a97f0000000000000000000000000000000000000000000000000000000000000000610c69565b63313ce567906112b7610203565b948592611049565b825281806112cf6004820161027e565b03915afa80156113f657611307926000916113c8575b5060206112f1836106a4565b63313ce567906112ff610203565b958692611049565b825281806113176004820161027e565b03915afa9081156113c35761133f61138b926113449261139196600092611393575b50611144565b611168565b61138661134f612957565b61138061137a60056113746113646005610bb1565b61136e6001611187565b906111a3565b90610bba565b906107ef565b906110d9565b6110d9565b90612f5f565b565b6113b591925060203d81116113bc575b6113ad8183610e52565b810190611125565b9038611339565b503d6113a3565b61107d565b6113e9915060203d81116113ef575b6113e18183610e52565b810190611125565b386112e5565b503d6113d7565b61107d565b611403610203565b63e802952160e01b81528061141a6004820161027e565b0390fd5b61143f915060203d8111611445575b6114378183610e52565b81019061105e565b38611258565b503d61142d565b61107d565b611459610203565b63914edb0f60e01b8152806114706004820161027e565b0390fd5b61147d90611002565b565b600090565b61148e600a610aac565b90565b67ffffffffffffffff81116114a65760200290565b610e3c565b6114b76114bc91611491565b610e7b565b90565b369037565b906114e26114d1836114ab565b926114dc8491611491565b906114bf565b565b6114ee600a6114c4565b90565b90565b61150861150361150d926114f1565b6103f2565b6102eb565b90565b9061151a906102eb565b9052565b600161152a91016102eb565b90565b50600a90565b9061153d8261152d565b81101561154b576020020190565b6105f8565b91602061157292949361156b604082019660008301906102ee565b01906102ee565b565b60001c90565b61158661158b91611574565b6107d4565b90565b611598905461157a565b90565b6115aa6115b0919392936102eb565b926102eb565b82018092116115bb57565b6110c3565b6115cf6115d5919392936102eb565b926102eb565b916115e18382026102eb565b9281840414901517156115f057565b6110c3565b6115ff90516102eb565b90565b91909161160d61147f565b506116166114e4565b90611621600a6114ab565b61163761162e60006114f4565b60008301611510565b61164d61164460006114f4565b60208301611510565b61166361165a60006114f4565b60408301611510565b61167961167060006114f4565b60608301611510565b61168f61168660006114f4565b60808301611510565b6116a561169c60006114f4565b60a08301611510565b6116bb6116b260006114f4565b60c08301611510565b6116d16116c860006114f4565b60e08301611510565b6116e86116de60006114f4565b6101008301611510565b6116ff6116f560006114f4565b6101208301611510565b9260009061175261171060006114f4565b93602061173c7f0000000000000000000000000000000000000000000000000000000000000000610c69565b63313ce5679061174a610203565b948592611049565b825281806117626004820161027e565b03915afa9182156120bf57600092612085575b50602061178461179a926106a4565b63313ce56790611792610203565b938492611049565b825281806117aa6004820161027e565b03915afa8015612080576117cf926117ca92600092612050575b50611144565b611168565b926117d861147f565b5b806117f36117ed6117e8611484565b6102eb565b916102eb565b1015611b835761183d60206118277f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb0190611835610203565b938492611049565b8252818061184d6004820161027e565b03915afa908115611b7e576118899161187791600091611b50575b50611871611484565b906110d9565b6118848891849092611533565b611510565b6118cd60206118b77f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb01906118c5610203565b938492611049565b825281806118dd6004820161027e565b03915afa8015611b4b576119096119249161192b93600091611b1d575b50611903611484565b906110d9565b61191e61191860058690610bba565b906107ef565b906110d9565b86906110d9565b8061193f61193960006114f4565b916102eb565b1480611a56575b61196e57906119646119699261195f8a91849092611533565b611510565b61151e565b6117d9565b506119b3602061199d7f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb01906119ab610203565b938492611049565b825281806119c36004820161027e565b03915afa8015611a51576119ef6119f7916119fd93600091611a23575b506119e9611484565b906110d9565b926005610bba565b906107ef565b90611a1f611a09610203565b92839263d379876360e01b845260048401611550565b0390fd5b611a44915060203d8111611a4a575b611a3c8183610e52565b81019061105e565b856119e0565b503d611a32565b61107d565b50611a9b6020611a857f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb0190611a93610203565b938492611049565b82528180611aab6004820161027e565b03915afa8015611b1857611ad091600091611aea575b50611aca611484565b906110d9565b611ae3611add60006114f4565b916102eb565b1415611946565b611b0b915060203d8111611b11575b611b038183610e52565b81019061105e565b38611ac1565b503d611af9565b61107d565b611b3e915060203d8111611b44575b611b368183610e52565b81019061105e565b386118fa565b503d611b2c565b61107d565b611b71915060203d8111611b77575b611b698183610e52565b81019061105e565b38611868565b503d611b5f565b61107d565b509395919094611b9161147f565b965b87611bad611ba7611ba2611484565b6102eb565b916102eb565b101561204357611bbd600f61158e565b611c06611c00611bfb611bed611bdd8d611bd76001611187565b9061159b565b611be76064611091565b906115c0565b611bf5611484565b906110d9565b6102eb565b916102eb565b1060001461203557611c526020611c3c7f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb0190611c4a610203565b938492611049565b82528180611c626004820161027e565b03915afa90811561203057611cac611c92611cce93611cbc93600091612002575b50611c8c611484565b906110d9565b611ca68c611ca06001611187565b9061159b565b906115c0565b611cb6601061158e565b906111a3565b611cc983918b9092611533565b611510565b611cd88315610744565b611f0c575b83611d02611cfc611cf7611cf2868d90611533565b6115f5565b6102eb565b916102eb565b1115600014611df257505050611d5f611d3a611d3383611d2d611d2760058b90610bba565b906107ef565b906115c0565b84906115c0565b92611d5a84611d54611d4e60058b90610bba565b906107ef565b906110d9565b6110d9565b611d71611d6b836102eb565b916102eb565b03611db85750611d839293509061159b565b5b80611d9e611d98611d93612957565b6102eb565b916102eb565b11600014611db35750611daf612957565b5b90565b611db0565b611dcc611dc6866005610bba565b906107ef565b90611dee611dd8610203565b9283926368bb8cbb60e01b845260048401611550565b0390fd5b9091969294611e32611e2b611e10611e0b868890611533565b6115f5565b611e25611e1f60058990610bba565b906107ef565b906115c0565b86906115c0565b611e5b611e5482611e4e611e4860058a90610bba565b906107ef565b906110d9565b87906110d9565b611e7f611e79611e74611e6f888a90611533565b6115f5565b6102eb565b916102eb565b03611ebe57611e95611eb692611eaf929061159b565b96611ea9611ea4868890611533565b6115f5565b906111a3565b935b61151e565b969190611b93565b84611ee6611ee0611ed8611ed3888590611533565b6115f5565b926005610bba565b906107ef565b90611f08611ef2610203565b9283926368bb8cbb60e01b845260048401611550565b0390fd5b9150611f49611f42611f27611f22858b90611533565b6115f5565b611f3c611f3660058c90610bba565b906107ef565b906110d9565b85906110d9565b80611f5d611f5760006114f4565b916102eb565b1480611fd4575b611f8657611f7e90611f7983918a9092611533565b611510565b600191611cdd565b87611fae611fa8611fa0611f9b878590611533565b6115f5565b926005610bba565b906107ef565b90611fd0611fba610203565b92839263d379876360e01b845260048401611550565b0390fd5b50611fe8611fe3848a90611533565b6115f5565b611ffb611ff560006114f4565b916102eb565b1415611f64565b612023915060203d8111612029575b61201b8183610e52565b81019061105e565b38611c83565b503d612011565b61107d565b909150611eb6600097611eb1565b5050505050909150611d84565b61207291925060203d8111612079575b61206a8183610e52565b810190611125565b90386117c4565b503d612060565b61107d565b61179a9192506117846120af602092833d81116120b8575b6120a78183610e52565b810190611125565b93925050611775565b503d61209d565b61107d565b6120cc613555565b6120d4612142565b565b6120e26120e791611574565b610708565b90565b6120f490546120d6565b90565b60001b90565b9061210960ff916120f7565b9181191691161790565b61211c90610744565b90565b90565b9061213761213261213e92612113565b61211f565b82546120fd565b9055565b61214c60116120ea565b6121945761215c60016011612122565b7f80c8f4ee93129ab9b38a5d893cc03b09e1639b21d4adcda0881f1344acbe5fb9612185610203565b8061218f8161027e565b0390a1565b61219c610203565b6376c855ed60e01b8152806121b36004820161027e565b0390fd5b6121bf6120c4565b565b6121c9613555565b6121d16121fb565b565b6121e76121e26121ec926114f1565b6103f2565b610218565b90565b6121f8906121d3565b90565b61220d61220860006121ef565b6135e8565b565b6122176121c1565b565b61222161147f565b5061222c600a6114ab565b61224261223960006114f4565b60008301611510565b61225861224f60006114f4565b60208301611510565b61226e61226560006114f4565b60408301611510565b61228461227b60006114f4565b60608301611510565b61229a61229160006114f4565b60808301611510565b6122b06122a760006114f4565b60a08301611510565b6122c66122bd60006114f4565b60c08301611510565b6122dc6122d360006114f4565b60e08301611510565b6122f36122e960006114f4565b6101008301611510565b61230a61230060006114f4565b6101208301611510565b60009161235c61231a60006114f4565b9160206123467f0000000000000000000000000000000000000000000000000000000000000000610c69565b63313ce56790612354610203565b948592611049565b8252818061236c6004820161027e565b03915afa9182156128465760009261280c575b50602061238e6123a4926106a4565b63313ce5679061239c610203565b938492611049565b825281806123b46004820161027e565b03915afa8015612807576123d9926123d4926000926127d7575b50611144565b611168565b926123e261147f565b5b806123fd6123f76123f2611484565b6102eb565b916102eb565b10156124fb576124489060206124327f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb0190612440610203565b948592611049565b825281806124586004820161027e565b03915afa80156124f6576124ac6124a561248a6124be936124c3966000916124c8575b50612484611484565b906110d9565b61249f61249960058790610bba565b906107ef565b906110d9565b88906110d9565b6124b98791849092611533565b611510565b61151e565b6123e3565b6124e9915060203d81116124ef575b6124e18183610e52565b81019061105e565b3861247b565b503d6124d7565b61107d565b5093909392919261250a61147f565b935b8461252661252061251b611484565b6102eb565b916102eb565b10156127cd57612536600f61158e565b61257f6125796125746125666125568a6125506001611187565b9061159b565b6125606064611091565b906115c0565b61256e611484565b906110d9565b6102eb565b916102eb565b106000146127c0576125918215610744565b61269b575b826125e36125dd6125d86125d16125b66125b1878c90611533565b6115f5565b6125cb6125c560058d90610bba565b906107ef565b906115c0565b88906115c0565b6102eb565b916102eb565b11156000146126245750509161261461261a9261260f6126096126209796946005610bba565b906107ef565b6115c0565b906110d9565b9061159b565b5b90565b9093919461268d61264b61269492612645612640868890611533565b6115f5565b9061159b565b96612687612680612665612660878990611533565b6115f5565b61267a61267460058a90610bba565b906107ef565b906115c0565b87906115c0565b906111a3565b925b61151e565b939061250c565b90506126e160206126cb7f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb01906126d9610203565b938492611049565b825281806126f16004820161027e565b03915afa9081156127bb5761276c612751612741612727612785956127739560009161278d575b50612721611484565b906110d9565b61273b8a6127356001611187565b9061159b565b906115c0565b61274b601061158e565b906111a3565b61276661276060058a90610bba565b906107ef565b906110d9565b85906110d9565b6127808391879092611533565b611510565b600190612596565b6127ae915060203d81116127b4575b6127a68183610e52565b81019061105e565b38612718565b503d61279c565b61107d565b905061269460009461268f565b5050505050612621565b6127f991925060203d8111612800575b6127f18183610e52565b810190611125565b90386123ce565b503d6127e7565b61107d565b6123a491925061238e612836602092833d811161283f575b61282e8183610e52565b810190611125565b9392505061237f565b503d612824565b61107d565b600090565b60018060a01b031690565b61286761286c91611574565b612850565b90565b612879905461285b565b90565b61288461284b565b5061288f600061286f565b90565b906128a49161289f612e1b565b6128ae565b6128ac612e87565b565b906128d36128cd6128c860126128c2613649565b906109b8565b6120ea565b15610744565b6128e2576128e091612905565b565b6128ea610203565b6322f8556360e01b8152806129016004820161027e565b0390fd5b9061291961291360116120ea565b15610744565b6129285761292691612f5f565b565b612930610203565b63914edb0f60e01b8152806129476004820161027e565b0390fd5b9061295591612892565b565b61295f61147f565b506129a4602061298e7f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb019061299c610203565b938492611049565b825281806129b46004820161027e565b03915afa8015612a0c576129db916000916129de575b506129d5601061158e565b906111a3565b90565b6129ff915060203d8111612a05575b6129f78183610e52565b81019061105e565b386129ca565b503d6129ed565b61107d565b90612a2391612a1e612e1b565b612a2d565b612a2b612e87565b565b90612a41612a3b6011611037565b15610744565b612a5057612a4e91612f5f565b565b612a58610203565b63914edb0f60e01b815280612a6f6004820161027e565b0390fd5b90612a7d91612a11565b565b612a87613555565b612a8f612ace565b565b60081b90565b90612aa461ff0091612a91565b9181191691161790565b90612ac3612abe612aca92612113565b61211f565b8254612a97565b9055565b612ad86011611037565b612b2057612ae860016011612aae565b7fbad7871e16f9b9d8b2a6bd6e38ada7c99940913046fe099cffa0040643fb064e612b11610203565b80612b1b8161027e565b0390a1565b612b28610203565b6376c855ed60e01b815280612b3f6004820161027e565b0390fd5b612b4b612a7f565b565b612b5e90612b59613555565b612b60565b565b612b766001612b71601284906109b8565b612122565b612ba07f12c94d2725e3b811140fad6a73350adbd38646149c9a9a62ffc1018bec2ec97c916109ac565b90612ba9610203565b80612bb38161027e565b0390a2565b612bc190612b4d565b565b612bd490612bcf613555565b612bd6565b565b80612bf2612bec612be760006121ef565b610223565b91610223565b14612c0257612c00906135e8565b565b612c2d612c0f60006121ef565b612c17610203565b91829163b20f76e360e01b8352600483016104e5565b0390fd5b612c3a90612bc3565b565b612c4d90612c48613555565b612c80565b565b5190565b90612c5d82612c4f565b811015612c6e576020809102010190565b6105f8565b612c7d9051610223565b90565b90612c8a82612c4f565b90612c9361147f565b5b80612ca7612ca1856102eb565b916102eb565b1015612d3657612d3190612cd96001612cd46012612cce612cc98a8790612c53565b612c73565b906109b8565b612122565b612cec612ce7868390612c53565b612c73565b612d167f12c94d2725e3b811140fad6a73350adbd38646149c9a9a62ffc1018bec2ec97c916109ac565b90612d1f610203565b80612d298161027e565b0390a261151e565b612c94565b50915050565b612d4590612c3c565b565b600090565b612d63612d6891612d5b612d47565b5060126109b8565b6120ea565b90565b612d73612e1b565b612d7b612d85565b612d83612e87565b565b612d8d613656565b565b612d97612d6b565b565b90565b612db0612dab612db592612d99565b6103f2565b6102eb565b90565b612dc26002612d9c565b90565b90612dd2600019916120f7565b9181191691161790565b612df0612deb612df5926102eb565b6103f2565b6102eb565b90565b90565b90612e10612e0b612e1792612ddc565b612df8565b8254612dc5565b9055565b612e25600161158e565b612e3e612e38612e33612db8565b6102eb565b916102eb565b14612e5757612e55612e4e612db8565b6001612dfb565b565b612e5f610203565b6306fda65d60e31b815280612e766004820161027e565b0390fd5b612e846001611187565b90565b612e99612e92612e7a565b6001612dfb565b565b612ea4906103f5565b90565b612eb090612e9b565b90565b612ebc90610411565b90565b612ec8906103f5565b90565b612ed490612ebf565b90565b6000910312612ee257565b61020e565b916020612f09929493612f02604082019660008301906104d8565b01906102ee565b565b612f17612f1c91611574565b610534565b90565b612f299054612f0b565b90565b604090612f56612f5d9496959396612f4c60608401986000850190610d6f565b60208301906104d8565b01906102ee565b565b90612f72612f6c836137af565b15610744565b61353257612f81828290611602565b9081612f96612f9060006114f4565b916102eb565b148015613511575b80156134d7575b6134b457613060612fe4612fd483612fce6064612fc9612fc3610ac8565b91611091565b6111a3565b906115c0565b612fde6064611091565b906110d9565b91613002612ffb85612ff6601061158e565b61159b565b6010612dfb565b61301f61300f601061158e565b6130196064611091565b906115c0565b602061304a7f0000000000000000000000000000000000000000000000000000000000000000610c69565b63d5abeb0190613058610203565b958692611049565b825281806130706004820161027e565b03915afa9283156134af576130c69361309c926130959260009261347f575b506110d9565b600f612dfb565b6130ad6130a8866106a4565b612ea7565b906130b6613649565b6130bf30612eb3565b91926138a4565b6130ff6130fa6130f57f0000000000000000000000000000000000000000000000000000000000000000610c69565b612ecb565b610c69565b63af14052c90803b1561347a576131239160009161311b610203565b938492611049565b82528183816131346004820161027e565b03925af1801561347557613448575b5061317d6131786131737f0000000000000000000000000000000000000000000000000000000000000000610c69565b612ecb565b610c69565b6340c10f1961318a613649565b8492803b15613443576131b1600080946131bc6131a5610203565b97889687958694611049565b845260048401612ee7565b03925af1801561343e57613411575b506131d6600361060e565b926131df61147f565b5b806131f36131ed876102eb565b916102eb565b1015613403578161322061321a61321561320f6003869061061d565b90610669565b61022f565b9161022f565b146132335761322e9061151e565b6131e0565b909192935061324a6132456002612f1f565b610575565b61326361325d638eda7e69936004610cdc565b90610d28565b9061326d30612eb3565b9492813b156133fe576000613295916132a08296613289610203565b998a9788968795611049565b855260048501612f2c565b03925af19182156133f957613326926133cc575b505b6132c76132c2826106a4565b612ea7565b9060206132f47f0000000000000000000000000000000000000000000000000000000000000000926106a4565b6370a082319061331b61330630612eb3565b9261330f610203565b97889485938493611049565b8352600483016104e5565b03915afa9182156133c75761334393600093613397575b506138f4565b61334b613656565b613353613649565b6133926133807f3f2c9d57c068687834f0de942a9babb9e5acab57d516d3480a3c16ee165a4273926109ac565b92613389610203565b918291826102fb565b0390a2565b6133b991935060203d81116133c0575b6133b18183610e52565b81019061105e565b913861333d565b503d6133a7565b61107d565b6133ec9060003d81116133f2575b6133e48183610e52565b810190612ed7565b386132b4565b503d6133da565b61107d565b611044565b5090506133269192506132b6565b6134319060003d8111613437575b6134298183610e52565b810190612ed7565b386131cb565b503d61341f565b61107d565b611044565b6134689060003d811161346e575b6134608183610e52565b810190612ed7565b38613143565b503d613456565b61107d565b611044565b6134a191925060203d81116134a8575b6134998183610e52565b81019061105e565b903861308f565b503d61348f565b61107d565b6134bc610203565b63199f5a0360e31b8152806134d36004820161027e565b0390fd5b508161350b6135057f00000000000000000000000000000000000000000000000000000000000000006102eb565b916102eb565b11612fa5565b508161352c613526613521612957565b6102eb565b916102eb565b11612f9e565b61353a610203565b635bfbc03960e01b8152806135516004820161027e565b0390fd5b61355d61287c565b61357661357061356b613649565b610223565b91610223565b0361357d57565b6135a6613588613649565b613590610203565b9182916332b2baa360e01b8352600483016104e5565b0390fd5b906135bb60018060a01b03916120f7565b9181191691161790565b90565b906135dd6135d86135e4926109ac565b6135c5565b82546135aa565b9055565b6135f2600061286f565b6135fd8260006135c8565b9061363161362b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0936109ac565b916109ac565b9161363a610203565b806136448161027e565b0390a3565b61365161284b565b503390565b6136b660206136847f0000000000000000000000000000000000000000000000000000000000000000610905565b6370a08231906136ab61369630612eb3565b9261369f610203565b95869485938493611049565b8352600483016104e5565b03915afa9081156137aa5760009161377c575b50806136de6136d860006114f4565b916102eb565b116136e7575b50565b6136f96136f46002612f1f565b610575565b9063dc7d732390823b1561377757613731926137266000809461371a610203565b96879586948593611049565b8352600483016102fb565b03925af1801561377257613745575b6136e4565b6137659060003d811161376b575b61375d8183610e52565b810190612ed7565b38613740565b503d613753565b61107d565b611044565b61379d915060203d81116137a3575b6137958183610e52565b81019061105e565b386136c9565b503d61378b565b61107d565b6137b7612d47565b506137c2600361060e565b9060006137cd61147f565b5b806137e16137db866102eb565b916102eb565b101561382b578261380e6138086138036137fd6003869061061d565b90610669565b61022f565b9161022f565b146138215761381c9061151e565b6137ce565b5050505060015b90565b50915050613828565b61383d90610411565b90565b63ffffffff1690565b63ffffffff60e01b1690565b61386961386461386e92613840565b611049565b613849565b90565b60409061389b6138a29496959396613891606084019860008501906104d8565b60208301906104d8565b01906102ee565b565b6004926138de6138f295936138ed93946138c56323b872dd92949192613855565b936138ce610203565b9788956020870190815201613871565b60208201810382520383610e52565b613942565b565b9061393b6139409361392c6004949361391363a9059cbb919391613855565b9261391c610203565b9687946020860190815201612ee7565b60208201810382520383610e52565b613942565b565b90600060209161395061147f565b5061395961147f565b50828151910182855af1156139f7573d6000519061398061397a60006114f4565b916102eb565b146000146139dd575061399281613834565b3b6139a66139a060006114f4565b916102eb565b145b6139af5750565b6139bb6139d991613834565b6139c3610203565b918291635274afe760e01b8352600483016104e5565b0390fd5b6139f06139ea6001611187565b916102eb565b14156139a8565b6040513d6000823e3d90fdfea264697066735822122041e1d3d8d8580d0e9626cb8d271bb21b508138507076d840eb4db751942ef1c064736f6c634300081800330000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c00000000000000000000000012684d18bdba8e31936f40abce1175366874114f

Deployed Bytecode

0x60806040526004361015610013575b610ffd565b61001e6000356101fd565b80630e23d25c146101f8578063239c70ae146101f357806335f0bbd7146101ee57806340695363146101e95780634fee1290146101e457806361d027b3146101df57806363b0e66a146101da578063643aadb7146101d557806364de1e85146101d0578063715018a6146101cb5780637e9845f5146101c657806387674f33146101c15780638da5cb5b146101bc57806395799388146101b757806396df10c0146101b2578063a80dcfee146101ad578063b131da40146101a8578063b67c25a3146101a3578063bf1ad7e01461019e578063cbcb317114610199578063ce6df2b914610194578063d62f3b1c1461018f578063dd418ae21461018a578063ec4d801914610185578063ed987a0814610180578063efeb5f1f1461017b578063f2fde38b14610176578063f810de6714610171578063fc399c791461016c5763febf25bc0361000e57610fca565b610f95565b610f62565b610dfa565b610dc7565b610d92565b610c98565b610c10565b610b7e565b610b4a565b610b15565b610ae0565b610a74565b610a2f565b6109ea565b610934565b6108ad565b610878565b610842565b61080d565b6107a1565b61076c565b6106d3565b6105a4565b6104fb565b610481565b61044c565b610398565b610311565b610284565b60e01c90565b60405190565b600080fd5b600080fd5b600080fd5b60018060a01b031690565b61022c90610218565b90565b61023890610223565b90565b6102448161022f565b0361024b57565b600080fd5b9050359061025d8261023b565b565b906020828203126102795761027691600001610250565b90565b61020e565b60000190565b346102b25761029c61029736600461025f565b611474565b6102a4610203565b806102ae8161027e565b0390f35b610209565b60009103126102c257565b61020e565b7f00000000000000000000000000000000000000000097432b8379da85b0a0000090565b90565b6102f7906102eb565b9052565b919061030f906000602085019401906102ee565b565b34610341576103213660046102b7565b61033d61032c6102c7565b610334610203565b918291826102fb565b0390f35b610209565b61034f816102eb565b0361035657565b600080fd5b9050359061036882610346565b565b919060408382031261039357806103876103909260008601610250565b9360200161035b565b90565b61020e565b346103c9576103c56103b46103ae36600461036a565b90611602565b6103bc610203565b918291826102fb565b0390f35b610209565b7f000000000000000000000000b8c30cf1aa46b4e8ee8d008a0f2f763b3d5bac0e90565b90565b61040961040461040e92610218565b6103f2565b610218565b90565b61041a906103f5565b90565b61042690610411565b90565b6104329061041d565b9052565b919061044a90600060208501940190610429565b565b3461047c5761045c3660046102b7565b6104786104676103ce565b61046f610203565b91829182610436565b0390f35b610209565b346104af576104913660046102b7565b6104996121b7565b6104a1610203565b806104ab8161027e565b0390f35b610209565b7f00000000000000000000000012684d18bdba8e31936f40abce1175366874114f90565b6104e190610223565b9052565b91906104f9906000602085019401906104d8565b565b3461052b5761050b3660046102b7565b6105276105166104b4565b61051e610203565b918291826104e5565b0390f35b610209565b1c90565b60018060a01b031690565b61054f9060086105549302610530565b610534565b90565b90610562915461053f565b90565b6105726002600090610557565b90565b61057e90610411565b90565b61058a90610575565b9052565b91906105a290600060208501940190610581565b565b346105d4576105b43660046102b7565b6105d06105bf610565565b6105c7610203565b9182918261058e565b0390f35b610209565b906020828203126105f3576105f09160000161035b565b90565b61020e565b634e487b7160e01b600052603260045260246000fd5b5490565b600052602060002090565b6106268161060e565b82101561064157610638600191610612565b91020190600090565b6105f8565b60018060a01b031690565b6106619060086106669302610530565b610646565b90565b906106749154610651565b90565b60036106828161060e565b82101561069f5761069c916106969161061d565b90610669565b90565b600080fd5b6106ad90610411565b90565b6106b9906106a4565b9052565b91906106d1906000602085019401906106b0565b565b34610703576106ff6106ee6106e93660046105d9565b610677565b6106f6610203565b918291826106bd565b0390f35b610209565b60ff1690565b61071e9060086107239302610530565b610708565b90565b90610731915461070e565b90565b6107416011600090610726565b90565b151590565b61075290610744565b9052565b919061076a90600060208501940190610749565b565b3461079c5761077c3660046102b7565b610798610787610734565b61078f610203565b91829182610756565b0390f35b610209565b346107cf576107b13660046102b7565b6107b961220f565b6107c1610203565b806107cb8161027e565b0390f35b610209565b90565b6107e79060086107ec9302610530565b6107d4565b90565b906107fa91546107d7565b90565b61080a60106000906107ef565b90565b3461083d5761081d3660046102b7565b6108396108286107fd565b610830610203565b918291826102fb565b0390f35b610209565b346108735761086f61085e61085836600461036a565b90612219565b610866610203565b918291826102fb565b0390f35b610209565b346108a8576108883660046102b7565b6108a461089361287c565b61089b610203565b918291826104e5565b0390f35b610209565b346108dc576108c66108c036600461036a565b9061294b565b6108ce610203565b806108d88161027e565b0390f35b610209565b7f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f85490565b61090e90610411565b90565b61091a90610905565b9052565b919061093290600060208501940190610911565b565b34610964576109443660046102b7565b61096061094f6108e1565b610957610203565b9182918261091e565b0390f35b610209565b61097281610223565b0361097957565b600080fd5b9050359061098b82610969565b565b906020828203126109a7576109a49160000161097e565b90565b61020e565b6109b590610411565b90565b906109c2906109ac565b600052602052604060002090565b6109e7906109e26012916000926109b8565b610726565b90565b34610a1a57610a16610a05610a0036600461098d565b6109d0565b610a0d610203565b91829182610756565b0390f35b610209565b610a2c600f6000906107ef565b90565b34610a5f57610a3f3660046102b7565b610a5b610a4a610a1f565b610a52610203565b918291826102fb565b0390f35b610209565b610a716011600190610726565b90565b34610aa457610a843660046102b7565b610aa0610a8f610a64565b610a97610203565b91829182610756565b0390f35b610209565b90565b610ac0610abb610ac592610aa9565b6103f2565b6102eb565b90565b610ad2600a610aac565b90565b610add610ac8565b90565b34610b1057610af03660046102b7565b610b0c610afb610ad5565b610b03610203565b918291826102fb565b0390f35b610209565b34610b4557610b253660046102b7565b610b41610b30612957565b610b38610203565b918291826102fb565b0390f35b610209565b34610b7957610b63610b5d36600461036a565b90612a73565b610b6b610203565b80610b758161027e565b0390f35b610209565b34610bac57610b8e3660046102b7565b610b96612b43565b610b9e610203565b80610ba88161027e565b0390f35b610209565b50600a90565b90565b610bc381610bb1565b821015610bde57610bd5600191610bb7565b91020190600090565b6105f8565b6005610bee81610bb1565b821015610c0b57610c0891610c0291610bba565b906107ef565b90565b600080fd5b34610c4057610c3c610c2b610c263660046105d9565b610be3565b610c33610203565b918291826102fb565b0390f35b610209565b7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea90565b610c7290610411565b90565b610c7e90610c69565b9052565b9190610c9690600060208501940190610c75565b565b34610cc857610ca83660046102b7565b610cc4610cb3610c45565b610cbb610203565b91829182610c82565b0390f35b610209565b5490565b600052602060002090565b610ce581610ccd565b821015610d0057610cf7600191610cd1565b91020190600090565b6105f8565b60018060a01b031690565b610d20906008610d259302610530565b610d05565b90565b90610d339154610d10565b90565b6004610d4181610ccd565b821015610d5e57610d5b91610d5591610cdc565b90610d28565b90565b600080fd5b610d6c90610411565b90565b610d7890610d63565b9052565b9190610d9090600060208501940190610d6f565b565b34610dc257610dbe610dad610da83660046105d9565b610d36565b610db5610203565b91829182610d7c565b0390f35b610209565b34610df557610ddf610dda36600461098d565b612bb8565b610de7610203565b80610df18161027e565b0390f35b610209565b34610e2857610e12610e0d36600461098d565b612c31565b610e1a610203565b80610e248161027e565b0390f35b610209565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b90610e5c90610e32565b810190811067ffffffffffffffff821117610e7657604052565b610e3c565b90610e8e610e87610203565b9283610e52565b565b67ffffffffffffffff8111610ea85760208091020190565b610e3c565b600080fd5b90929192610ec7610ec282610e90565b610e7b565b9381855260208086019202830192818411610f0457915b838310610eeb5750505050565b60208091610ef9848661097e565b815201920191610ede565b610ead565b9080601f83011215610f2757816020610f2493359101610eb2565b90565b610e2d565b90602082820312610f5d57600082013567ffffffffffffffff8111610f5857610f559201610f09565b90565b610213565b61020e565b34610f9057610f7a610f75366004610f2c565b612d3c565b610f82610203565b80610f8c8161027e565b0390f35b610209565b34610fc557610fc1610fb0610fab36600461098d565b612d4c565b610fb8610203565b91829182610756565b0390f35b610209565b34610ff857610fda3660046102b7565b610fe2612d8f565b610fea610203565b80610ff48161027e565b0390f35b610209565b600080fd5b6110139061100e612e1b565b6111c8565b61101b612e87565b565b60081c90565b61102f6110349161101d565b610708565b90565b6110419054611023565b90565b600080fd5b60e01b90565b9050519061105c82610346565b565b90602082820312611078576110759160000161104f565b90565b61020e565b611085610203565b3d6000823e3d90fd5b90565b6110a56110a06110aa9261108e565b6103f2565b6102eb565b90565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6110e56110eb916102eb565b916102eb565b9081156110f6570490565b6110ad565b60ff1690565b61110a816110fb565b0361111157565b600080fd5b9050519061112382611101565b565b9060208282031261113f5761113c91600001611116565b90565b61020e565b611150611156916110fb565b916110fb565b90039060ff821161116357565b6110c3565b611171906110fb565b604d811161117f57600a0a90565b6110c3565b90565b61119b6111966111a092611184565b6103f2565b6102eb565b90565b6111b26111b8919392936102eb565b926102eb565b82039182116111c357565b6110c3565b6111db6111d56011611037565b15610744565b611451576111e7612957565b61122b60206112157f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb0190611223610203565b938492611049565b8252818061123b6004820161027e565b03915afa801561144c5761126961126e916112749360009161141e575b506112636064611091565b906110d9565b6102eb565b916102eb565b10156113fb576112bf9060206112a97f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63313ce567906112b7610203565b948592611049565b825281806112cf6004820161027e565b03915afa80156113f657611307926000916113c8575b5060206112f1836106a4565b63313ce567906112ff610203565b958692611049565b825281806113176004820161027e565b03915afa9081156113c35761133f61138b926113449261139196600092611393575b50611144565b611168565b61138661134f612957565b61138061137a60056113746113646005610bb1565b61136e6001611187565b906111a3565b90610bba565b906107ef565b906110d9565b6110d9565b90612f5f565b565b6113b591925060203d81116113bc575b6113ad8183610e52565b810190611125565b9038611339565b503d6113a3565b61107d565b6113e9915060203d81116113ef575b6113e18183610e52565b810190611125565b386112e5565b503d6113d7565b61107d565b611403610203565b63e802952160e01b81528061141a6004820161027e565b0390fd5b61143f915060203d8111611445575b6114378183610e52565b81019061105e565b38611258565b503d61142d565b61107d565b611459610203565b63914edb0f60e01b8152806114706004820161027e565b0390fd5b61147d90611002565b565b600090565b61148e600a610aac565b90565b67ffffffffffffffff81116114a65760200290565b610e3c565b6114b76114bc91611491565b610e7b565b90565b369037565b906114e26114d1836114ab565b926114dc8491611491565b906114bf565b565b6114ee600a6114c4565b90565b90565b61150861150361150d926114f1565b6103f2565b6102eb565b90565b9061151a906102eb565b9052565b600161152a91016102eb565b90565b50600a90565b9061153d8261152d565b81101561154b576020020190565b6105f8565b91602061157292949361156b604082019660008301906102ee565b01906102ee565b565b60001c90565b61158661158b91611574565b6107d4565b90565b611598905461157a565b90565b6115aa6115b0919392936102eb565b926102eb565b82018092116115bb57565b6110c3565b6115cf6115d5919392936102eb565b926102eb565b916115e18382026102eb565b9281840414901517156115f057565b6110c3565b6115ff90516102eb565b90565b91909161160d61147f565b506116166114e4565b90611621600a6114ab565b61163761162e60006114f4565b60008301611510565b61164d61164460006114f4565b60208301611510565b61166361165a60006114f4565b60408301611510565b61167961167060006114f4565b60608301611510565b61168f61168660006114f4565b60808301611510565b6116a561169c60006114f4565b60a08301611510565b6116bb6116b260006114f4565b60c08301611510565b6116d16116c860006114f4565b60e08301611510565b6116e86116de60006114f4565b6101008301611510565b6116ff6116f560006114f4565b6101208301611510565b9260009061175261171060006114f4565b93602061173c7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63313ce5679061174a610203565b948592611049565b825281806117626004820161027e565b03915afa9182156120bf57600092612085575b50602061178461179a926106a4565b63313ce56790611792610203565b938492611049565b825281806117aa6004820161027e565b03915afa8015612080576117cf926117ca92600092612050575b50611144565b611168565b926117d861147f565b5b806117f36117ed6117e8611484565b6102eb565b916102eb565b1015611b835761183d60206118277f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb0190611835610203565b938492611049565b8252818061184d6004820161027e565b03915afa908115611b7e576118899161187791600091611b50575b50611871611484565b906110d9565b6118848891849092611533565b611510565b6118cd60206118b77f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb01906118c5610203565b938492611049565b825281806118dd6004820161027e565b03915afa8015611b4b576119096119249161192b93600091611b1d575b50611903611484565b906110d9565b61191e61191860058690610bba565b906107ef565b906110d9565b86906110d9565b8061193f61193960006114f4565b916102eb565b1480611a56575b61196e57906119646119699261195f8a91849092611533565b611510565b61151e565b6117d9565b506119b3602061199d7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb01906119ab610203565b938492611049565b825281806119c36004820161027e565b03915afa8015611a51576119ef6119f7916119fd93600091611a23575b506119e9611484565b906110d9565b926005610bba565b906107ef565b90611a1f611a09610203565b92839263d379876360e01b845260048401611550565b0390fd5b611a44915060203d8111611a4a575b611a3c8183610e52565b81019061105e565b856119e0565b503d611a32565b61107d565b50611a9b6020611a857f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb0190611a93610203565b938492611049565b82528180611aab6004820161027e565b03915afa8015611b1857611ad091600091611aea575b50611aca611484565b906110d9565b611ae3611add60006114f4565b916102eb565b1415611946565b611b0b915060203d8111611b11575b611b038183610e52565b81019061105e565b38611ac1565b503d611af9565b61107d565b611b3e915060203d8111611b44575b611b368183610e52565b81019061105e565b386118fa565b503d611b2c565b61107d565b611b71915060203d8111611b77575b611b698183610e52565b81019061105e565b38611868565b503d611b5f565b61107d565b509395919094611b9161147f565b965b87611bad611ba7611ba2611484565b6102eb565b916102eb565b101561204357611bbd600f61158e565b611c06611c00611bfb611bed611bdd8d611bd76001611187565b9061159b565b611be76064611091565b906115c0565b611bf5611484565b906110d9565b6102eb565b916102eb565b1060001461203557611c526020611c3c7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb0190611c4a610203565b938492611049565b82528180611c626004820161027e565b03915afa90811561203057611cac611c92611cce93611cbc93600091612002575b50611c8c611484565b906110d9565b611ca68c611ca06001611187565b9061159b565b906115c0565b611cb6601061158e565b906111a3565b611cc983918b9092611533565b611510565b611cd88315610744565b611f0c575b83611d02611cfc611cf7611cf2868d90611533565b6115f5565b6102eb565b916102eb565b1115600014611df257505050611d5f611d3a611d3383611d2d611d2760058b90610bba565b906107ef565b906115c0565b84906115c0565b92611d5a84611d54611d4e60058b90610bba565b906107ef565b906110d9565b6110d9565b611d71611d6b836102eb565b916102eb565b03611db85750611d839293509061159b565b5b80611d9e611d98611d93612957565b6102eb565b916102eb565b11600014611db35750611daf612957565b5b90565b611db0565b611dcc611dc6866005610bba565b906107ef565b90611dee611dd8610203565b9283926368bb8cbb60e01b845260048401611550565b0390fd5b9091969294611e32611e2b611e10611e0b868890611533565b6115f5565b611e25611e1f60058990610bba565b906107ef565b906115c0565b86906115c0565b611e5b611e5482611e4e611e4860058a90610bba565b906107ef565b906110d9565b87906110d9565b611e7f611e79611e74611e6f888a90611533565b6115f5565b6102eb565b916102eb565b03611ebe57611e95611eb692611eaf929061159b565b96611ea9611ea4868890611533565b6115f5565b906111a3565b935b61151e565b969190611b93565b84611ee6611ee0611ed8611ed3888590611533565b6115f5565b926005610bba565b906107ef565b90611f08611ef2610203565b9283926368bb8cbb60e01b845260048401611550565b0390fd5b9150611f49611f42611f27611f22858b90611533565b6115f5565b611f3c611f3660058c90610bba565b906107ef565b906110d9565b85906110d9565b80611f5d611f5760006114f4565b916102eb565b1480611fd4575b611f8657611f7e90611f7983918a9092611533565b611510565b600191611cdd565b87611fae611fa8611fa0611f9b878590611533565b6115f5565b926005610bba565b906107ef565b90611fd0611fba610203565b92839263d379876360e01b845260048401611550565b0390fd5b50611fe8611fe3848a90611533565b6115f5565b611ffb611ff560006114f4565b916102eb565b1415611f64565b612023915060203d8111612029575b61201b8183610e52565b81019061105e565b38611c83565b503d612011565b61107d565b909150611eb6600097611eb1565b5050505050909150611d84565b61207291925060203d8111612079575b61206a8183610e52565b810190611125565b90386117c4565b503d612060565b61107d565b61179a9192506117846120af602092833d81116120b8575b6120a78183610e52565b810190611125565b93925050611775565b503d61209d565b61107d565b6120cc613555565b6120d4612142565b565b6120e26120e791611574565b610708565b90565b6120f490546120d6565b90565b60001b90565b9061210960ff916120f7565b9181191691161790565b61211c90610744565b90565b90565b9061213761213261213e92612113565b61211f565b82546120fd565b9055565b61214c60116120ea565b6121945761215c60016011612122565b7f80c8f4ee93129ab9b38a5d893cc03b09e1639b21d4adcda0881f1344acbe5fb9612185610203565b8061218f8161027e565b0390a1565b61219c610203565b6376c855ed60e01b8152806121b36004820161027e565b0390fd5b6121bf6120c4565b565b6121c9613555565b6121d16121fb565b565b6121e76121e26121ec926114f1565b6103f2565b610218565b90565b6121f8906121d3565b90565b61220d61220860006121ef565b6135e8565b565b6122176121c1565b565b61222161147f565b5061222c600a6114ab565b61224261223960006114f4565b60008301611510565b61225861224f60006114f4565b60208301611510565b61226e61226560006114f4565b60408301611510565b61228461227b60006114f4565b60608301611510565b61229a61229160006114f4565b60808301611510565b6122b06122a760006114f4565b60a08301611510565b6122c66122bd60006114f4565b60c08301611510565b6122dc6122d360006114f4565b60e08301611510565b6122f36122e960006114f4565b6101008301611510565b61230a61230060006114f4565b6101208301611510565b60009161235c61231a60006114f4565b9160206123467f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63313ce56790612354610203565b948592611049565b8252818061236c6004820161027e565b03915afa9182156128465760009261280c575b50602061238e6123a4926106a4565b63313ce5679061239c610203565b938492611049565b825281806123b46004820161027e565b03915afa8015612807576123d9926123d4926000926127d7575b50611144565b611168565b926123e261147f565b5b806123fd6123f76123f2611484565b6102eb565b916102eb565b10156124fb576124489060206124327f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb0190612440610203565b948592611049565b825281806124586004820161027e565b03915afa80156124f6576124ac6124a561248a6124be936124c3966000916124c8575b50612484611484565b906110d9565b61249f61249960058790610bba565b906107ef565b906110d9565b88906110d9565b6124b98791849092611533565b611510565b61151e565b6123e3565b6124e9915060203d81116124ef575b6124e18183610e52565b81019061105e565b3861247b565b503d6124d7565b61107d565b5093909392919261250a61147f565b935b8461252661252061251b611484565b6102eb565b916102eb565b10156127cd57612536600f61158e565b61257f6125796125746125666125568a6125506001611187565b9061159b565b6125606064611091565b906115c0565b61256e611484565b906110d9565b6102eb565b916102eb565b106000146127c0576125918215610744565b61269b575b826125e36125dd6125d86125d16125b66125b1878c90611533565b6115f5565b6125cb6125c560058d90610bba565b906107ef565b906115c0565b88906115c0565b6102eb565b916102eb565b11156000146126245750509161261461261a9261260f6126096126209796946005610bba565b906107ef565b6115c0565b906110d9565b9061159b565b5b90565b9093919461268d61264b61269492612645612640868890611533565b6115f5565b9061159b565b96612687612680612665612660878990611533565b6115f5565b61267a61267460058a90610bba565b906107ef565b906115c0565b87906115c0565b906111a3565b925b61151e565b939061250c565b90506126e160206126cb7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb01906126d9610203565b938492611049565b825281806126f16004820161027e565b03915afa9081156127bb5761276c612751612741612727612785956127739560009161278d575b50612721611484565b906110d9565b61273b8a6127356001611187565b9061159b565b906115c0565b61274b601061158e565b906111a3565b61276661276060058a90610bba565b906107ef565b906110d9565b85906110d9565b6127808391879092611533565b611510565b600190612596565b6127ae915060203d81116127b4575b6127a68183610e52565b81019061105e565b38612718565b503d61279c565b61107d565b905061269460009461268f565b5050505050612621565b6127f991925060203d8111612800575b6127f18183610e52565b810190611125565b90386123ce565b503d6127e7565b61107d565b6123a491925061238e612836602092833d811161283f575b61282e8183610e52565b810190611125565b9392505061237f565b503d612824565b61107d565b600090565b60018060a01b031690565b61286761286c91611574565b612850565b90565b612879905461285b565b90565b61288461284b565b5061288f600061286f565b90565b906128a49161289f612e1b565b6128ae565b6128ac612e87565b565b906128d36128cd6128c860126128c2613649565b906109b8565b6120ea565b15610744565b6128e2576128e091612905565b565b6128ea610203565b6322f8556360e01b8152806129016004820161027e565b0390fd5b9061291961291360116120ea565b15610744565b6129285761292691612f5f565b565b612930610203565b63914edb0f60e01b8152806129476004820161027e565b0390fd5b9061295591612892565b565b61295f61147f565b506129a4602061298e7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb019061299c610203565b938492611049565b825281806129b46004820161027e565b03915afa8015612a0c576129db916000916129de575b506129d5601061158e565b906111a3565b90565b6129ff915060203d8111612a05575b6129f78183610e52565b81019061105e565b386129ca565b503d6129ed565b61107d565b90612a2391612a1e612e1b565b612a2d565b612a2b612e87565b565b90612a41612a3b6011611037565b15610744565b612a5057612a4e91612f5f565b565b612a58610203565b63914edb0f60e01b815280612a6f6004820161027e565b0390fd5b90612a7d91612a11565b565b612a87613555565b612a8f612ace565b565b60081b90565b90612aa461ff0091612a91565b9181191691161790565b90612ac3612abe612aca92612113565b61211f565b8254612a97565b9055565b612ad86011611037565b612b2057612ae860016011612aae565b7fbad7871e16f9b9d8b2a6bd6e38ada7c99940913046fe099cffa0040643fb064e612b11610203565b80612b1b8161027e565b0390a1565b612b28610203565b6376c855ed60e01b815280612b3f6004820161027e565b0390fd5b612b4b612a7f565b565b612b5e90612b59613555565b612b60565b565b612b766001612b71601284906109b8565b612122565b612ba07f12c94d2725e3b811140fad6a73350adbd38646149c9a9a62ffc1018bec2ec97c916109ac565b90612ba9610203565b80612bb38161027e565b0390a2565b612bc190612b4d565b565b612bd490612bcf613555565b612bd6565b565b80612bf2612bec612be760006121ef565b610223565b91610223565b14612c0257612c00906135e8565b565b612c2d612c0f60006121ef565b612c17610203565b91829163b20f76e360e01b8352600483016104e5565b0390fd5b612c3a90612bc3565b565b612c4d90612c48613555565b612c80565b565b5190565b90612c5d82612c4f565b811015612c6e576020809102010190565b6105f8565b612c7d9051610223565b90565b90612c8a82612c4f565b90612c9361147f565b5b80612ca7612ca1856102eb565b916102eb565b1015612d3657612d3190612cd96001612cd46012612cce612cc98a8790612c53565b612c73565b906109b8565b612122565b612cec612ce7868390612c53565b612c73565b612d167f12c94d2725e3b811140fad6a73350adbd38646149c9a9a62ffc1018bec2ec97c916109ac565b90612d1f610203565b80612d298161027e565b0390a261151e565b612c94565b50915050565b612d4590612c3c565b565b600090565b612d63612d6891612d5b612d47565b5060126109b8565b6120ea565b90565b612d73612e1b565b612d7b612d85565b612d83612e87565b565b612d8d613656565b565b612d97612d6b565b565b90565b612db0612dab612db592612d99565b6103f2565b6102eb565b90565b612dc26002612d9c565b90565b90612dd2600019916120f7565b9181191691161790565b612df0612deb612df5926102eb565b6103f2565b6102eb565b90565b90565b90612e10612e0b612e1792612ddc565b612df8565b8254612dc5565b9055565b612e25600161158e565b612e3e612e38612e33612db8565b6102eb565b916102eb565b14612e5757612e55612e4e612db8565b6001612dfb565b565b612e5f610203565b6306fda65d60e31b815280612e766004820161027e565b0390fd5b612e846001611187565b90565b612e99612e92612e7a565b6001612dfb565b565b612ea4906103f5565b90565b612eb090612e9b565b90565b612ebc90610411565b90565b612ec8906103f5565b90565b612ed490612ebf565b90565b6000910312612ee257565b61020e565b916020612f09929493612f02604082019660008301906104d8565b01906102ee565b565b612f17612f1c91611574565b610534565b90565b612f299054612f0b565b90565b604090612f56612f5d9496959396612f4c60608401986000850190610d6f565b60208301906104d8565b01906102ee565b565b90612f72612f6c836137af565b15610744565b61353257612f81828290611602565b9081612f96612f9060006114f4565b916102eb565b148015613511575b80156134d7575b6134b457613060612fe4612fd483612fce6064612fc9612fc3610ac8565b91611091565b6111a3565b906115c0565b612fde6064611091565b906110d9565b91613002612ffb85612ff6601061158e565b61159b565b6010612dfb565b61301f61300f601061158e565b6130196064611091565b906115c0565b602061304a7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b63d5abeb0190613058610203565b958692611049565b825281806130706004820161027e565b03915afa9283156134af576130c69361309c926130959260009261347f575b506110d9565b600f612dfb565b6130ad6130a8866106a4565b612ea7565b906130b6613649565b6130bf30612eb3565b91926138a4565b6130ff6130fa6130f57f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b612ecb565b610c69565b63af14052c90803b1561347a576131239160009161311b610203565b938492611049565b82528183816131346004820161027e565b03925af1801561347557613448575b5061317d6131786131737f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610c69565b612ecb565b610c69565b6340c10f1961318a613649565b8492803b15613443576131b1600080946131bc6131a5610203565b97889687958694611049565b845260048401612ee7565b03925af1801561343e57613411575b506131d6600361060e565b926131df61147f565b5b806131f36131ed876102eb565b916102eb565b1015613403578161322061321a61321561320f6003869061061d565b90610669565b61022f565b9161022f565b146132335761322e9061151e565b6131e0565b909192935061324a6132456002612f1f565b610575565b61326361325d638eda7e69936004610cdc565b90610d28565b9061326d30612eb3565b9492813b156133fe576000613295916132a08296613289610203565b998a9788968795611049565b855260048501612f2c565b03925af19182156133f957613326926133cc575b505b6132c76132c2826106a4565b612ea7565b9060206132f47f00000000000000000000000012684d18bdba8e31936f40abce1175366874114f926106a4565b6370a082319061331b61330630612eb3565b9261330f610203565b97889485938493611049565b8352600483016104e5565b03915afa9182156133c75761334393600093613397575b506138f4565b61334b613656565b613353613649565b6133926133807f3f2c9d57c068687834f0de942a9babb9e5acab57d516d3480a3c16ee165a4273926109ac565b92613389610203565b918291826102fb565b0390a2565b6133b991935060203d81116133c0575b6133b18183610e52565b81019061105e565b913861333d565b503d6133a7565b61107d565b6133ec9060003d81116133f2575b6133e48183610e52565b810190612ed7565b386132b4565b503d6133da565b61107d565b611044565b5090506133269192506132b6565b6134319060003d8111613437575b6134298183610e52565b810190612ed7565b386131cb565b503d61341f565b61107d565b611044565b6134689060003d811161346e575b6134608183610e52565b810190612ed7565b38613143565b503d613456565b61107d565b611044565b6134a191925060203d81116134a8575b6134998183610e52565b81019061105e565b903861308f565b503d61348f565b61107d565b6134bc610203565b63199f5a0360e31b8152806134d36004820161027e565b0390fd5b508161350b6135057f00000000000000000000000000000000000000000097432b8379da85b0a000006102eb565b916102eb565b11612fa5565b508161352c613526613521612957565b6102eb565b916102eb565b11612f9e565b61353a610203565b635bfbc03960e01b8152806135516004820161027e565b0390fd5b61355d61287c565b61357661357061356b613649565b610223565b91610223565b0361357d57565b6135a6613588613649565b613590610203565b9182916332b2baa360e01b8352600483016104e5565b0390fd5b906135bb60018060a01b03916120f7565b9181191691161790565b90565b906135dd6135d86135e4926109ac565b6135c5565b82546135aa565b9055565b6135f2600061286f565b6135fd8260006135c8565b9061363161362b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0936109ac565b916109ac565b9161363a610203565b806136448161027e565b0390a3565b61365161284b565b503390565b6136b660206136847f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f854610905565b6370a08231906136ab61369630612eb3565b9261369f610203565b95869485938493611049565b8352600483016104e5565b03915afa9081156137aa5760009161377c575b50806136de6136d860006114f4565b916102eb565b116136e7575b50565b6136f96136f46002612f1f565b610575565b9063dc7d732390823b1561377757613731926137266000809461371a610203565b96879586948593611049565b8352600483016102fb565b03925af1801561377257613745575b6136e4565b6137659060003d811161376b575b61375d8183610e52565b810190612ed7565b38613740565b503d613753565b61107d565b611044565b61379d915060203d81116137a3575b6137958183610e52565b81019061105e565b386136c9565b503d61378b565b61107d565b6137b7612d47565b506137c2600361060e565b9060006137cd61147f565b5b806137e16137db866102eb565b916102eb565b101561382b578261380e6138086138036137fd6003869061061d565b90610669565b61022f565b9161022f565b146138215761381c9061151e565b6137ce565b5050505060015b90565b50915050613828565b61383d90610411565b90565b63ffffffff1690565b63ffffffff60e01b1690565b61386961386461386e92613840565b611049565b613849565b90565b60409061389b6138a29496959396613891606084019860008501906104d8565b60208301906104d8565b01906102ee565b565b6004926138de6138f295936138ed93946138c56323b872dd92949192613855565b936138ce610203565b9788956020870190815201613871565b60208201810382520383610e52565b613942565b565b9061393b6139409361392c6004949361391363a9059cbb919391613855565b9261391c610203565b9687946020860190815201612ee7565b60208201810382520383610e52565b613942565b565b90600060209161395061147f565b5061395961147f565b50828151910182855af1156139f7573d6000519061398061397a60006114f4565b916102eb565b146000146139dd575061399281613834565b3b6139a66139a060006114f4565b916102eb565b145b6139af5750565b6139bb6139d991613834565b6139c3610203565b918291635274afe760e01b8352600483016104e5565b0390fd5b6139f06139ea6001611187565b916102eb565b14156139a8565b6040513d6000823e3d90fdfea264697066735822122041e1d3d8d8580d0e9626cb8d271bb21b508138507076d840eb4db751942ef1c064736f6c63430008180033

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

0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c00000000000000000000000012684d18bdba8e31936f40abce1175366874114f

-----Decoded View---------------
Arg [0] : baseContracts_ (address): 0x5Ce899AEd04c656776148fc3b1Adbe59e5f13D5c
Arg [1] : treasury_ (address): 0x12684d18BDBA8e31936f40aBcE1175366874114f

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c
Arg [1] : 00000000000000000000000012684d18bdba8e31936f40abce1175366874114f


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.