S Price: $0.655909 (-12.29%)

Contract

0x8221312e9cF90A2B160eCdabf922408a5ef1CF9E

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer114409362025-03-03 17:32:241 min ago1741023144IN
0x8221312e...a5ef1CF9E
0 S0.0019843255.01
Deposit114405432025-03-03 17:29:423 mins ago1741022982IN
0x8221312e...a5ef1CF9E
0 S0.0042349955.01
Deposit114397942025-03-03 17:24:448 mins ago1741022684IN
0x8221312e...a5ef1CF9E
0 S0.0057745655
Approve114374072025-03-03 17:10:0823 mins ago1741021808IN
0x8221312e...a5ef1CF9E
0 S0.0052649185.625
Begin Withdrawal114360862025-03-03 17:01:4031 mins ago1741021300IN
0x8221312e...a5ef1CF9E
0 S0.0034261755
Approve114360862025-03-03 17:01:4031 mins ago1741021300IN
0x8221312e...a5ef1CF9E
0 S0.003075150
Begin Withdrawal114359542025-03-03 17:00:4932 mins ago1741021249IN
0x8221312e...a5ef1CF9E
0 S0.0033719754.12999999
Begin Withdrawal114358752025-03-03 17:00:2133 mins ago1741021221IN
0x8221312e...a5ef1CF9E
0 S0.00654087105
Begin Withdrawal114357882025-03-03 16:59:4833 mins ago1741021188IN
0x8221312e...a5ef1CF9E
0 S0.005348550
Deposit114350342025-03-03 16:54:3139 mins ago1741020871IN
0x8221312e...a5ef1CF9E
0 S0.0055939955
Begin Withdrawal114348742025-03-03 16:53:1640 mins ago1741020796IN
0x8221312e...a5ef1CF9E
0 S0.0029463355.01
Begin Withdrawal114348022025-03-03 16:52:4940 mins ago1741020769IN
0x8221312e...a5ef1CF9E
0 S0.0051160455.01
Approve114335682025-03-03 16:44:0549 mins ago1741020245IN
0x8221312e...a5ef1CF9E
0 S0.0028906955
Deposit114326722025-03-03 16:38:2455 mins ago1741019904IN
0x8221312e...a5ef1CF9E
0 S0.0050528755.02
Deposit114319932025-03-03 16:34:061 hrs ago1741019646IN
0x8221312e...a5ef1CF9E
0 S0.0057387555
Approve114310722025-03-03 16:28:201 hr ago1741019300IN
0x8221312e...a5ef1CF9E
0 S0.0032732960.5
Deposit114309032025-03-03 16:27:091 hr ago1741019229IN
0x8221312e...a5ef1CF9E
0 S0.0060612466
Deposit114307102025-03-03 16:25:591 hr ago1741019159IN
0x8221312e...a5ef1CF9E
0 S0.007548268.75
Approve114306392025-03-03 16:25:351 hr ago1741019135IN
0x8221312e...a5ef1CF9E
0 S0.00683135111.05
Begin Withdrawal114300862025-03-03 16:21:551 hr ago1741018915IN
0x8221312e...a5ef1CF9E
0 S0.0088464282.73333333
Deposit114290672025-03-03 16:15:211 hr ago1741018521IN
0x8221312e...a5ef1CF9E
0 S0.0054734355
Approve114265602025-03-03 15:59:221 hr ago1741017562IN
0x8221312e...a5ef1CF9E
0 S0.0031304557.86
Deposit114265252025-03-03 15:59:081 hr ago1741017548IN
0x8221312e...a5ef1CF9E
0 S0.0047856655
Deposit114258352025-03-03 15:54:381 hr ago1741017278IN
0x8221312e...a5ef1CF9E
0 S0.007281660
Deposit114254582025-03-03 15:52:041 hr ago1741017124IN
0x8221312e...a5ef1CF9E
0 S0.0057879855
View all transactions

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

Contract Source Code Verified (Exact Match)

Contract Name:
VoteEscrowedSTTX

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
No with 200 runs

Other Settings:
paris EvmVersion
File 1 of 33 : VoteEscrowedSTTX.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 {IERC20TokenRebase} from "./interface/IERC20TokenRebase.sol";
import {IVoteEscrowedSTTX} from "./interface/IVoteEscrowedSTTX.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20 as IERC20Safe} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/**
 * @title VoteEscrowedSTTX
 * @dev Time-locked governance token
 * @notice Lock and vote manager
 */
contract VoteEscrowedSTTX is
    Ownable,
    ReentrancyGuard,
    IERC20Custom,
    IVoteEscrowedSTTX
{
    /*//////////////////////////////////////////////////////////////
                        TOKEN CONFIGURATION
    //////////////////////////////////////////////////////////////*/
    /// @notice Base STTX token contract
    IERC20TokenRebase public immutable sttx;
    /// @notice Token name
    string private _name;
    /// @notice Token symbol
    string private _symbol;
    /// @notice Token decimal places
    /// @dev Fixed at 18 decimals
    uint8 private constant DECIMALS = 18;
    /*//////////////////////////////////////////////////////////////
                        TOKEN STATE TRACKING
    //////////////////////////////////////////////////////////////*/
    /// @notice Total supply of veSTTX tokens
    uint256 private _totalSupply;
    /// @notice User token balances
    /// @dev Tracks individual account balances
    mapping(address => uint256) private _balances;
    /// @notice Token spending allowances
    /// @dev Nested mapping of owner → spender → allowance
    mapping(address => mapping(address => uint256)) private _allowances;
    /*//////////////////////////////////////////////////////////////
                        WITHDRAWAL CONFIGURATION
    //////////////////////////////////////////////////////////////*/
    /// @notice Delay before withdrawal becomes available
    /// @dev Default: 7 days
    uint256 public withdrawalDelay = 7 days;
    /// @notice Window duration for completing withdrawal
    /// @dev Default: 21 hours
    uint256 public withdrawalWindow = 21 hours;
    /*//////////////////////////////////////////////////////////////
                        WITHDRAWAL STATE TRACKING
    //////////////////////////////////////////////////////////////*/
    /// @notice Pending withdrawal amounts per account
    mapping(address => uint256) public withdrawalAmounts;
    /// @notice Withdrawal timestamp for each account
    mapping(address => uint256) public withdrawalTimestamps;
    /// @notice Withdrawal slot tracking
    mapping(uint256 => uint256) public withdrawalSlots;
    /*//////////////////////////////////////////////////////////////
                        ACCESS CONTROL STATE
    //////////////////////////////////////////////////////////////*/
    /// @notice Mapping of approved token spenders
    /// @dev Allows controlled token spending
    mapping(address => bool) public approvedSpenders;
    /*//////////////////////////////////////////////////////////////
                            EVENTS
    //////////////////////////////////////////////////////////////*/
    /// @notice Emitted when a spender is approved
    event SpenderApproved(address indexed spender);
    /// @notice Emitted when a spender is revoked
    event SpenderRevoked(address indexed spender);
    /// @notice Emitted when withdrawal delay is decreased
    event WithdrawalDelayDecreased(uint256 newDelay);
    /// @notice Emitted when withdrawal window is increased
    event WithdrawalWindowIncreased(uint256 newWindow);
    /// @notice Emitted when a withdrawal is initiated
    event WithdrawalInitiated(
        address indexed account,
        uint256 amount,
        uint256 timestamp
    );
    /// @notice Emitted when a withdrawal is completed
    event WithdrawalCompleted(address indexed account, uint256 amount);
    /*//////////////////////////////////////////////////////////////
                            CUSTOM ERRORS
    //////////////////////////////////////////////////////////////*/
    /// @notice Thrown when a zero address is provided
    error ZeroAddress();
    /// @notice Thrown when a zero amount is provided
    error ZeroAmount();
    /// @notice Thrown when an invalid withdrawal delay is set
    error InvalidWithdrawalDelay();
    /// @notice Thrown when an invalid withdrawal window is set
    error InvalidWithdrawalWindow();
    /// @notice Thrown when an invalid sender is detected
    error InvalidSender(address sender);
    /// @notice Thrown when an invalid receiver is detected
    error InvalidReceiver(address receiver);
    /// @notice Thrown when an invalid approver is detected
    error InvalidApprover(address approver);
    /// @notice Thrown when an invalid spender is detected
    error InvalidSpender(address spender);
    /// @notice Thrown when balance is insufficient
    error InsufficientBalance();
    /// @notice Thrown when allowance is insufficient
    error InsufficientAllowance(
        address spender,
        uint256 allowance,
        uint256 needed
    );
    /// @notice Thrown when a spender is not authorized
    error SpenderNotAuthorized();
    /// @notice Thrown when no withdrawal is initiated
    error WithdrawalNotInitiated();
    /// @notice Thrown when withdrawal window is not open
    error WithdrawalWindowNotOpenYet();
    /// @notice Thrown when withdrawal window is closed
    error WithdrawalWindowAlreadyClosed();

    /*//////////////////////////////////////////////////////////////
                            CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Initializes the veSTTX token
     * @param name_ Token name
     * @param symbol_ Token symbol
     * @param baseContracts_ BaseContracts instance for protocol integration
     *
     * Requirements:
     * · STTX contract address must be non-zero
     *
     * Effects:
     * · Sets token metadata
     * · Sets base STTX token reference
     */
    constructor(
        string memory name_,
        string memory symbol_,
        IBaseContracts baseContracts_
    ) {
        _ensureNonzeroAddress(address(baseContracts_));
        sttx = baseContracts_.sttx();
        _ensureNonzeroAddress(address(sttx));
        _name = name_;
        _symbol = symbol_;
    }

    /*//////////////////////////////////////////////////////////////
                        EXTERNAL FUNCTIONS · ACCESS CONTROL
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Approves a spender to spend tokens on behalf of the owner
     * @param spender Address of the approved spender
     *
     * Requirements:
     * · Only callable by contract owner
     * · Validates non-zero address for spender
     *
     * Effects:
     * · Sets spender approval
     */
    function approveSpender(address spender) external onlyOwner {
        _ensureNonzeroAddress(spender);
        approvedSpenders[spender] = true;
        emit SpenderApproved(spender);
    }

    /**
     * @notice Revokes a spender's approval to spend tokens on behalf of the owner
     * @param spender Address of the revoked spender
     *
     * Requirements:
     * · Only callable by contract owner
     * · Validates non-zero address for spender
     *
     * Effects:
     * · Sets spender approval
     */
    function revokeSpender(address spender) external onlyOwner {
        _ensureNonzeroAddress(spender);
        approvedSpenders[spender] = false;
        emit SpenderRevoked(spender);
    }

    /*//////////////////////////////////////////////////////////////
                        EXTERNAL FUNCTIONS · WITHDRAWAL SETTINGS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Decreases the withdrawal delay
     * @param newDelay New withdrawal delay
     *
     * Requirements:
     * · Only callable by contract owner
     * · New delay must be less than the current delay
     *
     * Effects:
     * · Sets the new withdrawal delay
     */
    function decreaseWithdrawalDelay(uint256 newDelay) external onlyOwner {
        if (newDelay >= withdrawalDelay) revert InvalidWithdrawalDelay();
        withdrawalDelay = newDelay;
        emit WithdrawalDelayDecreased(newDelay);
    }

    /**
     * @notice Increases the withdrawal window
     * @param newWindow New withdrawal window
     *
     * Requirements:
     * · Only callable by contract owner
     * · New window must be greater than the current window
     *
     * Effects:
     * · Sets the new withdrawal window
     */
    function increaseWithdrawalWindow(uint256 newWindow) external onlyOwner {
        if (newWindow <= withdrawalWindow) revert InvalidWithdrawalWindow();
        withdrawalWindow = newWindow;
        emit WithdrawalWindowIncreased(newWindow);
    }

    /*//////////////////////////////////////////////////////////////
                        EXTERNAL FUNCTIONS · CORE OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Deposits tokens into the contract
     * @param to Address to deposit tokens to
     * @param amount Amount of tokens to deposit
     *
     * Requirements:
     * · To address must be non-zero
     * · Amount must be non-zero
     *
     * Effects:
     * · Increases the to address's balance
     * · Increases the total supply
     * · Transfers tokens from the sender to the contract
     */
    function deposit(address to, uint256 amount) external nonReentrant {
        _ensureNonzeroAddress(to);
        _ensureNonzeroAmount(amount);
        _balances[to] += amount;
        _totalSupply += amount;
        SafeERC20.safeTransferFrom(
            IERC20Safe(address(sttx)),
            _msgSender(),
            address(this),
            amount
        );
        emit Transfer(address(0), to, amount);
    }

    /**
     * @notice Initiates a withdrawal
     * @param amount Amount of tokens to withdraw
     *
     * Requirements:
     * · Amount must be non-zero
     * · Amount must be less than or equal to the sender's balance
     *
     * Effects:
     * · Decreases the sender's balance
     * · Decreases the total supply
     * · Sets the withdrawal timestamp and amount
     */
    function beginWithdrawal(uint256 amount) external nonReentrant {
        _ensureNonzeroAmount(amount);
        address account = _msgSender();
        if (amount > balanceOf(account)) revert InsufficientBalance();
        _decreaseWithdrawalSlot(
            withdrawalTimestamps[account],
            withdrawalAmounts[account]
        );
        uint256 time = block.timestamp + withdrawalDelay;
        withdrawalTimestamps[account] = time;
        withdrawalAmounts[account] = amount;
        _increaseWithdrawalSlot(time, amount);
        emit WithdrawalInitiated(account, amount, time);
    }

    /**
     * @notice Completes a withdrawal
     *
     * Requirements:
     * · Withdrawal must be initiated
     * · Withdrawal window must be open
     * · Withdrawal amount must be less than or equal to the sender's balance
     *
     * Effects:
     * · Decreases the sender's balance
     * · Decreases the total supply
     * · Transfers tokens from the contract to the sender
     */
    function withdraw() external nonReentrant {
        address account = _msgSender();
        uint256 currentTime = block.timestamp;
        uint256 minTime = withdrawalTimestamps[account];
        if (minTime == 0) revert WithdrawalNotInitiated();
        if (currentTime <= minTime) revert WithdrawalWindowNotOpenYet();
        if (currentTime >= minTime + withdrawalWindow)
            revert WithdrawalWindowAlreadyClosed();
        uint256 amount = withdrawalAmounts[account];
        if (amount > balanceOf(account)) revert InsufficientBalance();
        _decreaseWithdrawalSlot(minTime, amount);
        withdrawalTimestamps[account] = 0;
        withdrawalAmounts[account] = 0;
        _balances[account] -= amount;
        _totalSupply -= amount;
        sttx.rebase();
        SafeERC20.safeTransfer(IERC20Safe(address(sttx)), account, amount);
        emit WithdrawalCompleted(account, amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @notice Transfers tokens from one address to another
     * @param to Address to transfer tokens to
     * @param value Amount of tokens to transfer
     *
     * Requirements:
     * · To address must be non-zero
     * · Value must be non-zero
     *
     * Effects:
     * · Decreases the sender's balance
     * · Increases the to address's balance
     */
    function transfer(address to, uint256 value) external returns (bool) {
        _transfer(_msgSender(), to, value);
        return true;
    }

    /**
     * @notice Approves a spender to spend tokens on behalf of the owner
     * @param spender Address of the approved spender
     * @param value Amount of tokens to approve
     *
     * Requirements:
     * · Spender must be approved
     *
     * Effects:
     * · Sets the spender's allowance
     */
    function approve(address spender, uint256 value) external returns (bool) {
        if (!isApprovedSpender(spender)) revert SpenderNotAuthorized();
        _approve(_msgSender(), spender, value);
        return true;
    }

    /**
     * @notice Transfers tokens from one address to another using an allowance
     * @param from Address to transfer tokens from
     * @param to Address to transfer tokens to
     * @param value Amount of tokens to transfer
     *
     * Requirements:
     * · From address must be non-zero
     * · To address must be non-zero
     * · Value must be non-zero
     * · Spender must be approved
     *
     * Effects:
     * · Decreases the from address's balance
     * · Increases the to address's balance
     * · Decreases the spender's allowance
     */
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @notice Returns the token name
     *
     * Returns:
     * · Token name
     */
    function name() external view returns (string memory) {
        return _name;
    }

    /**
     * @notice Returns the token symbol
     *
     * Returns:
     * · Token symbol
     */
    function symbol() external view returns (string memory) {
        return _symbol;
    }

    /**
     * @notice Returns the total supply of tokens
     *
     * Returns:
     * · Total supply
     */
    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @notice Returns the withdrawal status for an account
     * @param account Address to retrieve the withdrawal status for
     *
     * Returns:
     * · Withdrawal amount
     * · Withdrawal timestamp
     * · Whether the withdrawal is withdrawable
     */
    function getWithdrawalStatus(
        address account
    )
        external
        view
        returns (uint256 amount, uint256 timestamp, bool isWithdrawable)
    {
        amount = withdrawalAmounts[account];
        timestamp = withdrawalTimestamps[account];
        uint256 currentTime = block.timestamp;
        isWithdrawable =
            timestamp != 0 &&
            currentTime > timestamp &&
            currentTime < timestamp + withdrawalWindow;
    }

    /**
     * @notice Returns the number of decimal places for the token
     *
     * Returns:
     * · Number of decimal places
     */
    function decimals() external pure returns (uint8) {
        return DECIMALS;
    }

    /**
     * @notice Returns the balance of an account
     * @param account Address to retrieve the balance for
     *
     * Returns:
     * · Balance
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @notice Returns the allowance for a spender
     * @param owner Address of the owner
     * @param spender Address of the spender
     *
     * Returns:
     * · Allowance
     */
    function allowance(
        address owner,
        address spender
    ) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @notice Returns whether a spender is approved
     * @param spender Address of the spender
     *
     * Returns:
     * · Whether the spender is approved
     */
    function isApprovedSpender(address spender) public view returns (bool) {
        return approvedSpenders[spender];
    }

    /**
     * @notice Returns the withdrawal slot for a timestamp
     * @param time Timestamp to retrieve the withdrawal slot for
     *
     * Returns:
     * · Withdrawal slot
     */
    function getWithdrawalSlot(uint256 time) public view returns (uint256) {
        return time / withdrawalWindow;
    }

    /**
     * @notice Returns the total amount of tokens in the withdrawal slot
     * @param slot The withdrawal slot to check
     * @return Total amount of tokens in the slot
     */
    function getWithdrawalSlotAmount(
        uint256 slot
    ) public view returns (uint256) {
        return withdrawalSlots[slot];
    }

    /**
     * @notice Returns all withdrawal slots within a time range
     * @param startTime Start of the time range
     * @param endTime End of the time range
     * @return slots Array of slot numbers
     * @return amounts Array of amounts in each slot
     */
    function getWithdrawalSlotRange(
        uint256 startTime,
        uint256 endTime
    ) public view returns (uint256[] memory slots, uint256[] memory amounts) {
        uint256 startSlot = getWithdrawalSlot(startTime);
        uint256 endSlot = getWithdrawalSlot(endTime);
        uint256 slotCount = endSlot - startSlot + 1;
        slots = new uint256[](slotCount);
        amounts = new uint256[](slotCount);
        for (uint256 i = 0; i < slotCount; i++) {
            uint256 slot = startSlot + i;
            slots[i] = slot;
            amounts[i] = withdrawalSlots[slot];
        }
    }

    /**
     * @notice Returns the current withdrawal slot and the next slot
     * @return currentSlot Current withdrawal slot
     * @return currentAmount Amount in current slot
     * @return nextSlot Next withdrawal slot
     * @return nextAmount Amount in next slot
     */
    function getCurrentAndNextWithdrawalSlots()
        public
        view
        returns (
            uint256 currentSlot,
            uint256 currentAmount,
            uint256 nextSlot,
            uint256 nextAmount
        )
    {
        currentSlot = getWithdrawalSlot(block.timestamp);
        nextSlot = currentSlot + 1;
        currentAmount = withdrawalSlots[currentSlot];
        nextAmount = withdrawalSlots[nextSlot];
    }

    /*//////////////////////////////////////////////////////////////
                            PRIVATE FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Transfers tokens from one address to another
     * @param from Address to transfer tokens from
     * @param to Address to transfer tokens to
     * @param value Amount of tokens to transfer
     *
     * Effects:
     * · Decreases the from address's balance
     * · Increases the to address's balance
     * · Emits a Transfer event
     */
    function _transfer(address from, address to, uint256 value) private {
        if (from == address(0)) revert InvalidSender(address(0));
        if (to == address(0)) revert InvalidReceiver(address(0));
        _update(from, to, value);
    }

    /**
     * @notice Updates the balances of two addresses
     * @param from Address to decrease the balance of
     * @param to Address to increase the balance of
     * @param value Amount of tokens to transfer
     *
     * Effects:
     * · Decreases the from address's balance
     * · Increases the to address's balance
     * · Emits a Transfer event
     */
    function _update(address from, address to, uint256 value) private {
        if (from == address(0)) {
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert InsufficientBalance();
            }
            unchecked {
                _balances[from] = fromBalance - value;
            }
        }
        if (to == address(0)) {
            unchecked {
                _totalSupply -= value;
            }
        } else {
            unchecked {
                _balances[to] += value;
            }
        }
        emit Transfer(from, to, value);
    }

    /**
     * @notice Approves a spender to spend tokens on behalf of the owner
     * @param owner Address of the owner
     * @param spender Address of the approved spender
     * @param value Amount of tokens to approve
     *
     * Effects:
     * · Sets the spender's allowance
     */
    function _approve(address owner, address spender, uint256 value) private {
        _approve(owner, spender, value, true);
    }

    /**
     * @notice Approves a spender to spend tokens on behalf of the owner
     * @param owner Address of the owner
     * @param spender Address of the approved spender
     * @param value Amount of tokens to approve
     * @param emitEvent Whether to emit an Approval event
     *
     * Effects:
     * · Sets the spender's allowance
     */
    function _approve(
        address owner,
        address spender,
        uint256 value,
        bool emitEvent
    ) private {
        if (owner == address(0)) revert InvalidApprover(address(0));
        if (spender == address(0)) revert InvalidSpender(address(0));
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @notice Spends an allowance
     * @param owner Address of the owner
     * @param spender Address of the spender
     * @param value Amount of tokens to spend
     *
     * Effects:
     * · Decreases the spender's allowance
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 value
    ) private {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }

    /**
     * @notice Increases the withdrawal slot for a timestamp
     * @param time Timestamp to increase the withdrawal slot for
     * @param amount Amount of tokens to increase the withdrawal slot by
     *
     * Effects:
     * · Increases the withdrawal slot
     */
    function _increaseWithdrawalSlot(uint256 time, uint256 amount) private {
        uint256 slot = getWithdrawalSlot(time);
        withdrawalSlots[slot] += amount;
    }

    /**
     * @notice Decreases the withdrawal slot for a timestamp
     * @param time Timestamp to decrease the withdrawal slot for
     * @param amount Amount of tokens to decrease the withdrawal slot by
     *
     * Effects:
     * · Decreases the withdrawal slot
     */
    function _decreaseWithdrawalSlot(uint256 time, uint256 amount) private {
        if (time == 0 || amount == 0) return;
        uint256 slot = getWithdrawalSlot(time);
        if (amount > withdrawalSlots[slot]) {
            withdrawalSlots[slot] = 0;
            return;
        }
        withdrawalSlots[slot] -= amount;
    }

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

    // Validates that an amount is greater than zero
    function _ensureNonzeroAmount(uint256 amount) private pure {
        if (amount == 0) {
            revert ZeroAmount();
        }
    }
}

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":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"contract IBaseContracts","name":"baseContracts_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidWithdrawalDelay","type":"error"},{"inputs":[],"name":"InvalidWithdrawalWindow","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SpenderNotAuthorized","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"UnauthorizedAccount","type":"error"},{"inputs":[],"name":"WithdrawalNotInitiated","type":"error"},{"inputs":[],"name":"WithdrawalWindowAlreadyClosed","type":"error"},{"inputs":[],"name":"WithdrawalWindowNotOpenYet","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"spender","type":"address"}],"name":"SpenderApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"spender","type":"address"}],"name":"SpenderRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDelay","type":"uint256"}],"name":"WithdrawalDelayDecreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"WithdrawalInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newWindow","type":"uint256"}],"name":"WithdrawalWindowIncreased","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"approveSpender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedSpenders","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"beginWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"newDelay","type":"uint256"}],"name":"decreaseWithdrawalDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentAndNextWithdrawalSlots","outputs":[{"internalType":"uint256","name":"currentSlot","type":"uint256"},{"internalType":"uint256","name":"currentAmount","type":"uint256"},{"internalType":"uint256","name":"nextSlot","type":"uint256"},{"internalType":"uint256","name":"nextAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"getWithdrawalSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot","type":"uint256"}],"name":"getWithdrawalSlotAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"getWithdrawalSlotRange","outputs":[{"internalType":"uint256[]","name":"slots","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getWithdrawalStatus","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isWithdrawable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newWindow","type":"uint256"}],"name":"increaseWithdrawalWindow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"isApprovedSpender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"revokeSpender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sttx","outputs":[{"internalType":"contract IERC20TokenRebase","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"withdrawalAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawalSlots","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"withdrawalTimestamps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalWindow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60a06040523462000056576200001f6200001862000254565b91620006ab565b620000296200005c565b612956620009f28239608051818181610da3015281816114c70152818161153b0152611763015261295690f35b62000062565b60405190565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b90620000939062000067565b810190811060018060401b03821117620000ac57604052565b62000071565b90620000c9620000c16200005c565b928362000087565b565b600080fd5b600080fd5b600080fd5b600080fd5b60018060401b038111620000fe57620000fa60209162000067565b0190565b62000071565b60005b83811062000119575050906000910152565b80602091830151818501520162000107565b90929192620001446200013e82620000df565b620000b2565b938185526020850190828401116200016357620001619262000104565b565b620000da565b9080601f830112156200018a5781602062000187935191016200012b565b90565b620000d5565b60018060a01b031690565b620001a69062000190565b90565b620001b4906200019b565b90565b620001c281620001a9565b03620001ca57565b600080fd5b90505190620001de82620001b7565b565b90916060828403126200024e57600082015160018060401b0381116200024857836200020e91840162000169565b9260208301519060018060401b038211620002425762000235816200023f93860162000169565b93604001620001cf565b90565b620000d0565b620000d0565b620000cb565b6200027762003348803803806200026b81620000b2565b928339810190620001e0565b909192565b60001b90565b9062000291600019916200027c565b9181191691161790565b90565b90565b90565b620002bd620002b7620002c3926200029b565b620002a1565b6200029e565b90565b90565b90620002e3620002dd620002eb92620002a4565b620002c6565b825462000282565b9055565b90565b6200030b620003056200031192620002ef565b620002a1565b6200029e565b90565b906200032e620003286200033692620002f2565b620002c6565b825462000282565b9055565b620003536200034d620003599262000190565b620002a1565b62000190565b90565b62000367906200033a565b90565b62000375906200035c565b90565b60e01b90565b62000389906200019b565b90565b62000397816200037e565b036200039f57565b600080fd5b90505190620003b3826200038c565b565b90602082820312620003d257620003cf91600001620003a4565b90565b620000cb565b60000190565b620003e86200005c565b3d6000823e3d90fd5b620003fd90516200037e565b90565b6200040b906200035c565b90565b5190565b634e487b7160e01b600052602260045260246000fd5b90600160028304921680156200044b575b60208310146200044557565b62000412565b91607f169162000439565b600052602060002090565b601f602091010490565b1b90565b919060086200048f91029162000488600019846200046b565b926200046b565b9181191691161790565b620004b2620004ac620004b8926200029e565b620002a1565b6200029e565b90565b9190620004d6620004d0620004df9362000499565b620002c6565b9083546200046f565b9055565b600090565b620004fe91620004f7620004e3565b91620004bb565b565b5b8181106200050d575050565b806200051d6000600193620004e8565b0162000501565b9190601f811162000535575b505050565b620005446200056f9362000456565b906020620005528462000461565b8301931062000578575b620005679062000461565b019062000500565b38808062000530565b915062000567819290506200055c565b1c90565b906200059f906000199060080262000588565b191690565b81620005b0916200058c565b906002021790565b90620005c4816200040e565b9060018060401b0382116200069757620005eb82620005e4855462000428565b8562000524565b602090601f83116001146200062557918091620006139360009262000618575b5050620005a4565b90555b565b909150015138806200060b565b601f19831691620006368562000456565b9260005b8181106200067e5750916002939185600196941062000661575b5050500201905562000616565b62000673910151601f8416906200058c565b905538808062000654565b919360206001819287870151815501950192016200063a565b62000071565b90620006a991620005b8565b565b916020620006fc6200071592620006c1620007b7565b620006d162093a806007620002c9565b620006e162012750600862000314565b620006f6620006f0826200036a565b62000894565b6200036a565b63ec4d8019906200070c6200005c565b93849262000378565b825281806200072760048201620003d8565b03915afa928315620007b1576200077a9362000772926000916200077c575b506080526200076a620007646200075e6080620003f1565b62000400565b62000894565b60026200069d565b60036200069d565b565b620007a2915060203d8111620007a9575b62000799818362000087565b810190620003b5565b3862000746565b503d6200078d565b620003de565b620007c1620007c3565b565b620007cd62000829565b565b90565b620007eb620007e5620007f192620007cf565b620002a1565b6200029e565b90565b620008006001620007d2565b90565b906200081d62000817620008259262000499565b620002c6565b825462000282565b9055565b620008336200084b565b6200084962000841620007f4565b600162000803565b565b6200085f62000859620008e9565b62000984565b565b90565b6200087d62000877620008839262000861565b620002a1565b62000190565b90565b620008919062000864565b90565b620008b5620008ae620008a8600062000886565b6200019b565b916200019b565b14620008bd57565b620008c76200005c565b63d92e233d60e01b815280620008e060048201620003d8565b0390fd5b600090565b620008f3620008e4565b503390565b60001c90565b60018060a01b031690565b620009186200091e91620008f8565b620008fe565b90565b6200092d905462000909565b90565b906200094360018060a01b03916200027c565b9181191691161790565b62000958906200035c565b90565b90565b90620009786200097262000980926200094d565b6200095b565b825462000930565b9055565b62000990600062000921565b6200099d8260006200095e565b90620009d5620009ce7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0936200094d565b916200094d565b91620009e06200005c565b80620009ec81620003d8565b0390a356fe60806040526004361015610013575b610e5c565b61001e60003561021d565b806306fdde0314610218578063095ea7b314610213578063099a0aae1461020e578063141ebd831461020957806318160ddd146102045780632366f298146101ff57806323b872dd146101fa578063313ce567146101f5578063382e7244146101f0578063399231e3146101eb5780633ccfd60b146101e657806347e7ef24146101e15780635bb5d99d146101dc5780635dea7556146101d757806370a08231146101d2578063715018a6146101cd5780637491687e146101c857806375b8b52f146101c357806380c62199146101be5780638da5cb5b146101b957806395d89b41146101b4578063a3760758146101af578063a3ef270b146101aa578063a7ab6961146101a5578063a9059cbb146101a0578063ae76cf2a1461019b578063c303a6a714610196578063c7f71b8a14610191578063d19bd0a71461018c578063dd62ed3e14610187578063ec4d8019146101825763f2fde38b0361000e57610e29565b610df4565b610d6b565b610d08565b610cc3565b610c8e565b610c5b565b610c25565b610bf0565b610bab565b610b76565b610b27565b610af2565b610a9c565b610a69565b610a31565b6109cb565b610996565b61095f565b61084a565b610816565b6107e3565b6107ae565b61070c565b610679565b61061a565b6105a6565b610532565b6104fd565b610411565b6103b6565b6102c9565b60e01c90565b60405190565b600080fd5b600080fd5b600091031261023e57565b61022e565b5190565b60209181520190565b60005b838110610264575050906000910152565b806020918301518185015201610253565b601f801991011690565b61029e6102a76020936102ac9361029581610243565b93848093610247565b95869101610250565b610275565b0190565b6102c6916020820191600081840391015261027f565b90565b346102f9576102d9366004610233565b6102f56102e4610fc3565b6102ec610223565b918291826102b0565b0390f35b610229565b60018060a01b031690565b610312906102fe565b90565b61031e81610309565b0361032557565b600080fd5b9050359061033782610315565b565b90565b61034581610339565b0361034c57565b600080fd5b9050359061035e8261033c565b565b9190604083820312610389578061037d610386926000860161032a565b93602001610351565b90565b61022e565b151590565b61039c9061038e565b9052565b91906103b490600060208501940190610393565b565b346103e7576103e36103d26103cc366004610360565b90610fde565b6103da610223565b918291826103a0565b0390f35b610229565b90602082820312610406576104039160000161032a565b90565b61022e565b60000190565b3461043f576104296104243660046103ec565b6110f8565b610431610223565b8061043b8161040b565b0390f35b610229565b90565b61045b610456610460926102fe565b610444565b6102fe565b90565b61046c90610447565b90565b61047890610463565b90565b906104859061046f565b600052602052604060002090565b1c90565b90565b6104aa9060086104af9302610493565b610497565b90565b906104bd915461049a565b90565b6104d7906104d2600a9160009261047b565b6104b2565b90565b6104e390610339565b9052565b91906104fb906000602085019401906104da565b565b3461052d576105296105186105133660046103ec565b6104c0565b610520610223565b918291826104e7565b0390f35b610229565b3461056257610542366004610233565b61055e61054d61112f565b610555610223565b918291826104e7565b0390f35b610229565b61059d6105a494610593606094989795610589608086019a60008701906104da565b60208501906104da565b60408301906104da565b01906104da565b565b346105da576105b6366004610233565b6105d66105c161119f565b906105cd949294610223565b94859485610567565b0390f35b610229565b9091606082840312610615576106126105fb846000850161032a565b93610609816020860161032a565b93604001610351565b90565b61022e565b3461064b576106476106366106303660046105df565b9161120d565b61063e610223565b918291826103a0565b0390f35b610229565b60ff1690565b61065f90610650565b9052565b919061067790600060208501940190610656565b565b346106a957610689366004610233565b6106a561069461126d565b61069c610223565b91829182610663565b0390f35b610229565b906106b89061046f565b600052602052604060002090565b60ff1690565b6106dc9060086106e19302610493565b6106c6565b90565b906106ef91546106cc565b90565b61070990610704600c916000926106ae565b6106e4565b90565b3461073c576107386107276107223660046103ec565b6106f2565b61072f610223565b918291826103a0565b0390f35b610229565b9060208282031261075b5761075891600001610351565b90565b61022e565b61077461076f61077992610339565b610444565b610339565b90565b9061078690610760565b600052602052604060002090565b6107ab906107a6600b9160009261077c565b6104b2565b90565b346107de576107da6107c96107c4366004610741565b610794565b6107d1610223565b918291826104e7565b0390f35b610229565b34610811576107f3366004610233565b6107fb6116ce565b610803610223565b8061080d8161040b565b0390f35b610229565b346108455761082f610829366004610360565b906117ff565b610837610223565b806108418161040b565b0390f35b610229565b346108785761086261085d366004610741565b6118a9565b61086a610223565b806108748161040b565b0390f35b610229565b91906040838203126108a6578061089a6108a39260008601610351565b93602001610351565b90565b61022e565b5190565b60209181520190565b60200190565b6108c790610339565b9052565b906108d8816020936108be565b0190565b60200190565b906108ff6108f96108f2846108ab565b80936108af565b926108b8565b9060005b8181106109105750505090565b90919261092961092360019286516108cb565b946108dc565b9101919091610903565b909161094e61095c93604084019084820360008601526108e2565b9160208184039101526108e2565b90565b346109915761097861097236600461087d565b90611981565b9061098d610984610223565b92839283610933565b0390f35b610229565b346109c6576109c26109b16109ac3660046103ec565b611a5b565b6109b9610223565b918291826104e7565b0390f35b610229565b346109f9576109db366004610233565b6109e3611aa0565b6109eb610223565b806109f58161040b565b0390f35b610229565b604090610a28610a2f9496959396610a1e606084019860008501906104da565b60208301906104da565b0190610393565b565b34610a6457610a60610a4c610a473660046103ec565b611aaa565b610a57939193610223565b938493846109fe565b0390f35b610229565b34610a9757610a81610a7c366004610741565b611bfc565b610a89610223565b80610a938161040b565b0390f35b610229565b34610aca57610ab4610aaf366004610741565b611d5c565b610abc610223565b80610ac68161040b565b0390f35b610229565b610ad890610309565b9052565b9190610af090600060208501940190610acf565b565b34610b2257610b02366004610233565b610b1e610b0d611d98565b610b15610223565b91829182610adc565b0390f35b610229565b34610b5757610b37366004610233565b610b53610b42611dae565b610b4a610223565b918291826102b0565b0390f35b610229565b610b7390610b6e60099160009261047b565b6104b2565b90565b34610ba657610ba2610b91610b8c3660046103ec565b610b5c565b610b99610223565b918291826104e7565b0390f35b610229565b34610bdb57610bd7610bc6610bc1366004610741565b611dfc565b610bce610223565b918291826104e7565b0390f35b610229565b610bed60076000906104b2565b90565b34610c2057610c00366004610233565b610c1c610c0b610be0565b610c13610223565b918291826104e7565b0390f35b610229565b34610c5657610c52610c41610c3b366004610360565b90611e1c565b610c49610223565b918291826103a0565b0390f35b610229565b34610c8957610c73610c6e3660046103ec565b611eb2565b610c7b610223565b80610c858161040b565b0390f35b610229565b34610cbe57610cba610ca9610ca43660046103ec565b611ede565b610cb1610223565b918291826103a0565b0390f35b610229565b34610cf357610cef610cde610cd9366004610741565b611efd565b610ce6610223565b918291826104e7565b0390f35b610229565b610d0560086000906104b2565b90565b34610d3857610d18366004610233565b610d34610d23610cf8565b610d2b610223565b918291826104e7565b0390f35b610229565b9190604083820312610d665780610d5a610d63926000860161032a565b9360200161032a565b90565b61022e565b34610d9c57610d98610d87610d81366004610d3d565b90611f34565b610d8f610223565b918291826104e7565b0390f35b610229565b7f000000000000000000000000000000000000000000000000000000000000000090565b610dce90610463565b90565b610dda90610dc5565b9052565b9190610df290600060208501940190610dd1565b565b34610e2457610e04366004610233565b610e20610e0f610da1565b610e17610223565b91829182610dde565b0390f35b610229565b34610e5757610e41610e3c3660046103ec565b611fca565b610e49610223565b80610e538161040b565b0390f35b610229565b600080fd5b606090565b634e487b7160e01b600052602260045260246000fd5b9060016002830492168015610e9c575b6020831014610e9757565b610e66565b91607f1691610e8c565b60209181520190565b600052602060002090565b9060009291805490610ed5610ece83610e7c565b8094610ea6565b91600181169081600014610f2e5750600114610ef1575b505050565b610efe9192939450610eaf565b916000925b818410610f165750500190388080610eec565b60018160209295939554848601520191019290610f03565b92949550505060ff1916825215156020020190388080610eec565b90610f5391610eba565b90565b634e487b7160e01b600052604160045260246000fd5b90610f7690610275565b810190811067ffffffffffffffff821117610f9057604052565b610f56565b90610fb5610fae92610fa5610223565b93848092610f49565b0383610f6c565b565b610fc090610f95565b90565b610fcb610e61565b50610fd66002610fb7565b90565b600090565b610fe6610fd9565b50610ff9610ff382611ede565b1561038e565b6110165761101191611009611fd5565b919091611fe2565b600190565b61101e610223565b633b09f10560e01b8152806110356004820161040b565b0390fd5b61104a90611045611ff2565b611097565b565b60001b90565b9061105e60ff9161104c565b9181191691161790565b6110719061038e565b90565b90565b9061108c61108761109392611068565b611074565b8254611052565b9055565b6110a081612047565b6110b660016110b1600c84906106ae565b611077565b6110e07f3584ac55fd91fcf5efce973892cccf98c9b1bc944e64135fc1b93132a8e3933e9161046f565b906110e9610223565b806110f38161040b565b0390a2565b61110190611039565b565b600090565b60001c90565b61111a61111f91611108565b610497565b90565b61112c905461110e565b90565b611137611103565b506111426004611122565b90565b90565b61115c61115761116192611145565b610444565b610339565b90565b634e487b7160e01b600052601160045260246000fd5b61118961118f91939293610339565b92610339565b820180921161119a57565b611164565b6111a7611103565b506111b0611103565b506111b9611103565b506111c2611103565b506111cc42611dfc565b906111e1826111db6001611148565b9061117a565b6111f56111f0600b859061077c565b611122565b9161120a611205600b849061077c565b611122565b90565b916112379261121a610fd9565b5061122f611226611fd5565b829084916120cd565b919091612162565b600190565b600090565b90565b61125861125361125d92611241565b610444565b610650565b90565b61126a6012611244565b90565b61127561123c565b5061127e611260565b90565b61128961223d565b611291611385565b6112996122a9565b565b90565b6112b26112ad6112b79261129b565b610444565b610339565b90565b906112c76000199161104c565b9181191691161790565b90565b906112e96112e46112f092610760565b6112d1565b82546112ba565b9055565b61130361130991939293610339565b92610339565b820391821161131457565b611164565b600080fd5b60e01b90565b600091031261132f57565b61022e565b61133c610223565b3d6000823e3d90fd5b61134e90610447565b90565b61135a90611345565b90565b61137161136c6113769261129b565b610444565b6102fe565b90565b6113829061135d565b90565b61138d611fd5565b42906113a361139e600a839061047b565b611122565b91826113b86113b2600061129e565b91610339565b146116ab57806113d06113ca85610339565b91610339565b1115611688576113fb6113f56113f0856113ea6008611122565b9061117a565b610339565b91610339565b1015611665576114156114106009839061047b565b611122565b918261143161142b61142685611a5b565b610339565b91610339565b11611642576114419083906122bd565b61145f61144e600061129e565b61145a600a849061047b565b6112d4565b61147d61146c600061129e565b6114786009849061047b565b6112d4565b6114a58261149f6114906005859061047b565b9161149a83611122565b6112f4565b906112d4565b6114c26114bb836114b66004611122565b6112f4565b60046112d4565b6114eb7f0000000000000000000000000000000000000000000000000000000000000000610dc5565b63af14052c90803b1561163d5761150f91600091611507610223565b93849261131e565b82528183816115206004820161040b565b03925af180156116385761160b575b5061156c61156461155f7f0000000000000000000000000000000000000000000000000000000000000000610dc5565b611351565b8284916123db565b8082906115ae61159c7f1a39b9c5044b9f0ff56c5951e30c1ebe24911353aafcceb9250e83a24fe158c49261046f565b926115a5610223565b918291826104e7565b0390a2906115bc6000611379565b90916116066115f46115ee7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9361046f565b9361046f565b936115fd610223565b918291826104e7565b0390a3565b61162b9060003d8111611631575b6116238183610f6c565b810190611324565b3861152f565b503d611619565b611334565b611319565b61164a610223565b631e9acf1760e31b8152806116616004820161040b565b0390fd5b61166d610223565b63dbe67dcd60e01b8152806116846004820161040b565b0390fd5b611690610223565b6360fc88b360e11b8152806116a76004820161040b565b0390fd5b6116b3610223565b630b781b4d60e31b8152806116ca6004820161040b565b0390fd5b6116d6611281565b565b906116ea916116e561223d565b611700565b6116f26122a9565b565b6116fd90610463565b90565b9061170a82612047565b61171381612429565b61173b816117356117266005869061047b565b9161173083611122565b61117a565b906112d4565b6117586117518261174c6004611122565b61117a565b60046112d4565b6117a561178c6117877f0000000000000000000000000000000000000000000000000000000000000000610dc5565b611351565b611794611fd5565b61179d306116f4565b908492612499565b6117af6000611379565b9190916117fa6117e86117e27fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9361046f565b9361046f565b936117f1610223565b918291826104e7565b0390a3565b90611809916116d8565b565b61181c90611817611ff2565b61181e565b565b8061183a61183461182f6007611122565b610339565b91610339565b10156118865761184b8160076112d4565b6118817f6f3e5d6a00b186747b385d5be1e4e88c163f2541c4a63e9ecbb55ba29d44670b91611878610223565b918291826104e7565b0390a1565b61188e610223565b633cb2b8d760e11b8152806118a56004820161040b565b0390fd5b6118b29061180b565b565b606090565b906118cc6118c5610223565b9283610f6c565b565b67ffffffffffffffff81116118e65760208091020190565b610f56565b906118fd6118f8836118ce565b6118b9565b918252565b369037565b9061192c611914836118eb565b9260208061192286936118ce565b9201910390611902565b565b600161193a9101610339565b90565b634e487b7160e01b600052603260045260246000fd5b9061195d826108ab565b81101561196e576020809102010190565b61193d565b9061197d90610339565b9052565b6119b56119ae6119a86119c5939594956119996118b4565b506119a26118b4565b50611dfc565b94611dfc565b84906112f4565b6119bf6001611148565b9061117a565b906119cf82611907565b926119d983611907565b916119e4600061129e565b5b806119f86119f287610339565b91610339565b1015611a5457611a4f90611a4a611a38611a33611a1687859061117a565b611a2c81611a278d91889092611953565b611973565b600b61077c565b611122565b611a458791849092611953565b611973565b61192e565b6119e5565b5091925050565b611a72611a7791611a6a611103565b50600561047b565b611122565b90565b611a82611ff2565b611a8a611a8c565b565b611a9e611a996000611379565b612527565b565b611aa8611a7a565b565b90611ab3611103565b50611abc611103565b50611ac5610fd9565b50611aed611ae8611ae0611adb6009869061047b565b611122565b93600a61047b565b611122565b904282611b03611afd600061129e565b91610339565b141580611b44575b9081611b16575b5090565b9050611b3d611b37611b3285611b2c6008611122565b9061117a565b610339565b91610339565b1038611b12565b5080611b58611b5285610339565b91610339565b11611b0b565b611b6f90611b6a611ff2565b611b71565b565b80611b8d611b87611b826008611122565b610339565b91610339565b1115611bd957611b9e8160086112d4565b611bd47f176d9d2c8f84a996862e9cb6ae03eb576184e3fb7621bcbfc6e1828f4b11468091611bcb610223565b918291826104e7565b0390a1565b611be1610223565b6325d4924760e01b815280611bf86004820161040b565b0390fd5b611c0590611b5e565b565b611c1890611c1361223d565b611c46565b611c206122a9565b565b916020611c44929493611c3d604082019660008301906104da565b01906104da565b565b611c4f81612429565b611c57611fd5565b9080611c73611c6d611c6885611a5b565b610339565b91610339565b11611d3957611ca9611c8f611c8a600a859061047b565b611122565b611ca3611c9e6009869061047b565b611122565b906122bd565b611cbd42611cb76007611122565b9061117a565b91611cd383611cce600a849061047b565b6112d4565b611ce882611ce36009849061047b565b6112d4565b611cf3838390612588565b9091611d1f7f31f69201fab7912e3ec9850e3ab705964bf46d9d4276bdcbb6d05e965e5f54019261046f565b92611d34611d2b610223565b92839283611c22565b0390a2565b611d41610223565b631e9acf1760e31b815280611d586004820161040b565b0390fd5b611d6590611c07565b565b600090565b60018060a01b031690565b611d83611d8891611108565b611d6c565b90565b611d959054611d77565b90565b611da0611d67565b50611dab6000611d8b565b90565b611db6610e61565b50611dc16003610fb7565b90565b634e487b7160e01b600052601260045260246000fd5b611de6611dec91610339565b91610339565b908115611df7570490565b611dc4565b611e1990611e08611103565b50611e136008611122565b90611dda565b90565b611e3991611e28610fd9565b50611e31611fd5565b919091612162565b600190565b611e4f90611e4a611ff2565b611e51565b565b611e5a81612047565b611e706000611e6b600c84906106ae565b611077565b611e9a7f124b4488f16f954d5626769cbcab59a035cff89968908f4bbb90c264efcc9b839161046f565b90611ea3610223565b80611ead8161040b565b0390a2565b611ebb90611e3e565b565b611ec9611ece91611108565b6106c6565b90565b611edb9054611ebd565b90565b611ef5611efa91611eed610fd9565b50600c6106ae565b611ed1565b90565b611f14611f1991611f0c611103565b50600b61077c565b611122565b90565b90611f269061046f565b600052602052604060002090565b611f5991611f4f611f5492611f47611103565b506006611f1c565b61047b565b611122565b90565b611f6d90611f68611ff2565b611f6f565b565b80611f8b611f85611f806000611379565b610309565b91610309565b14611f9b57611f9990612527565b565b611fc6611fa86000611379565b611fb0610223565b91829163b20f76e360e01b835260048301610adc565b0390fd5b611fd390611f5c565b565b611fdd611d67565b503390565b91611ff092916001926125b9565b565b611ffa611d98565b61201361200d612008611fd5565b610309565b91610309565b0361201a57565b612043612025611fd5565b61202d610223565b9182916332b2baa360e01b835260048301610adc565b0390fd5b61206261205c6120576000611379565b610309565b91610309565b1461206957565b612071610223565b63d92e233d60e01b8152806120886004820161040b565b0390fd5b6040906120b66120bd94969593966120ac60608401986000850190610acf565b60208301906104da565b01906104da565b565b906120ca9103610339565b90565b9291926120db818390611f34565b90816120f16120eb600019610339565b91610339565b036120fe575b5050509050565b8161211161210b87610339565b91610339565b106121385761212f93946121269193926120bf565b906000926125b9565b803880806120f7565b5061215e84929192612148610223565b938493630c95cf2760e11b85526004850161208c565b0390fd5b918261217f6121796121746000611379565b610309565b91610309565b146121e257816121a061219a6121956000611379565b610309565b91610309565b146121b3576121b1929190916126e8565b565b6121de6121c06000611379565b6121c8610223565b918291639cfea58360e01b835260048301610adc565b0390fd5b61220d6121ef6000611379565b6121f7610223565b9182916313053d9360e21b835260048301610adc565b0390fd5b90565b61222861222361222d92612211565b610444565b610339565b90565b61223a6002612214565b90565b6122476001611122565b61226061225a612255612230565b610339565b91610339565b1461227957612277612270612230565b60016112d4565b565b612281610223565b6306fda65d60e31b8152806122986004820161040b565b0390fd5b6122a66001611148565b90565b6122bb6122b461229c565b60016112d4565b565b806122d16122cb600061129e565b91610339565b14801561235f575b61235b576122e690611dfc565b8161230c6123066123016122fc600b869061077c565b611122565b610339565b91610339565b1161233a576123326123236123389392600b61077c565b9161232d83611122565b6112f4565b906112d4565b565b612359915061235461234c600061129e565b91600b61077c565b6112d4565b565b5050565b508161237461236e600061129e565b91610339565b146122d9565b61238390610463565b90565b63ffffffff1690565b63ffffffff60e01b1690565b6123af6123aa6123b492612386565b61131e565b61238f565b90565b9160206123d99294936123d260408201966000830190610acf565b01906104da565b565b9061242261242793612413600494936123fa63a9059cbb91939161239b565b92612403610223565b96879460208601908152016123b7565b60208201810382520383610f6c565b61285f565b565b61243c612436600061129e565b91610339565b1461244357565b61244b610223565b631f2a200560e01b8152806124626004820161040b565b0390fd5b604090612490612497949695939661248660608401986000850190610acf565b6020830190610acf565b01906104da565b565b6004926124d36124e795936124e293946124ba6323b872dd9294919261239b565b936124c3610223565b9788956020870190815201612466565b60208201810382520383610f6c565b61285f565b565b906124fa60018060a01b039161104c565b9181191691161790565b90565b9061251c6125176125239261046f565b612504565b82546124e9565b9055565b6125316000611d8b565b61253c826000612507565b9061257061256a7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09361046f565b9161046f565b91612579610223565b806125838161040b565b0390a3565b906125b16125a261259b6125b794611dfc565b600b61077c565b916125ac83611122565b61117a565b906112d4565b565b9092816125d76125d16125cc6000611379565b610309565b91610309565b146126ab57836125f86125f26125ed6000611379565b610309565b91610309565b1461267c5761261c8361261761261060068690611f1c565b879061047b565b6112d4565b612626575b505050565b91909161267161265f6126597f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259361046f565b9361046f565b93612668610223565b918291826104e7565b0390a3388080612621565b6126a76126896000611379565b612691610223565b91829163270af7ed60e11b835260048301610adc565b0390fd5b6126d66126b86000611379565b6126c0610223565b9182916322f051b160e21b835260048301610adc565b0390fd5b906126e59101610339565b90565b919091806127076127016126fc6000611379565b610309565b91610309565b146000146127ec5761272c612725836127206004611122565b61117a565b60046112d4565b5b8261274961274361273e6000611379565b610309565b91610309565b146000146127bf5761276e612767836127626004611122565b6120bf565b60046112d4565b5b9190916127ba6127a86127a27fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9361046f565b9361046f565b936127b1610223565b918291826104e7565b0390a3565b6127e7826127e16127d26005879061047b565b916127dc83611122565b6126da565b906112d4565b61276f565b6128006127fb6005839061047b565b611122565b8061281361280d85610339565b91610339565b1061283c576128266128379184906120bf565b6128326005849061047b565b6112d4565b61272d565b612844610223565b631e9acf1760e31b81528061285b6004820161040b565b0390fd5b90600060209161286d611103565b50612876611103565b50828151910182855af115612914573d6000519061289d612897600061129e565b91610339565b146000146128fa57506128af8161237a565b3b6128c36128bd600061129e565b91610339565b145b6128cc5750565b6128d86128f69161237a565b6128e0610223565b918291635274afe760e01b835260048301610adc565b0390fd5b61290d6129076001611148565b91610339565b14156128c5565b6040513d6000823e3d90fdfea2646970667358221220e1a4ec787be00dfee0d5b9ed40777c22695e50c3eb61d50a0bc226c769df91d564736f6c63430008180033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c0000000000000000000000000000000000000000000000000000000000000012566f74652d457363726f7765642053545458000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067665535454580000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361015610013575b610e5c565b61001e60003561021d565b806306fdde0314610218578063095ea7b314610213578063099a0aae1461020e578063141ebd831461020957806318160ddd146102045780632366f298146101ff57806323b872dd146101fa578063313ce567146101f5578063382e7244146101f0578063399231e3146101eb5780633ccfd60b146101e657806347e7ef24146101e15780635bb5d99d146101dc5780635dea7556146101d757806370a08231146101d2578063715018a6146101cd5780637491687e146101c857806375b8b52f146101c357806380c62199146101be5780638da5cb5b146101b957806395d89b41146101b4578063a3760758146101af578063a3ef270b146101aa578063a7ab6961146101a5578063a9059cbb146101a0578063ae76cf2a1461019b578063c303a6a714610196578063c7f71b8a14610191578063d19bd0a71461018c578063dd62ed3e14610187578063ec4d8019146101825763f2fde38b0361000e57610e29565b610df4565b610d6b565b610d08565b610cc3565b610c8e565b610c5b565b610c25565b610bf0565b610bab565b610b76565b610b27565b610af2565b610a9c565b610a69565b610a31565b6109cb565b610996565b61095f565b61084a565b610816565b6107e3565b6107ae565b61070c565b610679565b61061a565b6105a6565b610532565b6104fd565b610411565b6103b6565b6102c9565b60e01c90565b60405190565b600080fd5b600080fd5b600091031261023e57565b61022e565b5190565b60209181520190565b60005b838110610264575050906000910152565b806020918301518185015201610253565b601f801991011690565b61029e6102a76020936102ac9361029581610243565b93848093610247565b95869101610250565b610275565b0190565b6102c6916020820191600081840391015261027f565b90565b346102f9576102d9366004610233565b6102f56102e4610fc3565b6102ec610223565b918291826102b0565b0390f35b610229565b60018060a01b031690565b610312906102fe565b90565b61031e81610309565b0361032557565b600080fd5b9050359061033782610315565b565b90565b61034581610339565b0361034c57565b600080fd5b9050359061035e8261033c565b565b9190604083820312610389578061037d610386926000860161032a565b93602001610351565b90565b61022e565b151590565b61039c9061038e565b9052565b91906103b490600060208501940190610393565b565b346103e7576103e36103d26103cc366004610360565b90610fde565b6103da610223565b918291826103a0565b0390f35b610229565b90602082820312610406576104039160000161032a565b90565b61022e565b60000190565b3461043f576104296104243660046103ec565b6110f8565b610431610223565b8061043b8161040b565b0390f35b610229565b90565b61045b610456610460926102fe565b610444565b6102fe565b90565b61046c90610447565b90565b61047890610463565b90565b906104859061046f565b600052602052604060002090565b1c90565b90565b6104aa9060086104af9302610493565b610497565b90565b906104bd915461049a565b90565b6104d7906104d2600a9160009261047b565b6104b2565b90565b6104e390610339565b9052565b91906104fb906000602085019401906104da565b565b3461052d576105296105186105133660046103ec565b6104c0565b610520610223565b918291826104e7565b0390f35b610229565b3461056257610542366004610233565b61055e61054d61112f565b610555610223565b918291826104e7565b0390f35b610229565b61059d6105a494610593606094989795610589608086019a60008701906104da565b60208501906104da565b60408301906104da565b01906104da565b565b346105da576105b6366004610233565b6105d66105c161119f565b906105cd949294610223565b94859485610567565b0390f35b610229565b9091606082840312610615576106126105fb846000850161032a565b93610609816020860161032a565b93604001610351565b90565b61022e565b3461064b576106476106366106303660046105df565b9161120d565b61063e610223565b918291826103a0565b0390f35b610229565b60ff1690565b61065f90610650565b9052565b919061067790600060208501940190610656565b565b346106a957610689366004610233565b6106a561069461126d565b61069c610223565b91829182610663565b0390f35b610229565b906106b89061046f565b600052602052604060002090565b60ff1690565b6106dc9060086106e19302610493565b6106c6565b90565b906106ef91546106cc565b90565b61070990610704600c916000926106ae565b6106e4565b90565b3461073c576107386107276107223660046103ec565b6106f2565b61072f610223565b918291826103a0565b0390f35b610229565b9060208282031261075b5761075891600001610351565b90565b61022e565b61077461076f61077992610339565b610444565b610339565b90565b9061078690610760565b600052602052604060002090565b6107ab906107a6600b9160009261077c565b6104b2565b90565b346107de576107da6107c96107c4366004610741565b610794565b6107d1610223565b918291826104e7565b0390f35b610229565b34610811576107f3366004610233565b6107fb6116ce565b610803610223565b8061080d8161040b565b0390f35b610229565b346108455761082f610829366004610360565b906117ff565b610837610223565b806108418161040b565b0390f35b610229565b346108785761086261085d366004610741565b6118a9565b61086a610223565b806108748161040b565b0390f35b610229565b91906040838203126108a6578061089a6108a39260008601610351565b93602001610351565b90565b61022e565b5190565b60209181520190565b60200190565b6108c790610339565b9052565b906108d8816020936108be565b0190565b60200190565b906108ff6108f96108f2846108ab565b80936108af565b926108b8565b9060005b8181106109105750505090565b90919261092961092360019286516108cb565b946108dc565b9101919091610903565b909161094e61095c93604084019084820360008601526108e2565b9160208184039101526108e2565b90565b346109915761097861097236600461087d565b90611981565b9061098d610984610223565b92839283610933565b0390f35b610229565b346109c6576109c26109b16109ac3660046103ec565b611a5b565b6109b9610223565b918291826104e7565b0390f35b610229565b346109f9576109db366004610233565b6109e3611aa0565b6109eb610223565b806109f58161040b565b0390f35b610229565b604090610a28610a2f9496959396610a1e606084019860008501906104da565b60208301906104da565b0190610393565b565b34610a6457610a60610a4c610a473660046103ec565b611aaa565b610a57939193610223565b938493846109fe565b0390f35b610229565b34610a9757610a81610a7c366004610741565b611bfc565b610a89610223565b80610a938161040b565b0390f35b610229565b34610aca57610ab4610aaf366004610741565b611d5c565b610abc610223565b80610ac68161040b565b0390f35b610229565b610ad890610309565b9052565b9190610af090600060208501940190610acf565b565b34610b2257610b02366004610233565b610b1e610b0d611d98565b610b15610223565b91829182610adc565b0390f35b610229565b34610b5757610b37366004610233565b610b53610b42611dae565b610b4a610223565b918291826102b0565b0390f35b610229565b610b7390610b6e60099160009261047b565b6104b2565b90565b34610ba657610ba2610b91610b8c3660046103ec565b610b5c565b610b99610223565b918291826104e7565b0390f35b610229565b34610bdb57610bd7610bc6610bc1366004610741565b611dfc565b610bce610223565b918291826104e7565b0390f35b610229565b610bed60076000906104b2565b90565b34610c2057610c00366004610233565b610c1c610c0b610be0565b610c13610223565b918291826104e7565b0390f35b610229565b34610c5657610c52610c41610c3b366004610360565b90611e1c565b610c49610223565b918291826103a0565b0390f35b610229565b34610c8957610c73610c6e3660046103ec565b611eb2565b610c7b610223565b80610c858161040b565b0390f35b610229565b34610cbe57610cba610ca9610ca43660046103ec565b611ede565b610cb1610223565b918291826103a0565b0390f35b610229565b34610cf357610cef610cde610cd9366004610741565b611efd565b610ce6610223565b918291826104e7565b0390f35b610229565b610d0560086000906104b2565b90565b34610d3857610d18366004610233565b610d34610d23610cf8565b610d2b610223565b918291826104e7565b0390f35b610229565b9190604083820312610d665780610d5a610d63926000860161032a565b9360200161032a565b90565b61022e565b34610d9c57610d98610d87610d81366004610d3d565b90611f34565b610d8f610223565b918291826104e7565b0390f35b610229565b7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea90565b610dce90610463565b90565b610dda90610dc5565b9052565b9190610df290600060208501940190610dd1565b565b34610e2457610e04366004610233565b610e20610e0f610da1565b610e17610223565b91829182610dde565b0390f35b610229565b34610e5757610e41610e3c3660046103ec565b611fca565b610e49610223565b80610e538161040b565b0390f35b610229565b600080fd5b606090565b634e487b7160e01b600052602260045260246000fd5b9060016002830492168015610e9c575b6020831014610e9757565b610e66565b91607f1691610e8c565b60209181520190565b600052602060002090565b9060009291805490610ed5610ece83610e7c565b8094610ea6565b91600181169081600014610f2e5750600114610ef1575b505050565b610efe9192939450610eaf565b916000925b818410610f165750500190388080610eec565b60018160209295939554848601520191019290610f03565b92949550505060ff1916825215156020020190388080610eec565b90610f5391610eba565b90565b634e487b7160e01b600052604160045260246000fd5b90610f7690610275565b810190811067ffffffffffffffff821117610f9057604052565b610f56565b90610fb5610fae92610fa5610223565b93848092610f49565b0383610f6c565b565b610fc090610f95565b90565b610fcb610e61565b50610fd66002610fb7565b90565b600090565b610fe6610fd9565b50610ff9610ff382611ede565b1561038e565b6110165761101191611009611fd5565b919091611fe2565b600190565b61101e610223565b633b09f10560e01b8152806110356004820161040b565b0390fd5b61104a90611045611ff2565b611097565b565b60001b90565b9061105e60ff9161104c565b9181191691161790565b6110719061038e565b90565b90565b9061108c61108761109392611068565b611074565b8254611052565b9055565b6110a081612047565b6110b660016110b1600c84906106ae565b611077565b6110e07f3584ac55fd91fcf5efce973892cccf98c9b1bc944e64135fc1b93132a8e3933e9161046f565b906110e9610223565b806110f38161040b565b0390a2565b61110190611039565b565b600090565b60001c90565b61111a61111f91611108565b610497565b90565b61112c905461110e565b90565b611137611103565b506111426004611122565b90565b90565b61115c61115761116192611145565b610444565b610339565b90565b634e487b7160e01b600052601160045260246000fd5b61118961118f91939293610339565b92610339565b820180921161119a57565b611164565b6111a7611103565b506111b0611103565b506111b9611103565b506111c2611103565b506111cc42611dfc565b906111e1826111db6001611148565b9061117a565b6111f56111f0600b859061077c565b611122565b9161120a611205600b849061077c565b611122565b90565b916112379261121a610fd9565b5061122f611226611fd5565b829084916120cd565b919091612162565b600190565b600090565b90565b61125861125361125d92611241565b610444565b610650565b90565b61126a6012611244565b90565b61127561123c565b5061127e611260565b90565b61128961223d565b611291611385565b6112996122a9565b565b90565b6112b26112ad6112b79261129b565b610444565b610339565b90565b906112c76000199161104c565b9181191691161790565b90565b906112e96112e46112f092610760565b6112d1565b82546112ba565b9055565b61130361130991939293610339565b92610339565b820391821161131457565b611164565b600080fd5b60e01b90565b600091031261132f57565b61022e565b61133c610223565b3d6000823e3d90fd5b61134e90610447565b90565b61135a90611345565b90565b61137161136c6113769261129b565b610444565b6102fe565b90565b6113829061135d565b90565b61138d611fd5565b42906113a361139e600a839061047b565b611122565b91826113b86113b2600061129e565b91610339565b146116ab57806113d06113ca85610339565b91610339565b1115611688576113fb6113f56113f0856113ea6008611122565b9061117a565b610339565b91610339565b1015611665576114156114106009839061047b565b611122565b918261143161142b61142685611a5b565b610339565b91610339565b11611642576114419083906122bd565b61145f61144e600061129e565b61145a600a849061047b565b6112d4565b61147d61146c600061129e565b6114786009849061047b565b6112d4565b6114a58261149f6114906005859061047b565b9161149a83611122565b6112f4565b906112d4565b6114c26114bb836114b66004611122565b6112f4565b60046112d4565b6114eb7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610dc5565b63af14052c90803b1561163d5761150f91600091611507610223565b93849261131e565b82528183816115206004820161040b565b03925af180156116385761160b575b5061156c61156461155f7f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610dc5565b611351565b8284916123db565b8082906115ae61159c7f1a39b9c5044b9f0ff56c5951e30c1ebe24911353aafcceb9250e83a24fe158c49261046f565b926115a5610223565b918291826104e7565b0390a2906115bc6000611379565b90916116066115f46115ee7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9361046f565b9361046f565b936115fd610223565b918291826104e7565b0390a3565b61162b9060003d8111611631575b6116238183610f6c565b810190611324565b3861152f565b503d611619565b611334565b611319565b61164a610223565b631e9acf1760e31b8152806116616004820161040b565b0390fd5b61166d610223565b63dbe67dcd60e01b8152806116846004820161040b565b0390fd5b611690610223565b6360fc88b360e11b8152806116a76004820161040b565b0390fd5b6116b3610223565b630b781b4d60e31b8152806116ca6004820161040b565b0390fd5b6116d6611281565b565b906116ea916116e561223d565b611700565b6116f26122a9565b565b6116fd90610463565b90565b9061170a82612047565b61171381612429565b61173b816117356117266005869061047b565b9161173083611122565b61117a565b906112d4565b6117586117518261174c6004611122565b61117a565b60046112d4565b6117a561178c6117877f00000000000000000000000097a10beebb25e0ebfa55ca0a7d00e37afe957dea610dc5565b611351565b611794611fd5565b61179d306116f4565b908492612499565b6117af6000611379565b9190916117fa6117e86117e27fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9361046f565b9361046f565b936117f1610223565b918291826104e7565b0390a3565b90611809916116d8565b565b61181c90611817611ff2565b61181e565b565b8061183a61183461182f6007611122565b610339565b91610339565b10156118865761184b8160076112d4565b6118817f6f3e5d6a00b186747b385d5be1e4e88c163f2541c4a63e9ecbb55ba29d44670b91611878610223565b918291826104e7565b0390a1565b61188e610223565b633cb2b8d760e11b8152806118a56004820161040b565b0390fd5b6118b29061180b565b565b606090565b906118cc6118c5610223565b9283610f6c565b565b67ffffffffffffffff81116118e65760208091020190565b610f56565b906118fd6118f8836118ce565b6118b9565b918252565b369037565b9061192c611914836118eb565b9260208061192286936118ce565b9201910390611902565b565b600161193a9101610339565b90565b634e487b7160e01b600052603260045260246000fd5b9061195d826108ab565b81101561196e576020809102010190565b61193d565b9061197d90610339565b9052565b6119b56119ae6119a86119c5939594956119996118b4565b506119a26118b4565b50611dfc565b94611dfc565b84906112f4565b6119bf6001611148565b9061117a565b906119cf82611907565b926119d983611907565b916119e4600061129e565b5b806119f86119f287610339565b91610339565b1015611a5457611a4f90611a4a611a38611a33611a1687859061117a565b611a2c81611a278d91889092611953565b611973565b600b61077c565b611122565b611a458791849092611953565b611973565b61192e565b6119e5565b5091925050565b611a72611a7791611a6a611103565b50600561047b565b611122565b90565b611a82611ff2565b611a8a611a8c565b565b611a9e611a996000611379565b612527565b565b611aa8611a7a565b565b90611ab3611103565b50611abc611103565b50611ac5610fd9565b50611aed611ae8611ae0611adb6009869061047b565b611122565b93600a61047b565b611122565b904282611b03611afd600061129e565b91610339565b141580611b44575b9081611b16575b5090565b9050611b3d611b37611b3285611b2c6008611122565b9061117a565b610339565b91610339565b1038611b12565b5080611b58611b5285610339565b91610339565b11611b0b565b611b6f90611b6a611ff2565b611b71565b565b80611b8d611b87611b826008611122565b610339565b91610339565b1115611bd957611b9e8160086112d4565b611bd47f176d9d2c8f84a996862e9cb6ae03eb576184e3fb7621bcbfc6e1828f4b11468091611bcb610223565b918291826104e7565b0390a1565b611be1610223565b6325d4924760e01b815280611bf86004820161040b565b0390fd5b611c0590611b5e565b565b611c1890611c1361223d565b611c46565b611c206122a9565b565b916020611c44929493611c3d604082019660008301906104da565b01906104da565b565b611c4f81612429565b611c57611fd5565b9080611c73611c6d611c6885611a5b565b610339565b91610339565b11611d3957611ca9611c8f611c8a600a859061047b565b611122565b611ca3611c9e6009869061047b565b611122565b906122bd565b611cbd42611cb76007611122565b9061117a565b91611cd383611cce600a849061047b565b6112d4565b611ce882611ce36009849061047b565b6112d4565b611cf3838390612588565b9091611d1f7f31f69201fab7912e3ec9850e3ab705964bf46d9d4276bdcbb6d05e965e5f54019261046f565b92611d34611d2b610223565b92839283611c22565b0390a2565b611d41610223565b631e9acf1760e31b815280611d586004820161040b565b0390fd5b611d6590611c07565b565b600090565b60018060a01b031690565b611d83611d8891611108565b611d6c565b90565b611d959054611d77565b90565b611da0611d67565b50611dab6000611d8b565b90565b611db6610e61565b50611dc16003610fb7565b90565b634e487b7160e01b600052601260045260246000fd5b611de6611dec91610339565b91610339565b908115611df7570490565b611dc4565b611e1990611e08611103565b50611e136008611122565b90611dda565b90565b611e3991611e28610fd9565b50611e31611fd5565b919091612162565b600190565b611e4f90611e4a611ff2565b611e51565b565b611e5a81612047565b611e706000611e6b600c84906106ae565b611077565b611e9a7f124b4488f16f954d5626769cbcab59a035cff89968908f4bbb90c264efcc9b839161046f565b90611ea3610223565b80611ead8161040b565b0390a2565b611ebb90611e3e565b565b611ec9611ece91611108565b6106c6565b90565b611edb9054611ebd565b90565b611ef5611efa91611eed610fd9565b50600c6106ae565b611ed1565b90565b611f14611f1991611f0c611103565b50600b61077c565b611122565b90565b90611f269061046f565b600052602052604060002090565b611f5991611f4f611f5492611f47611103565b506006611f1c565b61047b565b611122565b90565b611f6d90611f68611ff2565b611f6f565b565b80611f8b611f85611f806000611379565b610309565b91610309565b14611f9b57611f9990612527565b565b611fc6611fa86000611379565b611fb0610223565b91829163b20f76e360e01b835260048301610adc565b0390fd5b611fd390611f5c565b565b611fdd611d67565b503390565b91611ff092916001926125b9565b565b611ffa611d98565b61201361200d612008611fd5565b610309565b91610309565b0361201a57565b612043612025611fd5565b61202d610223565b9182916332b2baa360e01b835260048301610adc565b0390fd5b61206261205c6120576000611379565b610309565b91610309565b1461206957565b612071610223565b63d92e233d60e01b8152806120886004820161040b565b0390fd5b6040906120b66120bd94969593966120ac60608401986000850190610acf565b60208301906104da565b01906104da565b565b906120ca9103610339565b90565b9291926120db818390611f34565b90816120f16120eb600019610339565b91610339565b036120fe575b5050509050565b8161211161210b87610339565b91610339565b106121385761212f93946121269193926120bf565b906000926125b9565b803880806120f7565b5061215e84929192612148610223565b938493630c95cf2760e11b85526004850161208c565b0390fd5b918261217f6121796121746000611379565b610309565b91610309565b146121e257816121a061219a6121956000611379565b610309565b91610309565b146121b3576121b1929190916126e8565b565b6121de6121c06000611379565b6121c8610223565b918291639cfea58360e01b835260048301610adc565b0390fd5b61220d6121ef6000611379565b6121f7610223565b9182916313053d9360e21b835260048301610adc565b0390fd5b90565b61222861222361222d92612211565b610444565b610339565b90565b61223a6002612214565b90565b6122476001611122565b61226061225a612255612230565b610339565b91610339565b1461227957612277612270612230565b60016112d4565b565b612281610223565b6306fda65d60e31b8152806122986004820161040b565b0390fd5b6122a66001611148565b90565b6122bb6122b461229c565b60016112d4565b565b806122d16122cb600061129e565b91610339565b14801561235f575b61235b576122e690611dfc565b8161230c6123066123016122fc600b869061077c565b611122565b610339565b91610339565b1161233a576123326123236123389392600b61077c565b9161232d83611122565b6112f4565b906112d4565b565b612359915061235461234c600061129e565b91600b61077c565b6112d4565b565b5050565b508161237461236e600061129e565b91610339565b146122d9565b61238390610463565b90565b63ffffffff1690565b63ffffffff60e01b1690565b6123af6123aa6123b492612386565b61131e565b61238f565b90565b9160206123d99294936123d260408201966000830190610acf565b01906104da565b565b9061242261242793612413600494936123fa63a9059cbb91939161239b565b92612403610223565b96879460208601908152016123b7565b60208201810382520383610f6c565b61285f565b565b61243c612436600061129e565b91610339565b1461244357565b61244b610223565b631f2a200560e01b8152806124626004820161040b565b0390fd5b604090612490612497949695939661248660608401986000850190610acf565b6020830190610acf565b01906104da565b565b6004926124d36124e795936124e293946124ba6323b872dd9294919261239b565b936124c3610223565b9788956020870190815201612466565b60208201810382520383610f6c565b61285f565b565b906124fa60018060a01b039161104c565b9181191691161790565b90565b9061251c6125176125239261046f565b612504565b82546124e9565b9055565b6125316000611d8b565b61253c826000612507565b9061257061256a7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09361046f565b9161046f565b91612579610223565b806125838161040b565b0390a3565b906125b16125a261259b6125b794611dfc565b600b61077c565b916125ac83611122565b61117a565b906112d4565b565b9092816125d76125d16125cc6000611379565b610309565b91610309565b146126ab57836125f86125f26125ed6000611379565b610309565b91610309565b1461267c5761261c8361261761261060068690611f1c565b879061047b565b6112d4565b612626575b505050565b91909161267161265f6126597f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259361046f565b9361046f565b93612668610223565b918291826104e7565b0390a3388080612621565b6126a76126896000611379565b612691610223565b91829163270af7ed60e11b835260048301610adc565b0390fd5b6126d66126b86000611379565b6126c0610223565b9182916322f051b160e21b835260048301610adc565b0390fd5b906126e59101610339565b90565b919091806127076127016126fc6000611379565b610309565b91610309565b146000146127ec5761272c612725836127206004611122565b61117a565b60046112d4565b5b8261274961274361273e6000611379565b610309565b91610309565b146000146127bf5761276e612767836127626004611122565b6120bf565b60046112d4565b5b9190916127ba6127a86127a27fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9361046f565b9361046f565b936127b1610223565b918291826104e7565b0390a3565b6127e7826127e16127d26005879061047b565b916127dc83611122565b6126da565b906112d4565b61276f565b6128006127fb6005839061047b565b611122565b8061281361280d85610339565b91610339565b1061283c576128266128379184906120bf565b6128326005849061047b565b6112d4565b61272d565b612844610223565b631e9acf1760e31b81528061285b6004820161040b565b0390fd5b90600060209161286d611103565b50612876611103565b50828151910182855af115612914573d6000519061289d612897600061129e565b91610339565b146000146128fa57506128af8161237a565b3b6128c36128bd600061129e565b91610339565b145b6128cc5750565b6128d86128f69161237a565b6128e0610223565b918291635274afe760e01b835260048301610adc565b0390fd5b61290d6129076001611148565b91610339565b14156128c5565b6040513d6000823e3d90fdfea2646970667358221220e1a4ec787be00dfee0d5b9ed40777c22695e50c3eb61d50a0bc226c769df91d564736f6c63430008180033

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

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c0000000000000000000000000000000000000000000000000000000000000012566f74652d457363726f7765642053545458000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067665535454580000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : name_ (string): Vote-Escrowed STTX
Arg [1] : symbol_ (string): veSTTX
Arg [2] : baseContracts_ (address): 0x5Ce899AEd04c656776148fc3b1Adbe59e5f13D5c

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [4] : 566f74652d457363726f77656420535454580000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [6] : 7665535454580000000000000000000000000000000000000000000000000000


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.