ERC-20
Overview
Max Total Supply
95,063.016078050816966619 stDUSX
Holders
128
Market
Price
$0.00 @ 0.000000 S
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
168.23 stDUSXValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
StakedDUSX
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /* __ ________ ____ ___ _____________ ___ _______/ |_\______ \ | | \/ _____/\ \/ / / ___/\ __\| | \ | | /\_____ \ \ / \___ \ | | | ` \| | / / \ / \ /____ > |__| /_______ /|______/ /_______ //___/\ \ \/ \/ \/ \_/ */ pragma solidity >=0.8.24 <0.9.0; import {Ownable} from "./abstract/Ownable.sol"; import {ReentrancyGuard} from "./abstract/ReentrancyGuard.sol"; import {IBaseContracts} from "./interface/IBaseContracts.sol"; import {IERC20Custom} from "./interface/IERC20Custom.sol"; import {IERC20Token} from "./interface/IERC20Token.sol"; import {IFeesDistributor} from "./interface/IFees.sol"; import {ILender} from "./interface/ILender.sol"; import {IMiscHelper} from "./interface/IMiscHelper.sol"; import {IStakedDUSX} from "./interface/IStakedDUSX.sol"; import {IVault} from "./interface/IVault.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IERC20 as IERC20Safe} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title StakedDUSX * @dev Staking and fee distribution token * @notice Stake and rewards manager */ contract StakedDUSX is Ownable, ReentrancyGuard, IERC20Custom, IStakedDUSX { /*////////////////////////////////////////////////////////////// TOKEN CONFIGURATION //////////////////////////////////////////////////////////////*/ /// @notice Base DUSX token contract /// @dev Used for token transfers IERC20Token public immutable dusx; /// @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 stDUSX 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; /*////////////////////////////////////////////////////////////// PROTOCOL CONFIGURATION //////////////////////////////////////////////////////////////*/ bool public initialized; /// @notice Base contracts registry IBaseContracts public immutable baseContracts; /// @notice Vault contract IVault public vault; /// @notice Helper contract for miscellaneous functions IMiscHelper public helper; /// @notice Address responsible for fee distribution IFeesDistributor public feesDistributor; /// @notice Treasury address for fee allocation address public treasury; /// @notice Earned fees per account mapping(address => uint256) private _earned; /// @notice Active account tracking mapping(address => bool) private _accountExists; /// @notice Account indices for fast lookup mapping(address => uint256) private _accountIndices; /// @notice Fee accumulator - tracks fees per share (scaled by 1e18) uint256 private _feeAccumulator; /// @notice Last fee accumulator value claimed by each account mapping(address => uint256) private _lastFeeAccumulator; /// @notice List of all staking accounts address[] private _accounts; /*////////////////////////////////////////////////////////////// WITHDRAWAL CONFIGURATION //////////////////////////////////////////////////////////////*/ /// @notice Delay before withdrawal becomes available /// @dev Default: 5 minutes uint256 public withdrawalDelay = 15 minutes; /// @notice Window duration for completing withdrawal /// @dev Default: 24 hours uint256 public withdrawalWindow = 24 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; /// @notice Percentage threshold for full balance withdrawal uint256 private constant PERCENTAGE_THRESHOLD = 99; /*////////////////////////////////////////////////////////////// ACCESS CONTROL STATE //////////////////////////////////////////////////////////////*/ /// @notice Mapping of approved token spenders /// @dev Allows controlled token spending mapping(address => bool) public approvedSpenders; /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Initialized(address helper, address feesDistributor); event TreasuryAddressUpdated(address oldTreasury, address newTreasury); event SpenderApproved(address spender); event SpenderRevoked(address spender); event WithdrawalDelayDecreased(uint256 newDelay); event WithdrawalWindowIncreased(uint256 newWindow); event WithdrawalInitiated( address indexed account, uint256 amount, uint256 time ); event FeesDistributed( uint256 amount, uint256 feePerShare, uint256 timestamp ); event FeesClaimed( address indexed account, uint256 amount, uint256 timestamp ); /*////////////////////////////////////////////////////////////// CUSTOM ERRORS //////////////////////////////////////////////////////////////*/ error InsufficientBalance(); error InsufficientAllowance( address spender, uint256 current, uint256 required ); error SpenderNotAuthorized(); error WithdrawalNotInitiated(); error WithdrawalWindowNotOpenYet(); error WithdrawalWindowAlreadyClosed(); error InvalidWithdrawalDelay(); error InvalidWithdrawalWindow(); error alreadyInitialized(); error InvalidSender(address sender); error InvalidReceiver(address receiver); error InvalidApprover(address approver); error InvalidSpender(address spender); error ZeroAddress(); error ZeroAmount(); /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ modifier onlyHelper() { if (address(helper) != _msgSender()) { revert UnauthorizedAccount(_msgSender()); } _; } modifier onlyFeeDistributor() { if (address(feesDistributor) != _msgSender()) { revert UnauthorizedAccount(_msgSender()); } _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /** * @notice Initializes the stDUSX token * @param name_ Token name * @param symbol_ Token symbol * @param baseContracts_ BaseContracts instance for protocol integration */ constructor( string memory name_, string memory symbol_, IBaseContracts baseContracts_, address treasury_ ) { _ensureNonzeroAddress(address(baseContracts_)); baseContracts = baseContracts_; // Get core contracts from BaseContracts dusx = baseContracts.dusx(); vault = baseContracts.vault(); _ensureNonzeroAddress(address(dusx)); _ensureNonzeroAddress(address(vault)); _name = name_; _symbol = symbol_; _ensureNonzeroAddress(treasury_); treasury = treasury_; _accountExists[address(0)] = false; } /*////////////////////////////////////////////////////////////// EXTERNAL FUNCTIONS · CONFIGURATION //////////////////////////////////////////////////////////////*/ /** * @notice Sets core protocol parameters */ function initialize() external onlyOwner { if (initialized) revert alreadyInitialized(); // Get core contracts from BaseContracts helper = baseContracts.helper(); feesDistributor = baseContracts.feesDistributor(); // Validate addresses _ensureNonzeroAddress(address(helper)); _ensureNonzeroAddress(address(feesDistributor)); initialized = true; emit Initialized(address(helper), address(feesDistributor)); } /** * @notice Sets the treasury address for receiving leftover stablecoins * @param newTreasury The new treasury address */ function setTreasury(address newTreasury) external onlyOwner { _ensureNonzeroAddress(newTreasury); address oldTreasury = treasury; treasury = newTreasury; emit TreasuryAddressUpdated(oldTreasury, newTreasury); } /** * @notice Approves a spender to spend tokens on behalf of the owner * @param spender Address of the approved spender * * Requirements: * · Only the owner can call this function * · Spender address must be non-zero * * Effects: * · Sets the spender as approved * · Emits a SpenderApproved event */ 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 the owner can call this function * · Spender address must be non-zero * * Effects: * · Sets the spender as not approved * · Emits a SpenderRevoked event */ 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 the owner can call this function * · New delay must be less than the current delay * * Effects: * · Sets the new withdrawal delay * · Emits a WithdrawalDelayDecreased event */ 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 the owner can call this function * · New window must be greater than the current window * * Effects: * · Sets the new withdrawal window * · Emits a WithdrawalWindowIncreased event */ function increaseWithdrawalWindow(uint256 newWindow) external onlyOwner { if (newWindow <= withdrawalWindow) revert InvalidWithdrawalWindow(); withdrawalWindow = newWindow; emit WithdrawalWindowIncreased(newWindow); } /*////////////////////////////////////////////////////////////// EXTERNAL FUNCTIONS · CORE OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Deposits DUSX tokens into staking contract * @param from Source address of tokens * @param to Destination address receiving stake * @param amount Amount of tokens to stake */ function deposit( address from, address to, uint256 amount ) external nonReentrant onlyHelper { _ensureNonzeroAddress(to); _ensureNonzeroAmount(amount); // Claim any pending fees for the recipient _claimFees(to); _balances[to] += amount; _totalSupply += amount; _addAccount(to); // _addAccount already initializes the fee accumulator // No need to set it again here SafeERC20.safeTransferFrom( IERC20Safe(address(dusx)), from, address(this), amount ); _lendersAccrue(); emit Transfer(address(0), to, amount); } /** * @notice Distributes fees proportionally to stakers * @param amount Total fee amount to distribute */ function distributeFees(uint256 amount) external onlyFeeDistributor { _ensureNonzeroAmount(amount); // If there are no stakers, all fees go to treasury if (_totalSupply == 0) { _balances[treasury] += amount; _addAccount(treasury); _totalSupply += amount; // Make sure the treasury's accumulator is updated // This is important if the treasury is also a regular staker _lastFeeAccumulator[treasury] = _feeAccumulator; emit Transfer(address(0), treasury, amount); } else { // Calculate fee per share (scaled by 1e18 for precision) uint256 feePerShare = (amount * 1e18) / _totalSupply; // Increase the global accumulator _feeAccumulator += feePerShare; // Reserve a small portion for the treasury to handle rounding errors // Due to integer division, when calculating claimedAmount = (accountBalance * accumulatorDelta) / 1e18, // there will always be some dust left over. Over many transactions with many users, // these rounding errors can accumulate to a significant amount that would otherwise be lost. // We allocate 1% to the treasury to cover these rounding errors. uint256 treasuryAmount = amount / 100; // 1% to treasury to cover rounding _balances[treasury] += treasuryAmount; _addAccount(treasury); // Don't increase total supply as tokens are "virtual" until claimed // This prevents dilution of future fee distributions // Emit a transfer event for the protocol to track emit FeesDistributed(amount, feePerShare, block.timestamp); } // Transfer the tokens from the fee distributor to this contract SafeERC20.safeTransferFrom( IERC20Safe(address(dusx)), _msgSender(), address(this), 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 * · Emits a WithdrawalInitiated event */ 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 Withdraws staked DUSX tokens * @param account User address withdrawing tokens */ function withdraw(address account) external nonReentrant onlyHelper { // Check if withdrawal was initiated uint256 minTime = withdrawalTimestamps[account]; if (minTime == 0) revert WithdrawalNotInitiated(); // Check if the withdrawal window is open uint256 currentTime = block.timestamp; if (currentTime <= minTime) revert WithdrawalWindowNotOpenYet(); if (currentTime >= minTime + withdrawalWindow) revert WithdrawalWindowAlreadyClosed(); // Claim any pending fees before withdrawal _claimFees(account); // Validate sufficient balance uint256 amount = withdrawalAmounts[account]; uint256 balance = balanceOf(account); // Calculate the threshold percentage of the balance uint256 thresholdBalance = (balance * PERCENTAGE_THRESHOLD) / 100; // Adjust amount if it meets the threshold if (amount >= thresholdBalance) { amount = balance; } if (amount > balance) revert InsufficientBalance(); // Reset withdrawal data _decreaseWithdrawalSlot(minTime, amount); withdrawalTimestamps[account] = 0; withdrawalAmounts[account] = 0; // Decrease balance and total supply _balances[account] -= amount; _totalSupply -= amount; // Handle complete account withdrawal if (amount == balance) { _earned[account] = 0; _removeAccount(account); // Clean up fee accumulator tracking delete _lastFeeAccumulator[account]; } // Transfer tokens SafeERC20.safeTransfer(IERC20Safe(address(dusx)), account, amount); // Trigger lender accrual _lendersAccrue(); // Emit events emit Transfer(account, address(0), amount); } /** * @notice Claims pending fees for the caller * @return claimedAmount Amount of fees claimed */ function claimFees() external nonReentrant returns (uint256 claimedAmount) { address account = _msgSender(); claimedAmount = _claimFees(account); // Event is already emitted in _claimFees return claimedAmount; } /** * @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 * · Emits a Transfer event */ 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 * · Emits an Approval event */ 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 * · Emits a Transfer event */ 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; } function accounts() external view returns (address[] memory) { return _accounts; } function earnedOf(address account) external view returns (uint256) { return _earned[account]; } /** * @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]; } /** * @notice View pending unclaimed fees for an account * @param account Address to check pending fees for * @return pendingAmount Amount of fees available to claim */ function pendingFees( address account ) public view returns (uint256 pendingAmount) { if (account == address(0) || _balances[account] == 0) { return 0; } uint256 accountBalance = _balances[account]; uint256 lastClaimed = _lastFeeAccumulator[account]; // If accumulator is not initialized yet, initialize it for the calculation // But don't prevent calculating fees - this matches _claimFees behavior if (lastClaimed == 0) { // Use current accumulator for the calculation // This matches the behavior in _claimFees lastClaimed = _feeAccumulator; } // Safe subtraction to prevent underflow uint256 accumulatorDelta = _feeAccumulator >= lastClaimed ? _feeAccumulator - lastClaimed : 0; if (accumulatorDelta > 0) { // Calculate fees to distribute pendingAmount = (accountBalance * accumulatorDelta) / 1e18; } return pendingAmount; } /*////////////////////////////////////////////////////////////// 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)); // Claim any pending fees for both sender and recipient _claimFees(from); _claimFees(to); _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; } // Remove account if balance becomes zero if (fromBalance == value) { _earned[from] = 0; _removeAccount(from); // Clean up fee accumulator tracking for consistency delete _lastFeeAccumulator[from]; } } if (to == address(0)) { unchecked { _totalSupply -= value; } } else { unchecked { _balances[to] += value; } // Add the recipient to accounts if they receive tokens _addAccount(to); } 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 * · Emits an Approval event */ 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 * · Emits an Approval event if emitEvent is true */ 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; } /** * @notice Adds account to list of staking accounts * @param account Address to add */ function _addAccount(address account) private { if (!_accountExists[account]) { _accountIndices[account] = _accounts.length; _accounts.push(account); _accountExists[account] = true; // Initialize fee accumulator for the new account // Note: New stakeholders will have their accumulator set to the current value, // meaning they will not receive fees from distributions that occurred before // they staked, but will receive the same proportion of fees in future distributions // as all other stakeholders relative to their stake amount. _lastFeeAccumulator[account] = _feeAccumulator; } } /** * @notice Removes account from list of staking accounts * @param account Address to remove */ function _removeAccount(address account) private { if (_accountExists[account]) { uint256 index = _accountIndices[account]; uint256 lastIndex = _accounts.length - 1; if (index != lastIndex) { address lastAccount = _accounts[lastIndex]; _accounts[index] = lastAccount; _accountIndices[lastAccount] = index; } _accounts.pop(); delete _accountIndices[account]; _accountExists[account] = false; } } /** * @notice Triggers lender accrual */ function _lendersAccrue() private { address[] memory lenders = vault.getControllers(); uint256 length = lenders.length; for (uint256 i; i < length; i++) { ILender(lenders[i]).accrue(); } } /** * @notice Claims pending fees for an account * @param account Address to claim fees for * @return claimedAmount Amount of fees claimed */ function _claimFees( address account ) private returns (uint256 claimedAmount) { if (account == address(0) || _balances[account] == 0) { return 0; } // Calculate pending fees based on accumulator difference uint256 accountBalance = _balances[account]; uint256 lastClaimed = _lastFeeAccumulator[account]; // If accumulator is not initialized yet, initialize it // But don't prevent claiming fees if it's zero - this could happen // for valid reasons like contract deployment or resetting if (lastClaimed == 0) { _lastFeeAccumulator[account] = _feeAccumulator; // Don't return early - continue with the claim calculation // This ensures that if _feeAccumulator is already non-zero when an account // is first seen, they'll still get their share of fees lastClaimed = _feeAccumulator; } // Safe subtraction to prevent underflow uint256 accumulatorDelta = _feeAccumulator >= lastClaimed ? _feeAccumulator - lastClaimed : 0; if (accumulatorDelta > 0) { // Calculate fees to distribute claimedAmount = (accountBalance * accumulatorDelta) / 1e18; // Update account balance and earned fees if (claimedAmount > 0) { _balances[account] += claimedAmount; _earned[account] += claimedAmount; // Update total supply to reflect the claimed virtual tokens _totalSupply += claimedAmount; // Emit a transfer event for this distribution emit Transfer(address(0), account, claimedAmount); // Emit fee claiming event for all claims, even automatic ones // This improves off-chain tracking consistency emit FeesClaimed(account, claimedAmount, block.timestamp); } // Update last claimed accumulator value _lastFeeAccumulator[account] = _feeAccumulator; } return claimedAmount; } // 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(); } } }
// 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); }
// 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";
// 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";
// 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); }
// 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); } }
// 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); }
// 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; } }
// 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()); } } }
// 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; } }
// 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); }
// 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; }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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; }
// 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; } }
{ "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
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"contract IBaseContracts","name":"baseContracts_","type":"address"},{"internalType":"address","name":"treasury_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"current","type":"uint256"},{"internalType":"uint256","name":"required","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"},{"inputs":[],"name":"alreadyInitialized","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":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"FeesClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feePerShare","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"FeesDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"helper","type":"address"},{"indexed":false,"internalType":"address","name":"feesDistributor","type":"address"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"spender","type":"address"}],"name":"SpenderApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"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":false,"internalType":"address","name":"oldTreasury","type":"address"},{"indexed":false,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasuryAddressUpdated","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":"time","type":"uint256"}],"name":"WithdrawalInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newWindow","type":"uint256"}],"name":"WithdrawalWindowIncreased","type":"event"},{"inputs":[],"name":"accounts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"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":[],"name":"baseContracts","outputs":[{"internalType":"contract IBaseContracts","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"beginWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimFees","outputs":[{"internalType":"uint256","name":"claimedAmount","type":"uint256"}],"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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"distributeFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dusx","outputs":[{"internalType":"contract IERC20Token","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earnedOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesDistributor","outputs":[{"internalType":"contract IFeesDistributor","name":"","type":"address"}],"stateMutability":"view","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":[],"name":"helper","outputs":[{"internalType":"contract IMiscHelper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newWindow","type":"uint256"}],"name":"increaseWithdrawalWindow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[{"internalType":"address","name":"account","type":"address"}],"name":"pendingFees","outputs":[{"internalType":"uint256","name":"pendingAmount","type":"uint256"}],"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":[{"internalType":"address","name":"newTreasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","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":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"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"}]
Contract Creation Code
60c06040523462000070576200002262000018620002a4565b929190916200090a565b6200002c62000076565b61435962000cda823960805181818161106601528181611e3f015281816124100152612ded015260a0518181816107cd01528181612ae10152612b53015261435990f35b6200007c565b60405190565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b90620000ad9062000081565b810190811060018060401b03821117620000c657604052565b6200008b565b90620000e3620000db62000076565b9283620000a1565b565b600080fd5b600080fd5b600080fd5b600080fd5b60018060401b03811162000118576200011460209162000081565b0190565b6200008b565b60005b83811062000133575050906000910152565b80602091830151818501520162000121565b909291926200015e6200015882620000f9565b620000cc565b938185526020850190828401116200017d576200017b926200011e565b565b620000f4565b9080601f83011215620001a457816020620001a19351910162000145565b90565b620000ef565b60018060a01b031690565b620001c090620001aa565b90565b620001ce90620001b5565b90565b620001dc81620001c3565b03620001e457565b600080fd5b90505190620001f882620001d1565b565b6200020581620001b5565b036200020d57565b600080fd5b905051906200022182620001fa565b565b6080818303126200029e57600081015160018060401b0381116200029857826200024f91830162000183565b92602082015160018060401b038111620002925762000275846200028f92850162000183565b93620002858160408601620001e9565b9360600162000212565b90565b620000ea565b620000ea565b620000e5565b620002c76200503380380380620002bb81620000cc565b92833981019062000223565b90919293565b60001b90565b90620002e260001991620002cd565b9181191691161790565b90565b90565b90565b6200030e620003086200031492620002ec565b620002f2565b620002ef565b90565b90565b90620003346200032e6200033c92620002f5565b62000317565b8254620002d3565b9055565b90565b6200035c62000356620003629262000340565b620002f2565b620002ef565b90565b906200037f62000379620003879262000343565b62000317565b8254620002d3565b9055565b620003a46200039e620003aa92620001aa565b620002f2565b620001aa565b90565b620003b8906200038b565b90565b620003c690620003ad565b90565b620003d59051620001c3565b90565b60e01b90565b620003e990620001b5565b90565b620003f781620003de565b03620003ff57565b600080fd5b905051906200041382620003ec565b565b9060208282031262000432576200042f9160000162000404565b90565b620000e5565b60000190565b6200044862000076565b3d6000823e3d90fd5b6200045c90620001b5565b90565b6200046a8162000451565b036200047257565b600080fd5b9050519062000486826200045f565b565b90602082820312620004a557620004a29160000162000477565b90565b620000e5565b60081b90565b90620004c6610100600160a81b0391620004ab565b9181191691161790565b620004db906200038b565b90565b620004e990620004d0565b90565b90565b9062000509620005036200051192620004de565b620004ec565b8254620004b1565b9055565b620005219051620003de565b90565b6200052f90620003ad565b90565b60081c90565b60018060a01b031690565b62000552620005589162000532565b62000538565b90565b62000567905462000543565b90565b6200057590620003ad565b90565b5190565b634e487b7160e01b600052602260045260246000fd5b9060016002830492168015620005b5575b6020831014620005af57565b6200057c565b91607f1691620005a3565b600052602060002090565b601f602091010490565b1b90565b91906008620005f9910291620005f260001984620005d5565b92620005d5565b9181191691161790565b6200061c620006166200062292620002ef565b620002f2565b620002ef565b90565b9190620006406200063a620006499362000603565b62000317565b908354620005d9565b9055565b600090565b6200066891620006616200064d565b9162000625565b565b5b81811062000677575050565b8062000687600060019362000652565b016200066b565b9190601f81116200069f575b505050565b620006ae620006d993620005c0565b906020620006bc84620005cb565b83019310620006e2575b620006d190620005cb565b01906200066a565b3880806200069a565b9150620006d181929050620006c6565b1c90565b90620007099060001990600802620006f2565b191690565b816200071a91620006f6565b906002021790565b906200072e8162000578565b9060018060401b038211620008015762000755826200074e855462000592565b856200068e565b602090601f83116001146200078f579180916200077d9360009262000782575b50506200070e565b90555b565b9091500151388062000775565b601f19831691620007a085620005c0565b9260005b818110620007e857509160029391856001969410620007cb575b5050500201905562000780565b620007dd910151601f841690620006f6565b9055388080620007be565b91936020600181928787015181550195019201620007a4565b6200008b565b90620008139162000722565b565b906200082860018060a01b0391620002cd565b9181191691161790565b6200083d90620003ad565b90565b90565b906200085d62000857620008659262000832565b62000840565b825462000815565b9055565b90565b620008856200087f6200088b9262000869565b620002f2565b620001aa565b90565b62000899906200086c565b90565b90620008a89062000832565b600052602052604060002090565b90620008c460ff91620002cd565b9181191691161790565b151590565b620008de90620008ce565b90565b90565b90620008fe620008f86200090692620008d3565b620008e1565b8254620008b6565b9055565b92919062000984916200091c62000b26565b6200092b61038460116200031a565b6200093b62015180601262000365565b620009506200094a82620003bb565b62000bd0565b60a05260206200096b6200096560a0620003c9565b620003bb565b6396df10c0906200097b62000076565b948592620003d8565b82528180620009966004820162000438565b03915afa801562000b2057620009e49260009162000aeb575b506080526020620009cb620009c560a0620003c9565b620003bb565b63fbfa77cf90620009db62000076565b948592620003d8565b82528180620009f66004820162000438565b03915afa801562000ae55762000a899462000a2662000a6e9262000a769560009162000ab0575b506007620004ef565b62000a4662000a4062000a3a608062000515565b62000524565b62000bd0565b62000a6662000a6062000a5a60076200055b565b6200056a565b62000bd0565b600262000807565b600362000807565b62000a818162000bd0565b600a62000843565b62000aae600062000aa8600c62000aa160006200088e565b906200089c565b620008e4565b565b62000ad6915060203d811162000add575b62000acd8183620000a1565b81019062000488565b3862000a1d565b503d62000ac1565b6200043e565b62000b11915060203d811162000b18575b62000b088183620000a1565b81019062000415565b38620009af565b503d62000afc565b6200043e565b62000b3062000b32565b565b62000b3c62000b98565b565b90565b62000b5a62000b5462000b609262000b3e565b620002f2565b620002ef565b90565b62000b6f600162000b41565b90565b9062000b8c62000b8662000b949262000603565b62000317565b8254620002d3565b9055565b62000ba262000bba565b62000bb862000bb062000b63565b600162000b72565b565b62000bce62000bc862000c25565b62000c6c565b565b62000bf162000bea62000be460006200088e565b620001b5565b91620001b5565b1462000bf957565b62000c0362000076565b63d92e233d60e01b81528062000c1c6004820162000438565b0390fd5b600090565b62000c2f62000c20565b503390565b60001c90565b60018060a01b031690565b62000c5462000c5a9162000c34565b62000c3a565b90565b62000c69905462000c45565b90565b62000c78600062000c5d565b62000c8582600062000843565b9062000cbd62000cb67f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09362000832565b9162000832565b9162000cc862000076565b8062000cd48162000438565b0390a356fe60806040526004361015610013575b611471565b61001e6000356102ed565b806306fdde03146102e8578063095ea7b3146102e3578063099a0aae146102de578063141ebd83146102d9578063158ef93e146102d457806318160ddd146102cf5780632366f298146102ca57806323b872dd146102c557806325d2a3f3146102c057806325d3d7cf146102bb578063313ce567146102b6578063382e7244146102b1578063399231e3146102ac5780633ba1356c146102a757806351cff8d9146102a25780635bb5d99d1461029d5780635dea7556146102985780636029bf9f1461029357806361d027b31461028e57806363b0e66a1461028957806368cd03f61461028457806370a082311461027f578063715018a61461027a5780637491687e1461027557806375b8b52f1461027057806380c621991461026b5780638129fc1c146102665780638340f549146102615780638da5cb5b1461025c5780638e0bae7f1461025757806395d89b411461025257806396df10c01461024d578063a376075814610248578063a3ef270b14610243578063a7ab69611461023e578063a9059cbb14610239578063ae76cf2a14610234578063c303a6a71461022f578063c7f71b8a1461022a578063d19bd0a714610225578063d294f09314610220578063dd62ed3e1461021b578063f0f4426014610216578063f2fde38b146102115763fbfa77cf0361000e5761143c565b611399565b611366565b611330565b6112cd565b611298565b611253565b61121e565b6111eb565b6111b5565b611180565b61113b565b611106565b6110b7565b61102f565b610ffa565b610f55565b610f21565b610eee565b610ebb565b610e88565b610e50565b610dea565b610db5565b610d80565b610caa565b610c05565b610b6e565b610b37565b610a22565b6109ef565b6109ba565b610985565b6108e3565b61087c565b61081e565b610796565b610760565b6106ec565b610678565b610643565b6105d2565b6104e6565b61048b565b610399565b60e01c90565b60405190565b600080fd5b600080fd5b600091031261030e57565b6102fe565b5190565b60209181520190565b60005b838110610334575050906000910152565b806020918301518185015201610323565b601f801991011690565b61036e61037760209361037c9361036581610313565b93848093610317565b95869101610320565b610345565b0190565b610396916020820191600081840391015261034f565b90565b346103c9576103a9366004610303565b6103c56103b46115d8565b6103bc6102f3565b91829182610380565b0390f35b6102f9565b600080fd5b60018060a01b031690565b6103e7906103d3565b90565b6103f3816103de565b036103fa57565b600080fd5b9050359061040c826103ea565b565b90565b61041a8161040e565b0361042157565b600080fd5b9050359061043382610411565b565b919060408382031261045e578061045261045b92600086016103ff565b93602001610426565b90565b6102fe565b151590565b61047190610463565b9052565b919061048990600060208501940190610468565b565b346104bc576104b86104a76104a1366004610435565b906115f3565b6104af6102f3565b91829182610475565b0390f35b6102f9565b906020828203126104db576104d8916000016103ff565b90565b6102fe565b60000190565b34610514576104fe6104f93660046104c1565b611706565b6105066102f3565b80610510816104e0565b0390f35b6102f9565b90565b61053061052b610535926103d3565b610519565b6103d3565b90565b6105419061051c565b90565b61054d90610538565b90565b9061055a90610544565b600052602052604060002090565b1c90565b90565b61057f9060086105849302610568565b61056c565b90565b90610592915461056f565b90565b6105ac906105a7601491600092610550565b610587565b90565b6105b89061040e565b9052565b91906105d0906000602085019401906105af565b565b34610602576105fe6105ed6105e83660046104c1565b610595565b6105f56102f3565b918291826105bc565b0390f35b6102f9565b60ff1690565b61061d9060086106229302610568565b610607565b90565b90610630915461060d565b90565b6106406007600090610625565b90565b3461067357610653366004610303565b61066f61065e610633565b6106666102f3565b91829182610475565b0390f35b6102f9565b346106a857610688366004610303565b6106a461069361173d565b61069b6102f3565b918291826105bc565b0390f35b6102f9565b6106e36106ea946106d96060949897956106cf608086019a60008701906105af565b60208501906105af565b60408301906105af565b01906105af565b565b34610720576106fc366004610303565b61071c6107076117ad565b906107139492946102f3565b948594856106ad565b0390f35b6102f9565b909160608284031261075b5761075861074184600085016103ff565b9361074f81602086016103ff565b93604001610426565b90565b6102fe565b346107915761078d61077c610776366004610725565b9161181b565b6107846102f3565b91829182610475565b0390f35b6102f9565b346107c6576107c26107b16107ac3660046104c1565b611942565b6107b96102f3565b918291826105bc565b0390f35b6102f9565b7f000000000000000000000000000000000000000000000000000000000000000090565b6107f890610538565b90565b610804906107ef565b9052565b919061081c906000602085019401906107fb565b565b3461084e5761082e366004610303565b61084a6108396107cb565b6108416102f3565b91829182610808565b0390f35b6102f9565b60ff1690565b61086290610853565b9052565b919061087a90600060208501940190610859565b565b346108ac5761088c366004610303565b6108a8610897611ac8565b61089f6102f3565b91829182610866565b0390f35b6102f9565b906108bb90610544565b600052602052604060002090565b6108e0906108db6016916000926108b1565b610625565b90565b346109135761090f6108fe6108f93660046104c1565b6108c9565b6109066102f3565b91829182610475565b0390f35b6102f9565b906020828203126109325761092f91600001610426565b90565b6102fe565b61094b6109466109509261040e565b610519565b61040e565b90565b9061095d90610937565b600052602052604060002090565b6109829061097d601591600092610953565b610587565b90565b346109b5576109b16109a061099b366004610918565b61096b565b6109a86102f3565b918291826105bc565b0390f35b6102f9565b346109ea576109e66109d56109d03660046104c1565b611adc565b6109dd6102f3565b918291826105bc565b0390f35b6102f9565b34610a1d57610a07610a023660046104c1565b611fa9565b610a0f6102f3565b80610a19816104e0565b0390f35b6102f9565b34610a5057610a3a610a35366004610918565b612052565b610a426102f3565b80610a4c816104e0565b0390f35b6102f9565b9190604083820312610a7e5780610a72610a7b9260008601610426565b93602001610426565b90565b6102fe565b5190565b60209181520190565b60200190565b610a9f9061040e565b9052565b90610ab081602093610a96565b0190565b60200190565b90610ad7610ad1610aca84610a83565b8093610a87565b92610a90565b9060005b818110610ae85750505090565b909192610b01610afb6001928651610aa3565b94610ab4565b9101919091610adb565b9091610b26610b349360408401908482036000860152610aba565b916020818403910152610aba565b90565b34610b6957610b50610b4a366004610a55565b9061212a565b90610b65610b5c6102f3565b92839283610b0b565b0390f35b6102f9565b34610b9c57610b86610b81366004610918565b612537565b610b8e6102f3565b80610b98816104e0565b0390f35b6102f9565b60018060a01b031690565b610bbc906008610bc19302610568565b610ba1565b90565b90610bcf9154610bac565b90565b610bdf600a600090610bc4565b90565b610beb906103de565b9052565b9190610c0390600060208501940190610be2565b565b34610c3557610c15366004610303565b610c31610c20610bd2565b610c286102f3565b91829182610bef565b0390f35b6102f9565b60018060a01b031690565b610c55906008610c5a9302610568565b610c3a565b90565b90610c689154610c45565b90565b610c786008600090610c5d565b90565b610c8490610538565b90565b610c9090610c7b565b9052565b9190610ca890600060208501940190610c87565b565b34610cda57610cba366004610303565b610cd6610cc5610c6b565b610ccd6102f3565b91829182610c94565b0390f35b6102f9565b5190565b60209181520190565b60200190565b610cfb906103de565b9052565b90610d0c81602093610cf2565b0190565b60200190565b90610d33610d2d610d2684610cdf565b8093610ce3565b92610cec565b9060005b818110610d445750505090565b909192610d5d610d576001928651610cff565b94610d10565b9101919091610d37565b610d7d9160208201916000818403910152610d16565b90565b34610db057610d90366004610303565b610dac610d9b612605565b610da36102f3565b91829182610d67565b0390f35b6102f9565b34610de557610de1610dd0610dcb3660046104c1565b61261b565b610dd86102f3565b918291826105bc565b0390f35b6102f9565b34610e1857610dfa366004610303565b610e02612660565b610e0a6102f3565b80610e14816104e0565b0390f35b6102f9565b604090610e47610e4e9496959396610e3d606084019860008501906105af565b60208301906105af565b0190610468565b565b34610e8357610e7f610e6b610e663660046104c1565b61266a565b610e769391936102f3565b93849384610e1d565b0390f35b6102f9565b34610eb657610ea0610e9b366004610918565b6127bc565b610ea86102f3565b80610eb2816104e0565b0390f35b6102f9565b34610ee957610ed3610ece366004610918565b61291c565b610edb6102f3565b80610ee5816104e0565b0390f35b6102f9565b34610f1c57610efe366004610303565b610f06612ce3565b610f0e6102f3565b80610f18816104e0565b0390f35b6102f9565b34610f5057610f3a610f34366004610725565b91612e8a565b610f426102f3565b80610f4c816104e0565b0390f35b6102f9565b34610f8557610f65366004610303565b610f81610f70612e9c565b610f786102f3565b91829182610bef565b0390f35b6102f9565b60018060a01b031690565b610fa5906008610faa9302610568565b610f8a565b90565b90610fb89154610f95565b90565b610fc86009600090610fad565b90565b610fd490610538565b90565b610fe090610fcb565b9052565b9190610ff890600060208501940190610fd7565b565b3461102a5761100a366004610303565b611026611015610fbb565b61101d6102f3565b91829182610fe4565b0390f35b6102f9565b3461105f5761103f366004610303565b61105b61104a612eb2565b6110526102f3565b91829182610380565b0390f35b6102f9565b7f000000000000000000000000000000000000000000000000000000000000000090565b61109190610538565b90565b61109d90611088565b9052565b91906110b590600060208501940190611094565b565b346110e7576110c7366004610303565b6110e36110d2611064565b6110da6102f3565b918291826110a1565b0390f35b6102f9565b611103906110fe601391600092610550565b610587565b90565b346111365761113261112161111c3660046104c1565b6110ec565b6111296102f3565b918291826105bc565b0390f35b6102f9565b3461116b57611167611156611151366004610918565b612ec8565b61115e6102f3565b918291826105bc565b0390f35b6102f9565b61117d6011600090610587565b90565b346111b057611190366004610303565b6111ac61119b611170565b6111a36102f3565b918291826105bc565b0390f35b6102f9565b346111e6576111e26111d16111cb366004610435565b90612ee8565b6111d96102f3565b91829182610475565b0390f35b6102f9565b34611219576112036111fe3660046104c1565b612f77565b61120b6102f3565b80611215816104e0565b0390f35b6102f9565b3461124e5761124a6112396112343660046104c1565b612f82565b6112416102f3565b91829182610475565b0390f35b6102f9565b346112835761127f61126e611269366004610918565b612fa1565b6112766102f3565b918291826105bc565b0390f35b6102f9565b6112956012600090610587565b90565b346112c8576112a8366004610303565b6112c46112b3611288565b6112bb6102f3565b918291826105bc565b0390f35b6102f9565b346112fd576112dd366004610303565b6112f96112e8612ff0565b6112f06102f3565b918291826105bc565b0390f35b6102f9565b919060408382031261132b578061131f61132892600086016103ff565b936020016103ff565b90565b6102fe565b346113615761135d61134c611346366004611302565b9061301b565b6113546102f3565b918291826105bc565b0390f35b6102f9565b346113945761137e6113793660046104c1565b6130d3565b6113866102f3565b80611390816104e0565b0390f35b6102f9565b346113c7576113b16113ac3660046104c1565b61314c565b6113b96102f3565b806113c3816104e0565b0390f35b6102f9565b60018060a01b031690565b6113e79060086113ec9302610568565b6113cc565b90565b906113fa91546113d7565b90565b61140a60076001906113ef565b90565b61141690610538565b90565b6114229061140d565b9052565b919061143a90600060208501940190611419565b565b3461146c5761144c366004610303565b6114686114576113fd565b61145f6102f3565b91829182611426565b0390f35b6102f9565b600080fd5b606090565b634e487b7160e01b600052602260045260246000fd5b90600160028304921680156114b1575b60208310146114ac57565b61147b565b91607f16916114a1565b60209181520190565b600052602060002090565b90600092918054906114ea6114e383611491565b80946114bb565b916001811690816000146115435750600114611506575b505050565b61151391929394506114c4565b916000925b81841061152b5750500190388080611501565b60018160209295939554848601520191019290611518565b92949550505060ff1916825215156020020190388080611501565b90611568916114cf565b90565b634e487b7160e01b600052604160045260246000fd5b9061158b90610345565b810190811067ffffffffffffffff8211176115a557604052565b61156b565b906115ca6115c3926115ba6102f3565b9384809261155e565b0383611581565b565b6115d5906115aa565b90565b6115e0611476565b506115eb60026115cc565b90565b600090565b6115fb6115ee565b5061160e61160882612f82565b15610463565b61162b576116269161161e613157565b919091613164565b600190565b6116336102f3565b633b09f10560e01b81528061164a600482016104e0565b0390fd5b61165f9061165a613174565b6116ac565b565b60001b90565b9061167360ff91611661565b9181191691161790565b61168690610463565b90565b90565b906116a161169c6116a89261167d565b611689565b8254611667565b9055565b6116b5816131c9565b6116cb60016116c6601684906108b1565b61168c565b6117017f3584ac55fd91fcf5efce973892cccf98c9b1bc944e64135fc1b93132a8e3933e916116f86102f3565b91829182610bef565b0390a1565b61170f9061164e565b565b600090565b60001c90565b61172861172d91611716565b61056c565b90565b61173a905461171c565b90565b611745611711565b506117506004611730565b90565b90565b61176a61176561176f92611753565b610519565b61040e565b90565b634e487b7160e01b600052601160045260246000fd5b61179761179d9193929361040e565b9261040e565b82018092116117a857565b611772565b6117b5611711565b506117be611711565b506117c7611711565b506117d0611711565b506117da42612ec8565b906117ef826117e96001611756565b90611788565b6118036117fe60158590610953565b611730565b9161181861181360158490610953565b611730565b90565b91611845926118286115ee565b5061183d611834613157565b8290849161324f565b9190916132e4565b600190565b90565b61186161185c6118669261184a565b610519565b6103d3565b90565b6118729061184d565b90565b61188961188461188e9261184a565b610519565b61040e565b90565b6118a06118a69193929361040e565b9261040e565b82039182116118b157565b611772565b6118c56118cb9193929361040e565b9261040e565b916118d783820261040e565b9281840414901517156118e657565b611772565b90565b6119026118fd611907926118eb565b610519565b61040e565b90565b634e487b7160e01b600052601260045260246000fd5b61192c6119329161040e565b9161040e565b90811561193d570490565b61190a565b61194a611711565b908061196761196161195c6000611869565b6103de565b916103de565b148015611a69575b611a5a5761199a61199561198d61198860058590610550565b611730565b92600f610550565b611730565b806119ae6119a86000611875565b9161040e565b14611a4a575b6119be600e611730565b6119d06119ca8361040e565b9161040e565b1015600014611a3a576119ec906119e7600e611730565b611891565b5b9081611a026119fc6000611875565b9161040e565b11611a0d575b505090565b611a33925090611a1c916118b6565b611a2d670de0b6b3a76400006118ee565b90611920565b3880611a08565b50611a456000611875565b6119ed565b50611a55600e611730565b6119b4565b5050611a666000611875565b90565b50611a7e611a7960058390610550565b611730565b611a91611a8b6000611875565b9161040e565b1461196f565b600090565b90565b611ab3611aae611ab892611a9c565b610519565b610853565b90565b611ac56012611a9f565b90565b611ad0611a97565b50611ad9611abb565b90565b611af3611af891611aeb611711565b50600b610550565b611730565b90565b611b0c90611b076133d3565b611b37565b611b1461343f565b565b611b22611b2791611716565b610c3a565b90565b611b349054611b16565b90565b611b49611b446008611b2a565b610c7b565b611b62611b5c611b57613157565b6103de565b916103de565b03611b7257611b7090611c9c565b565b611b9b611b7d613157565b611b856102f3565b9182916332b2baa360e01b835260048301610bef565b0390fd5b90565b611bb6611bb1611bbb92611b9f565b610519565b61040e565b90565b611bc86063611ba2565b90565b90565b611be2611bdd611be792611bcb565b610519565b61040e565b90565b90611bf760001991611661565b9181191691161790565b90565b90611c19611c14611c2092610937565b611c01565b8254611bea565b9055565b1b90565b91906008611c44910291611c3e60001984611c24565b92611c24565b9181191691161790565b9190611c64611c5f611c6c93610937565b611c01565b908354611c28565b9055565b611c8291611c7c611711565b91611c4e565b565b611c8d9061051c565b90565b611c9990611c84565b90565b611cb0611cab60148390610550565b611730565b9081611cc5611cbf6000611875565b9161040e565b14611f86574280611cde611cd88561040e565b9161040e565b1115611f6357611d09611d03611cfe85611cf86012611730565b90611788565b61040e565b9161040e565b1015611f4057611d1881613453565b50611d2d611d2860138390610550565b611730565b91611d378261261b565b90611d5d611d4d83611d47611bbe565b906118b6565b611d576064611bce565b90611920565b611d70611d6a869261040e565b9161040e565b1015611f37575b83611d8a611d848461040e565b9161040e565b11611f1457611d9a908490613712565b611db8611da76000611875565b611db360148590610550565b611c04565b611dd6611dc56000611875565b611dd160138590610550565b611c04565b611dfe83611df8611de960058690610550565b91611df383611730565b611891565b90611c04565b611e1b611e1484611e0f6004611730565b611891565b6004611c04565b611e2e611e28849261040e565b9161040e565b14611ed2575b611e70611e68611e637f0000000000000000000000000000000000000000000000000000000000000000611088565b611c90565b828491613a2b565b611e78613be7565b90611e836000611869565b9091611ecd611ebb611eb57fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b93611ec46102f3565b918291826105bc565b0390a3565b611ef0611edf6000611875565b611eeb600b8490610550565b611c04565b611ef9816138d8565b611f0f6000611f0a600f8490610550565b611c70565b611e34565b611f1c6102f3565b631e9acf1760e31b815280611f33600482016104e0565b0390fd5b92508092611d77565b611f486102f3565b63dbe67dcd60e01b815280611f5f600482016104e0565b0390fd5b611f6b6102f3565b6360fc88b360e11b815280611f82600482016104e0565b0390fd5b611f8e6102f3565b630b781b4d60e31b815280611fa5600482016104e0565b0390fd5b611fb290611afb565b565b611fc590611fc0613174565b611fc7565b565b80611fe3611fdd611fd86011611730565b61040e565b9161040e565b101561202f57611ff4816011611c04565b61202a7f6f3e5d6a00b186747b385d5be1e4e88c163f2541c4a63e9ecbb55ba29d44670b916120216102f3565b918291826105bc565b0390a1565b6120376102f3565b633cb2b8d760e11b81528061204e600482016104e0565b0390fd5b61205b90611fb4565b565b606090565b9061207561206e6102f3565b9283611581565b565b67ffffffffffffffff811161208f5760208091020190565b61156b565b906120a66120a183612077565b612062565b918252565b369037565b906120d56120bd83612094565b926020806120cb8693612077565b92019103906120ab565b565b60016120e3910161040e565b90565b634e487b7160e01b600052603260045260246000fd5b9061210682610a83565b811015612117576020809102010190565b6120e6565b906121269061040e565b9052565b61215e61215761215161216e9395949561214261205d565b5061214b61205d565b50612ec8565b94612ec8565b8490611891565b6121686001611756565b90611788565b90612178826120b0565b92612182836120b0565b9161218d6000611875565b5b806121a161219b8761040e565b9161040e565b10156121fd576121f8906121f36121e16121dc6121bf878590611788565b6121d5816121d08d918890926120fc565b61211c565b6015610953565b611730565b6121ee87918490926120fc565b61211c565b6120d7565b61218e565b5091925050565b61221061221591611716565b610f8a565b90565b6122229054612204565b90565b6122376122326009612218565b610fcb565b61225061224a612245613157565b6103de565b916103de565b036122605761225e906122ed565b565b61228961226b613157565b6122736102f3565b9182916332b2baa360e01b835260048301610bef565b0390fd5b61229961229e91611716565b610ba1565b90565b6122ab905461228d565b90565b6040906122d86122df94969593966122ce606084019860008501906105af565b60208301906105af565b01906105af565b565b6122ea90610538565b90565b612452906122fa81613d41565b6123046004611730565b6123176123116000611875565b9161040e565b14600014612454576123508161234a61233b6005612335600a6122a1565b90610550565b9161234583611730565b611788565b90611c04565b61236261235d600a6122a1565b613db3565b61237f612378826123736004611730565b611788565b6004611c04565b6123a661238c600e611730565b6123a1600f61239b600a6122a1565b90610550565b611c04565b6123b06000611869565b6123ba600a6122a1565b82916124046123f26123ec7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b936123fb6102f3565b918291826105bc565b0390a35b6124396124347f0000000000000000000000000000000000000000000000000000000000000000611088565b611c90565b90612442613157565b61244b306122e1565b9192613e77565b565b6124826124728261246c670de0b6b3a76400006118ee565b906118b6565b61247c6004611730565b90611920565b61249f61249882612493600e611730565b611788565b600e611c04565b6124e36124b6836124b06064611bce565b90611920565b6124dd6124ce60056124c8600a6122a1565b90610550565b916124d883611730565b611788565b90611c04565b6124f56124f0600a6122a1565b613db3565b8190429161252f7f312c5308f42848705a866c73dec11fd0783c2d64aac6a97e94467062ad3f4058936125266102f3565b938493846122ae565b0390a1612408565b61254090612225565b565b606090565b5490565b60209181520190565b600052602060002090565b612569905461228d565b90565b60010190565b9061258f61258961258284612547565b809361254b565b92612554565b9060005b8181106125a05750505090565b9091926125c06125ba6001926125b58761255f565b610cff565b9461256c565b9101919091612593565b906125d491612572565b90565b906125f76125f0926125e76102f3565b938480926125ca565b0383611581565b565b612602906125d7565b90565b61260d612542565b5061261860106125f9565b90565b6126326126379161262a611711565b506005610550565b611730565b90565b612642613174565b61264a61264c565b565b61265e6126596000611869565b613ec7565b565b61266861263a565b565b90612673611711565b5061267c611711565b506126856115ee565b506126ad6126a86126a061269b60138690610550565b611730565b936014610550565b611730565b9042826126c36126bd6000611875565b9161040e565b141580612704575b90816126d6575b5090565b90506126fd6126f76126f2856126ec6012611730565b90611788565b61040e565b9161040e565b10386126d2565b50806127186127128561040e565b9161040e565b116126cb565b61272f9061272a613174565b612731565b565b8061274d6127476127426012611730565b61040e565b9161040e565b11156127995761275e816012611c04565b6127947f176d9d2c8f84a996862e9cb6ae03eb576184e3fb7621bcbfc6e1828f4b1146809161278b6102f3565b918291826105bc565b0390a1565b6127a16102f3565b6325d4924760e01b8152806127b8600482016104e0565b0390fd5b6127c59061271e565b565b6127d8906127d36133d3565b612806565b6127e061343f565b565b9160206128049294936127fd604082019660008301906105af565b01906105af565b565b61280f81613d41565b612817613157565b908061283361282d6128288561261b565b61040e565b9161040e565b116128f95761286961284f61284a60148590610550565b611730565b61286361285e60138690610550565b611730565b90613712565b61287d426128776011611730565b90611788565b916128938361288e60148490610550565b611c04565b6128a8826128a360138490610550565b611c04565b6128b3838390613f28565b90916128df7f31f69201fab7912e3ec9850e3ab705964bf46d9d4276bdcbb6d05e965e5f540192610544565b926128f46128eb6102f3565b928392836127e2565b0390a2565b6129016102f3565b631e9acf1760e31b815280612918600482016104e0565b0390fd5b612925906127c7565b565b61292f613174565b612937612ac9565b565b61294561294a91611716565b610607565b90565b6129579054612939565b90565b600080fd5b60e01b90565b61296e906103de565b90565b61297a81612965565b0361298157565b600080fd5b9050519061299382612971565b565b906020828203126129af576129ac91600001612986565b90565b6102fe565b6129bc6102f3565b3d6000823e3d90fd5b906129d660018060a01b0391611661565b9181191691161790565b6129e99061051c565b90565b6129f5906129e0565b90565b90565b90612a10612a0b612a17926129ec565b6129f8565b82546129c5565b9055565b612a24906103de565b90565b612a3081612a1b565b03612a3757565b600080fd5b90505190612a4982612a27565b565b90602082820312612a6557612a6291600001612a3c565b90565b6102fe565b612a739061051c565b90565b612a7f90612a6a565b90565b90565b90612a9a612a95612aa192612a76565b612a82565b82546129c5565b9055565b916020612ac7929493612ac060408201966000830190610be2565b0190610be2565b565b612ad3600761294d565b612cc057612b1b6020612b057f00000000000000000000000000000000000000000000000000000000000000006107ef565b6363b0e66a90612b136102f3565b93849261295f565b82528180612b2b600482016104e0565b03915afa8015612cbb57612b4991600091612c8d575b5060086129fb565b612b8d6020612b777f00000000000000000000000000000000000000000000000000000000000000006107ef565b638e0bae7f90612b856102f3565b93849261295f565b82528180612b9d600482016104e0565b03915afa8015612c8857612bbb91600091612c5a575b506009612a85565b612bd5612bd0612bcb6008611b2a565b610c7b565b6131c9565b612bef612bea612be56009612218565b610fcb565b6131c9565b612bfb6001600761168c565b612c0d612c086008611b2a565b610c7b565b612c1f612c1a6009612218565b610fcb565b7f3cd5ec01b1ae7cfec6ca1863e2cd6aa25d6d1702825803ff2b7cc95010fffdc291612c55612c4c6102f3565b92839283612aa5565b0390a1565b612c7b915060203d8111612c81575b612c738183611581565b810190612a4b565b38612bb3565b503d612c69565b6129b4565b612cae915060203d8111612cb4575b612ca68183611581565b810190612995565b38612b41565b503d612c9c565b6129b4565b612cc86102f3565b631499a6b760e21b815280612cdf600482016104e0565b0390fd5b612ceb612927565b565b90612d009291612cfb6133d3565b612d0a565b612d0861343f565b565b9190612d1e612d196008611b2a565b610c7b565b612d37612d31612d2c613157565b6103de565b916103de565b03612d4757612d4592612d74565b565b612d70612d52613157565b612d5a6102f3565b9182916332b2baa360e01b835260048301610bef565b0390fd5b612e2890929192612d84846131c9565b612d8d83613d41565b612d9684613453565b50612dbf83612db9612daa60058890610550565b91612db483611730565b611788565b90611c04565b612ddc612dd584612dd06004611730565b611788565b6004611c04565b612de584613db3565b612e16612e117f0000000000000000000000000000000000000000000000000000000000000000611088565b611c90565b90612e20306122e1565b908492613e77565b612e30613be7565b612e3a6000611869565b919091612e85612e73612e6d7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b93612e7c6102f3565b918291826105bc565b0390a3565b90612e959291612ced565b565b600090565b612ea4612e97565b50612eaf60006122a1565b90565b612eba611476565b50612ec560036115cc565b90565b612ee590612ed4611711565b50612edf6012611730565b90611920565b90565b612f0591612ef46115ee565b50612efd613157565b9190916132e4565b600190565b612f1b90612f16613174565b612f1d565b565b612f26816131c9565b612f3c6000612f37601684906108b1565b61168c565b612f727f124b4488f16f954d5626769cbcab59a035cff89968908f4bbb90c264efcc9b8391612f696102f3565b91829182610bef565b0390a1565b612f8090612f0a565b565b612f99612f9e91612f916115ee565b5060166108b1565b61294d565b90565b612fb8612fbd91612fb0611711565b506015610953565b611730565b90565b612fd190612fcc6133d3565b612fdc565b90612fda61343f565b565b50612fed612fe8613157565b613453565b90565b613000612ffb611711565b612fc0565b90565b9061300d90610544565b600052602052604060002090565b6130409161303661303b9261302e611711565b506006613003565b610550565b611730565b90565b6130549061304f613174565b613079565b565b90565b9061306e61306961307592610544565b613056565b82546129c5565b9055565b613082816131c9565b61308c600a6122a1565b61309782600a613059565b907f430359a6d97ced2b6f93c77a91e7ce9dfd43252eb91e916adba170485cd8a6a4916130ce6130c56102f3565b92839283612aa5565b0390a1565b6130dc90613043565b565b6130ef906130ea613174565b6130f1565b565b8061310d6131076131026000611869565b6103de565b916103de565b1461311d5761311b90613ec7565b565b61314861312a6000611869565b6131326102f3565b91829163b20f76e360e01b835260048301610bef565b0390fd5b613155906130de565b565b61315f612e97565b503390565b916131729291600192613f59565b565b61317c612e9c565b61319561318f61318a613157565b6103de565b916103de565b0361319c57565b6131c56131a7613157565b6131af6102f3565b9182916332b2baa360e01b835260048301610bef565b0390fd5b6131e46131de6131d96000611869565b6103de565b916103de565b146131eb57565b6131f36102f3565b63d92e233d60e01b81528061320a600482016104e0565b0390fd5b60409061323861323f949695939661322e60608401986000850190610be2565b60208301906105af565b01906105af565b565b9061324c910361040e565b90565b92919261325d81839061301b565b908161327361326d60001961040e565b9161040e565b03613280575b5050509050565b8161329361328d8761040e565b9161040e565b106132ba576132b193946132a8919392613241565b90600092613f59565b80388080613279565b506132e0849291926132ca6102f3565b938493630c95cf2760e11b85526004850161320e565b0390fd5b91826133016132fb6132f66000611869565b6103de565b916103de565b14613378578161332261331c6133176000611869565b6103de565b916103de565b14613349578261333461334794613453565b5061333e83613453565b50919091614088565b565b6133746133566000611869565b61335e6102f3565b918291639cfea58360e01b835260048301610bef565b0390fd5b6133a36133856000611869565b61338d6102f3565b9182916313053d9360e21b835260048301610bef565b0390fd5b90565b6133be6133b96133c3926133a7565b610519565b61040e565b90565b6133d060026133aa565b90565b6133dd6001611730565b6133f66133f06133eb6133c6565b61040e565b9161040e565b1461340f5761340d6134066133c6565b6001611c04565b565b6134176102f3565b6306fda65d60e31b81528061342e600482016104e0565b0390fd5b61343c6001611756565b90565b61345161344a613432565b6001611c04565b565b61345b611711565b908061347861347261346d6000611869565b6103de565b916103de565b1480156136e4575b6136d55761349861349360058390610550565b611730565b6134ac6134a7600f8490610550565b611730565b806134c06134ba6000611875565b9161040e565b146136a7575b6134d0600e611730565b6134e26134dc8361040e565b9161040e565b1015600014613697576134fe906134f9600e611730565b611891565b5b908161351461350e6000611875565b9161040e565b11613520575b50505090565b61357f92935061354a91613533916118b6565b613544670de0b6b3a76400006118ee565b90611920565b918261355f6135596000611875565b9161040e565b11613587575b61357a613572600e611730565b91600f610550565b611c04565b38808061351a565b6135af836135a961359a60058590610550565b916135a483611730565b611788565b90611c04565b6135d7836135d16135c2600b8590610550565b916135cc83611730565b611788565b90611c04565b6135f46135ed846135e86004611730565b611788565b6004611c04565b6135fe6000611869565b8184916136496136376136317fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b936136406102f3565b918291826105bc565b0390a38083904261367a7f1ac537f0ad67b64ac68a04587ff3a4cb6977de22eb2c37ee560897a92c6d07c792610544565b9261368f6136866102f3565b928392836127e2565b0390a2613565565b506136a26000611875565b6134ff565b506136c66136b5600e611730565b6136c1600f8590610550565b611c04565b6136d0600e611730565b6134c6565b50506136e16000611875565b90565b506136f96136f460058390610550565b611730565b61370c6137066000611875565b9161040e565b14613480565b806137266137206000611875565b9161040e565b1480156137b4575b6137b05761373b90612ec8565b8161376161375b61375661375160158690610953565b611730565b61040e565b9161040e565b1161378f5761378761377861378d93926015610953565b9161378283611730565b611891565b90611c04565b565b6137ae91506137a96137a16000611875565b916015610953565b611c04565b565b5050565b50816137c96137c36000611875565b9161040e565b1461372e565b6137d881612547565b8210156137f3576137ea600191612554565b91020190600090565b6120e6565b9190600861381891029161381260018060a01b0384611c24565b92611c24565b9181191691161790565b919061383861383361384093610544565b613056565b9083546137f8565b9055565b90565b634e487b7160e01b600052603160045260246000fd5b5490565b600052602060002090565b6138758161385d565b82101561389057613887600191613861565b91020190600090565b6120e6565b6138a7916138a1612e97565b91613822565b565b6138b28161385d565b80156138d35760019003906138d06138ca838361386c565b90613895565b55565b613847565b6138ec6138e7600c83906108b1565b61294d565b6138f4575b50565b61397f9061390c613907600d8390610550565b611730565b6139296139196010612547565b6139236001611756565b90611891565b908061393d6139378461040e565b9161040e565b03613985575b50506139576139526010613844565b6138a9565b61396d6000613968600d8490610550565b611c70565b61397a600091600c6108b1565b61168c565b386138f1565b6139be61399f6139996139c39460106137cf565b90610bc4565b916139b6836139b0601084906137cf565b90613822565b91600d610550565b611c04565b3880613943565b6139d390610538565b90565b63ffffffff1690565b63ffffffff60e01b1690565b6139ff6139fa613a04926139d6565b61295f565b6139df565b90565b916020613a29929493613a2260408201966000830190610be2565b01906105af565b565b90613a72613a7793613a6360049493613a4a63a9059cbb9193916139eb565b92613a536102f3565b9687946020860190815201613a07565b60208201810382520383611581565b614262565b565b60081c90565b613a8b613a9091613a79565b6113cc565b90565b613a9d9054613a7f565b90565b600080fd5b67ffffffffffffffff8111613abd5760208091020190565b61156b565b600080fd5b90505190613ad4826103ea565b565b90929192613aeb613ae682613aa5565b612062565b9381855260208086019202830192818411613b2857915b838310613b0f5750505050565b60208091613b1d8486613ac7565b815201920191613b02565b613ac2565b9080601f83011215613b4b57816020613b4893519101613ad6565b90565b613aa0565b90602082820312613b8157600082015167ffffffffffffffff8111613b7c57613b799201613b2d565b90565b6103ce565b6102fe565b90613b9082610cdf565b811015613ba1576020809102010190565b6120e6565b613bb090516103de565b90565b613bbc9061051c565b90565b613bc890613bb3565b90565b613bd490610538565b90565b6000910312613be257565b6102fe565b613c146000613bfe613bf96007613a93565b61140d565b63b4e8a6c490613c0c6102f3565b93849261295f565b82528180613c24600482016104e0565b03915afa908115613d3c57600091613d19575b50613c4181610cdf565b91613c4a611711565b5b80613c5e613c588661040e565b9161040e565b1015613d1357613c87613c82613c7d613c78868590613b86565b613ba6565b613bbf565b613bcb565b9063f8ba4cff91803b15613d0e57613cac92600091613ca46102f3565b94859261295f565b8252818381613cbd600482016104e0565b03925af1918215613d0957613cd792613cdc575b506120d7565b613c4b565b613cfc9060003d8111613d02575b613cf48183611581565b810190613bd7565b38613cd1565b503d613cea565b6129b4565b61295a565b50915050565b613d3691503d806000833e613d2e8183611581565b810190613b50565b38613c37565b6129b4565b613d54613d4e6000611875565b9161040e565b14613d5b57565b613d636102f3565b631f2a200560e01b815280613d7a600482016104e0565b0390fd5b9081549168010000000000000000831015613dae5782613da6916001613dac9501815561386c565b90613822565b565b61156b565b613dd0613dca613dc5600c84906108b1565b61294d565b15610463565b613dd8575b50565b613e3e90613dfa613de96010612547565b613df5600d8490610550565b611c04565b613e0e613e076010613844565b8290613d7e565b613e246001613e1f600c84906108b1565b61168c565b613e39613e31600e611730565b91600f610550565b611c04565b38613dd5565b604090613e6e613e759496959396613e6460608401986000850190610be2565b6020830190610be2565b01906105af565b565b600492613eb1613ec59593613ec09394613e986323b872dd929491926139eb565b93613ea16102f3565b9788956020870190815201613e44565b60208201810382520383611581565b614262565b565b613ed160006122a1565b613edc826000613059565b90613f10613f0a7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e093610544565b91610544565b91613f196102f3565b80613f23816104e0565b0390a3565b90613f51613f42613f3b613f5794612ec8565b6015610953565b91613f4c83611730565b611788565b90611c04565b565b909281613f77613f71613f6c6000611869565b6103de565b916103de565b1461404b5783613f98613f92613f8d6000611869565b6103de565b916103de565b1461401c57613fbc83613fb7613fb060068690613003565b8790610550565b611c04565b613fc6575b505050565b919091614011613fff613ff97f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92593610544565b93610544565b936140086102f3565b918291826105bc565b0390a3388080613fc1565b6140476140296000611869565b6140316102f3565b91829163270af7ed60e11b835260048301610bef565b0390fd5b6140766140586000611869565b6140606102f3565b9182916322f051b160e21b835260048301610bef565b0390fd5b90614085910161040e565b90565b919091806140a76140a161409c6000611869565b6103de565b916103de565b14600014614195576140cc6140c5836140c06004611730565b611788565b6004611c04565b5b826140e96140e36140de6000611869565b6103de565b916103de565b1460001461415f5761410e614107836141026004611730565b613241565b6004611c04565b5b91909161415a6141486141427fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b936141516102f3565b918291826105bc565b0390a3565b6141878261418161417260058790610550565b9161417c83611730565b61407a565b90611c04565b61419083613db3565b61410f565b6141a96141a460058390610550565b611730565b806141bc6141b68561040e565b9161040e565b1061423f576141e06141cf828590613241565b6141db60058590610550565b611c04565b6141f26141ec8461040e565b9161040e565b146141fd575b6140cd565b61421b61420a6000611875565b614216600b8490610550565b611c04565b614224816138d8565b61423a6000614235600f8490610550565b611c70565b6141f8565b6142476102f3565b631e9acf1760e31b81528061425e600482016104e0565b0390fd5b906000602091614270611711565b50614279611711565b50828151910182855af115614317573d600051906142a061429a6000611875565b9161040e565b146000146142fd57506142b2816139ca565b3b6142c66142c06000611875565b9161040e565b145b6142cf5750565b6142db6142f9916139ca565b6142e36102f3565b918291635274afe760e01b835260048301610bef565b0390fd5b61431061430a6001611756565b9161040e565b14156142c8565b6040513d6000823e3d90fdfea264697066735822122084b5a5e8ba9dee653411d0330aea5c6edd8fa180f07c4cd00cd21500e9ea71bb64736f6c63430008180033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c00000000000000000000000012684d18bdba8e31936f40abce1175366874114f000000000000000000000000000000000000000000000000000000000000000b5374616b6564204455535800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067374445553580000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361015610013575b611471565b61001e6000356102ed565b806306fdde03146102e8578063095ea7b3146102e3578063099a0aae146102de578063141ebd83146102d9578063158ef93e146102d457806318160ddd146102cf5780632366f298146102ca57806323b872dd146102c557806325d2a3f3146102c057806325d3d7cf146102bb578063313ce567146102b6578063382e7244146102b1578063399231e3146102ac5780633ba1356c146102a757806351cff8d9146102a25780635bb5d99d1461029d5780635dea7556146102985780636029bf9f1461029357806361d027b31461028e57806363b0e66a1461028957806368cd03f61461028457806370a082311461027f578063715018a61461027a5780637491687e1461027557806375b8b52f1461027057806380c621991461026b5780638129fc1c146102665780638340f549146102615780638da5cb5b1461025c5780638e0bae7f1461025757806395d89b411461025257806396df10c01461024d578063a376075814610248578063a3ef270b14610243578063a7ab69611461023e578063a9059cbb14610239578063ae76cf2a14610234578063c303a6a71461022f578063c7f71b8a1461022a578063d19bd0a714610225578063d294f09314610220578063dd62ed3e1461021b578063f0f4426014610216578063f2fde38b146102115763fbfa77cf0361000e5761143c565b611399565b611366565b611330565b6112cd565b611298565b611253565b61121e565b6111eb565b6111b5565b611180565b61113b565b611106565b6110b7565b61102f565b610ffa565b610f55565b610f21565b610eee565b610ebb565b610e88565b610e50565b610dea565b610db5565b610d80565b610caa565b610c05565b610b6e565b610b37565b610a22565b6109ef565b6109ba565b610985565b6108e3565b61087c565b61081e565b610796565b610760565b6106ec565b610678565b610643565b6105d2565b6104e6565b61048b565b610399565b60e01c90565b60405190565b600080fd5b600080fd5b600091031261030e57565b6102fe565b5190565b60209181520190565b60005b838110610334575050906000910152565b806020918301518185015201610323565b601f801991011690565b61036e61037760209361037c9361036581610313565b93848093610317565b95869101610320565b610345565b0190565b610396916020820191600081840391015261034f565b90565b346103c9576103a9366004610303565b6103c56103b46115d8565b6103bc6102f3565b91829182610380565b0390f35b6102f9565b600080fd5b60018060a01b031690565b6103e7906103d3565b90565b6103f3816103de565b036103fa57565b600080fd5b9050359061040c826103ea565b565b90565b61041a8161040e565b0361042157565b600080fd5b9050359061043382610411565b565b919060408382031261045e578061045261045b92600086016103ff565b93602001610426565b90565b6102fe565b151590565b61047190610463565b9052565b919061048990600060208501940190610468565b565b346104bc576104b86104a76104a1366004610435565b906115f3565b6104af6102f3565b91829182610475565b0390f35b6102f9565b906020828203126104db576104d8916000016103ff565b90565b6102fe565b60000190565b34610514576104fe6104f93660046104c1565b611706565b6105066102f3565b80610510816104e0565b0390f35b6102f9565b90565b61053061052b610535926103d3565b610519565b6103d3565b90565b6105419061051c565b90565b61054d90610538565b90565b9061055a90610544565b600052602052604060002090565b1c90565b90565b61057f9060086105849302610568565b61056c565b90565b90610592915461056f565b90565b6105ac906105a7601491600092610550565b610587565b90565b6105b89061040e565b9052565b91906105d0906000602085019401906105af565b565b34610602576105fe6105ed6105e83660046104c1565b610595565b6105f56102f3565b918291826105bc565b0390f35b6102f9565b60ff1690565b61061d9060086106229302610568565b610607565b90565b90610630915461060d565b90565b6106406007600090610625565b90565b3461067357610653366004610303565b61066f61065e610633565b6106666102f3565b91829182610475565b0390f35b6102f9565b346106a857610688366004610303565b6106a461069361173d565b61069b6102f3565b918291826105bc565b0390f35b6102f9565b6106e36106ea946106d96060949897956106cf608086019a60008701906105af565b60208501906105af565b60408301906105af565b01906105af565b565b34610720576106fc366004610303565b61071c6107076117ad565b906107139492946102f3565b948594856106ad565b0390f35b6102f9565b909160608284031261075b5761075861074184600085016103ff565b9361074f81602086016103ff565b93604001610426565b90565b6102fe565b346107915761078d61077c610776366004610725565b9161181b565b6107846102f3565b91829182610475565b0390f35b6102f9565b346107c6576107c26107b16107ac3660046104c1565b611942565b6107b96102f3565b918291826105bc565b0390f35b6102f9565b7f0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c90565b6107f890610538565b90565b610804906107ef565b9052565b919061081c906000602085019401906107fb565b565b3461084e5761082e366004610303565b61084a6108396107cb565b6108416102f3565b91829182610808565b0390f35b6102f9565b60ff1690565b61086290610853565b9052565b919061087a90600060208501940190610859565b565b346108ac5761088c366004610303565b6108a8610897611ac8565b61089f6102f3565b91829182610866565b0390f35b6102f9565b906108bb90610544565b600052602052604060002090565b6108e0906108db6016916000926108b1565b610625565b90565b346109135761090f6108fe6108f93660046104c1565b6108c9565b6109066102f3565b91829182610475565b0390f35b6102f9565b906020828203126109325761092f91600001610426565b90565b6102fe565b61094b6109466109509261040e565b610519565b61040e565b90565b9061095d90610937565b600052602052604060002090565b6109829061097d601591600092610953565b610587565b90565b346109b5576109b16109a061099b366004610918565b61096b565b6109a86102f3565b918291826105bc565b0390f35b6102f9565b346109ea576109e66109d56109d03660046104c1565b611adc565b6109dd6102f3565b918291826105bc565b0390f35b6102f9565b34610a1d57610a07610a023660046104c1565b611fa9565b610a0f6102f3565b80610a19816104e0565b0390f35b6102f9565b34610a5057610a3a610a35366004610918565b612052565b610a426102f3565b80610a4c816104e0565b0390f35b6102f9565b9190604083820312610a7e5780610a72610a7b9260008601610426565b93602001610426565b90565b6102fe565b5190565b60209181520190565b60200190565b610a9f9061040e565b9052565b90610ab081602093610a96565b0190565b60200190565b90610ad7610ad1610aca84610a83565b8093610a87565b92610a90565b9060005b818110610ae85750505090565b909192610b01610afb6001928651610aa3565b94610ab4565b9101919091610adb565b9091610b26610b349360408401908482036000860152610aba565b916020818403910152610aba565b90565b34610b6957610b50610b4a366004610a55565b9061212a565b90610b65610b5c6102f3565b92839283610b0b565b0390f35b6102f9565b34610b9c57610b86610b81366004610918565b612537565b610b8e6102f3565b80610b98816104e0565b0390f35b6102f9565b60018060a01b031690565b610bbc906008610bc19302610568565b610ba1565b90565b90610bcf9154610bac565b90565b610bdf600a600090610bc4565b90565b610beb906103de565b9052565b9190610c0390600060208501940190610be2565b565b34610c3557610c15366004610303565b610c31610c20610bd2565b610c286102f3565b91829182610bef565b0390f35b6102f9565b60018060a01b031690565b610c55906008610c5a9302610568565b610c3a565b90565b90610c689154610c45565b90565b610c786008600090610c5d565b90565b610c8490610538565b90565b610c9090610c7b565b9052565b9190610ca890600060208501940190610c87565b565b34610cda57610cba366004610303565b610cd6610cc5610c6b565b610ccd6102f3565b91829182610c94565b0390f35b6102f9565b5190565b60209181520190565b60200190565b610cfb906103de565b9052565b90610d0c81602093610cf2565b0190565b60200190565b90610d33610d2d610d2684610cdf565b8093610ce3565b92610cec565b9060005b818110610d445750505090565b909192610d5d610d576001928651610cff565b94610d10565b9101919091610d37565b610d7d9160208201916000818403910152610d16565b90565b34610db057610d90366004610303565b610dac610d9b612605565b610da36102f3565b91829182610d67565b0390f35b6102f9565b34610de557610de1610dd0610dcb3660046104c1565b61261b565b610dd86102f3565b918291826105bc565b0390f35b6102f9565b34610e1857610dfa366004610303565b610e02612660565b610e0a6102f3565b80610e14816104e0565b0390f35b6102f9565b604090610e47610e4e9496959396610e3d606084019860008501906105af565b60208301906105af565b0190610468565b565b34610e8357610e7f610e6b610e663660046104c1565b61266a565b610e769391936102f3565b93849384610e1d565b0390f35b6102f9565b34610eb657610ea0610e9b366004610918565b6127bc565b610ea86102f3565b80610eb2816104e0565b0390f35b6102f9565b34610ee957610ed3610ece366004610918565b61291c565b610edb6102f3565b80610ee5816104e0565b0390f35b6102f9565b34610f1c57610efe366004610303565b610f06612ce3565b610f0e6102f3565b80610f18816104e0565b0390f35b6102f9565b34610f5057610f3a610f34366004610725565b91612e8a565b610f426102f3565b80610f4c816104e0565b0390f35b6102f9565b34610f8557610f65366004610303565b610f81610f70612e9c565b610f786102f3565b91829182610bef565b0390f35b6102f9565b60018060a01b031690565b610fa5906008610faa9302610568565b610f8a565b90565b90610fb89154610f95565b90565b610fc86009600090610fad565b90565b610fd490610538565b90565b610fe090610fcb565b9052565b9190610ff890600060208501940190610fd7565b565b3461102a5761100a366004610303565b611026611015610fbb565b61101d6102f3565b91829182610fe4565b0390f35b6102f9565b3461105f5761103f366004610303565b61105b61104a612eb2565b6110526102f3565b91829182610380565b0390f35b6102f9565b7f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f85490565b61109190610538565b90565b61109d90611088565b9052565b91906110b590600060208501940190611094565b565b346110e7576110c7366004610303565b6110e36110d2611064565b6110da6102f3565b918291826110a1565b0390f35b6102f9565b611103906110fe601391600092610550565b610587565b90565b346111365761113261112161111c3660046104c1565b6110ec565b6111296102f3565b918291826105bc565b0390f35b6102f9565b3461116b57611167611156611151366004610918565b612ec8565b61115e6102f3565b918291826105bc565b0390f35b6102f9565b61117d6011600090610587565b90565b346111b057611190366004610303565b6111ac61119b611170565b6111a36102f3565b918291826105bc565b0390f35b6102f9565b346111e6576111e26111d16111cb366004610435565b90612ee8565b6111d96102f3565b91829182610475565b0390f35b6102f9565b34611219576112036111fe3660046104c1565b612f77565b61120b6102f3565b80611215816104e0565b0390f35b6102f9565b3461124e5761124a6112396112343660046104c1565b612f82565b6112416102f3565b91829182610475565b0390f35b6102f9565b346112835761127f61126e611269366004610918565b612fa1565b6112766102f3565b918291826105bc565b0390f35b6102f9565b6112956012600090610587565b90565b346112c8576112a8366004610303565b6112c46112b3611288565b6112bb6102f3565b918291826105bc565b0390f35b6102f9565b346112fd576112dd366004610303565b6112f96112e8612ff0565b6112f06102f3565b918291826105bc565b0390f35b6102f9565b919060408382031261132b578061131f61132892600086016103ff565b936020016103ff565b90565b6102fe565b346113615761135d61134c611346366004611302565b9061301b565b6113546102f3565b918291826105bc565b0390f35b6102f9565b346113945761137e6113793660046104c1565b6130d3565b6113866102f3565b80611390816104e0565b0390f35b6102f9565b346113c7576113b16113ac3660046104c1565b61314c565b6113b96102f3565b806113c3816104e0565b0390f35b6102f9565b60018060a01b031690565b6113e79060086113ec9302610568565b6113cc565b90565b906113fa91546113d7565b90565b61140a60076001906113ef565b90565b61141690610538565b90565b6114229061140d565b9052565b919061143a90600060208501940190611419565b565b3461146c5761144c366004610303565b6114686114576113fd565b61145f6102f3565b91829182611426565b0390f35b6102f9565b600080fd5b606090565b634e487b7160e01b600052602260045260246000fd5b90600160028304921680156114b1575b60208310146114ac57565b61147b565b91607f16916114a1565b60209181520190565b600052602060002090565b90600092918054906114ea6114e383611491565b80946114bb565b916001811690816000146115435750600114611506575b505050565b61151391929394506114c4565b916000925b81841061152b5750500190388080611501565b60018160209295939554848601520191019290611518565b92949550505060ff1916825215156020020190388080611501565b90611568916114cf565b90565b634e487b7160e01b600052604160045260246000fd5b9061158b90610345565b810190811067ffffffffffffffff8211176115a557604052565b61156b565b906115ca6115c3926115ba6102f3565b9384809261155e565b0383611581565b565b6115d5906115aa565b90565b6115e0611476565b506115eb60026115cc565b90565b600090565b6115fb6115ee565b5061160e61160882612f82565b15610463565b61162b576116269161161e613157565b919091613164565b600190565b6116336102f3565b633b09f10560e01b81528061164a600482016104e0565b0390fd5b61165f9061165a613174565b6116ac565b565b60001b90565b9061167360ff91611661565b9181191691161790565b61168690610463565b90565b90565b906116a161169c6116a89261167d565b611689565b8254611667565b9055565b6116b5816131c9565b6116cb60016116c6601684906108b1565b61168c565b6117017f3584ac55fd91fcf5efce973892cccf98c9b1bc944e64135fc1b93132a8e3933e916116f86102f3565b91829182610bef565b0390a1565b61170f9061164e565b565b600090565b60001c90565b61172861172d91611716565b61056c565b90565b61173a905461171c565b90565b611745611711565b506117506004611730565b90565b90565b61176a61176561176f92611753565b610519565b61040e565b90565b634e487b7160e01b600052601160045260246000fd5b61179761179d9193929361040e565b9261040e565b82018092116117a857565b611772565b6117b5611711565b506117be611711565b506117c7611711565b506117d0611711565b506117da42612ec8565b906117ef826117e96001611756565b90611788565b6118036117fe60158590610953565b611730565b9161181861181360158490610953565b611730565b90565b91611845926118286115ee565b5061183d611834613157565b8290849161324f565b9190916132e4565b600190565b90565b61186161185c6118669261184a565b610519565b6103d3565b90565b6118729061184d565b90565b61188961188461188e9261184a565b610519565b61040e565b90565b6118a06118a69193929361040e565b9261040e565b82039182116118b157565b611772565b6118c56118cb9193929361040e565b9261040e565b916118d783820261040e565b9281840414901517156118e657565b611772565b90565b6119026118fd611907926118eb565b610519565b61040e565b90565b634e487b7160e01b600052601260045260246000fd5b61192c6119329161040e565b9161040e565b90811561193d570490565b61190a565b61194a611711565b908061196761196161195c6000611869565b6103de565b916103de565b148015611a69575b611a5a5761199a61199561198d61198860058590610550565b611730565b92600f610550565b611730565b806119ae6119a86000611875565b9161040e565b14611a4a575b6119be600e611730565b6119d06119ca8361040e565b9161040e565b1015600014611a3a576119ec906119e7600e611730565b611891565b5b9081611a026119fc6000611875565b9161040e565b11611a0d575b505090565b611a33925090611a1c916118b6565b611a2d670de0b6b3a76400006118ee565b90611920565b3880611a08565b50611a456000611875565b6119ed565b50611a55600e611730565b6119b4565b5050611a666000611875565b90565b50611a7e611a7960058390610550565b611730565b611a91611a8b6000611875565b9161040e565b1461196f565b600090565b90565b611ab3611aae611ab892611a9c565b610519565b610853565b90565b611ac56012611a9f565b90565b611ad0611a97565b50611ad9611abb565b90565b611af3611af891611aeb611711565b50600b610550565b611730565b90565b611b0c90611b076133d3565b611b37565b611b1461343f565b565b611b22611b2791611716565b610c3a565b90565b611b349054611b16565b90565b611b49611b446008611b2a565b610c7b565b611b62611b5c611b57613157565b6103de565b916103de565b03611b7257611b7090611c9c565b565b611b9b611b7d613157565b611b856102f3565b9182916332b2baa360e01b835260048301610bef565b0390fd5b90565b611bb6611bb1611bbb92611b9f565b610519565b61040e565b90565b611bc86063611ba2565b90565b90565b611be2611bdd611be792611bcb565b610519565b61040e565b90565b90611bf760001991611661565b9181191691161790565b90565b90611c19611c14611c2092610937565b611c01565b8254611bea565b9055565b1b90565b91906008611c44910291611c3e60001984611c24565b92611c24565b9181191691161790565b9190611c64611c5f611c6c93610937565b611c01565b908354611c28565b9055565b611c8291611c7c611711565b91611c4e565b565b611c8d9061051c565b90565b611c9990611c84565b90565b611cb0611cab60148390610550565b611730565b9081611cc5611cbf6000611875565b9161040e565b14611f86574280611cde611cd88561040e565b9161040e565b1115611f6357611d09611d03611cfe85611cf86012611730565b90611788565b61040e565b9161040e565b1015611f4057611d1881613453565b50611d2d611d2860138390610550565b611730565b91611d378261261b565b90611d5d611d4d83611d47611bbe565b906118b6565b611d576064611bce565b90611920565b611d70611d6a869261040e565b9161040e565b1015611f37575b83611d8a611d848461040e565b9161040e565b11611f1457611d9a908490613712565b611db8611da76000611875565b611db360148590610550565b611c04565b611dd6611dc56000611875565b611dd160138590610550565b611c04565b611dfe83611df8611de960058690610550565b91611df383611730565b611891565b90611c04565b611e1b611e1484611e0f6004611730565b611891565b6004611c04565b611e2e611e28849261040e565b9161040e565b14611ed2575b611e70611e68611e637f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f854611088565b611c90565b828491613a2b565b611e78613be7565b90611e836000611869565b9091611ecd611ebb611eb57fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b93611ec46102f3565b918291826105bc565b0390a3565b611ef0611edf6000611875565b611eeb600b8490610550565b611c04565b611ef9816138d8565b611f0f6000611f0a600f8490610550565b611c70565b611e34565b611f1c6102f3565b631e9acf1760e31b815280611f33600482016104e0565b0390fd5b92508092611d77565b611f486102f3565b63dbe67dcd60e01b815280611f5f600482016104e0565b0390fd5b611f6b6102f3565b6360fc88b360e11b815280611f82600482016104e0565b0390fd5b611f8e6102f3565b630b781b4d60e31b815280611fa5600482016104e0565b0390fd5b611fb290611afb565b565b611fc590611fc0613174565b611fc7565b565b80611fe3611fdd611fd86011611730565b61040e565b9161040e565b101561202f57611ff4816011611c04565b61202a7f6f3e5d6a00b186747b385d5be1e4e88c163f2541c4a63e9ecbb55ba29d44670b916120216102f3565b918291826105bc565b0390a1565b6120376102f3565b633cb2b8d760e11b81528061204e600482016104e0565b0390fd5b61205b90611fb4565b565b606090565b9061207561206e6102f3565b9283611581565b565b67ffffffffffffffff811161208f5760208091020190565b61156b565b906120a66120a183612077565b612062565b918252565b369037565b906120d56120bd83612094565b926020806120cb8693612077565b92019103906120ab565b565b60016120e3910161040e565b90565b634e487b7160e01b600052603260045260246000fd5b9061210682610a83565b811015612117576020809102010190565b6120e6565b906121269061040e565b9052565b61215e61215761215161216e9395949561214261205d565b5061214b61205d565b50612ec8565b94612ec8565b8490611891565b6121686001611756565b90611788565b90612178826120b0565b92612182836120b0565b9161218d6000611875565b5b806121a161219b8761040e565b9161040e565b10156121fd576121f8906121f36121e16121dc6121bf878590611788565b6121d5816121d08d918890926120fc565b61211c565b6015610953565b611730565b6121ee87918490926120fc565b61211c565b6120d7565b61218e565b5091925050565b61221061221591611716565b610f8a565b90565b6122229054612204565b90565b6122376122326009612218565b610fcb565b61225061224a612245613157565b6103de565b916103de565b036122605761225e906122ed565b565b61228961226b613157565b6122736102f3565b9182916332b2baa360e01b835260048301610bef565b0390fd5b61229961229e91611716565b610ba1565b90565b6122ab905461228d565b90565b6040906122d86122df94969593966122ce606084019860008501906105af565b60208301906105af565b01906105af565b565b6122ea90610538565b90565b612452906122fa81613d41565b6123046004611730565b6123176123116000611875565b9161040e565b14600014612454576123508161234a61233b6005612335600a6122a1565b90610550565b9161234583611730565b611788565b90611c04565b61236261235d600a6122a1565b613db3565b61237f612378826123736004611730565b611788565b6004611c04565b6123a661238c600e611730565b6123a1600f61239b600a6122a1565b90610550565b611c04565b6123b06000611869565b6123ba600a6122a1565b82916124046123f26123ec7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b936123fb6102f3565b918291826105bc565b0390a35b6124396124347f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f854611088565b611c90565b90612442613157565b61244b306122e1565b9192613e77565b565b6124826124728261246c670de0b6b3a76400006118ee565b906118b6565b61247c6004611730565b90611920565b61249f61249882612493600e611730565b611788565b600e611c04565b6124e36124b6836124b06064611bce565b90611920565b6124dd6124ce60056124c8600a6122a1565b90610550565b916124d883611730565b611788565b90611c04565b6124f56124f0600a6122a1565b613db3565b8190429161252f7f312c5308f42848705a866c73dec11fd0783c2d64aac6a97e94467062ad3f4058936125266102f3565b938493846122ae565b0390a1612408565b61254090612225565b565b606090565b5490565b60209181520190565b600052602060002090565b612569905461228d565b90565b60010190565b9061258f61258961258284612547565b809361254b565b92612554565b9060005b8181106125a05750505090565b9091926125c06125ba6001926125b58761255f565b610cff565b9461256c565b9101919091612593565b906125d491612572565b90565b906125f76125f0926125e76102f3565b938480926125ca565b0383611581565b565b612602906125d7565b90565b61260d612542565b5061261860106125f9565b90565b6126326126379161262a611711565b506005610550565b611730565b90565b612642613174565b61264a61264c565b565b61265e6126596000611869565b613ec7565b565b61266861263a565b565b90612673611711565b5061267c611711565b506126856115ee565b506126ad6126a86126a061269b60138690610550565b611730565b936014610550565b611730565b9042826126c36126bd6000611875565b9161040e565b141580612704575b90816126d6575b5090565b90506126fd6126f76126f2856126ec6012611730565b90611788565b61040e565b9161040e565b10386126d2565b50806127186127128561040e565b9161040e565b116126cb565b61272f9061272a613174565b612731565b565b8061274d6127476127426012611730565b61040e565b9161040e565b11156127995761275e816012611c04565b6127947f176d9d2c8f84a996862e9cb6ae03eb576184e3fb7621bcbfc6e1828f4b1146809161278b6102f3565b918291826105bc565b0390a1565b6127a16102f3565b6325d4924760e01b8152806127b8600482016104e0565b0390fd5b6127c59061271e565b565b6127d8906127d36133d3565b612806565b6127e061343f565b565b9160206128049294936127fd604082019660008301906105af565b01906105af565b565b61280f81613d41565b612817613157565b908061283361282d6128288561261b565b61040e565b9161040e565b116128f95761286961284f61284a60148590610550565b611730565b61286361285e60138690610550565b611730565b90613712565b61287d426128776011611730565b90611788565b916128938361288e60148490610550565b611c04565b6128a8826128a360138490610550565b611c04565b6128b3838390613f28565b90916128df7f31f69201fab7912e3ec9850e3ab705964bf46d9d4276bdcbb6d05e965e5f540192610544565b926128f46128eb6102f3565b928392836127e2565b0390a2565b6129016102f3565b631e9acf1760e31b815280612918600482016104e0565b0390fd5b612925906127c7565b565b61292f613174565b612937612ac9565b565b61294561294a91611716565b610607565b90565b6129579054612939565b90565b600080fd5b60e01b90565b61296e906103de565b90565b61297a81612965565b0361298157565b600080fd5b9050519061299382612971565b565b906020828203126129af576129ac91600001612986565b90565b6102fe565b6129bc6102f3565b3d6000823e3d90fd5b906129d660018060a01b0391611661565b9181191691161790565b6129e99061051c565b90565b6129f5906129e0565b90565b90565b90612a10612a0b612a17926129ec565b6129f8565b82546129c5565b9055565b612a24906103de565b90565b612a3081612a1b565b03612a3757565b600080fd5b90505190612a4982612a27565b565b90602082820312612a6557612a6291600001612a3c565b90565b6102fe565b612a739061051c565b90565b612a7f90612a6a565b90565b90565b90612a9a612a95612aa192612a76565b612a82565b82546129c5565b9055565b916020612ac7929493612ac060408201966000830190610be2565b0190610be2565b565b612ad3600761294d565b612cc057612b1b6020612b057f0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c6107ef565b6363b0e66a90612b136102f3565b93849261295f565b82528180612b2b600482016104e0565b03915afa8015612cbb57612b4991600091612c8d575b5060086129fb565b612b8d6020612b777f0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c6107ef565b638e0bae7f90612b856102f3565b93849261295f565b82528180612b9d600482016104e0565b03915afa8015612c8857612bbb91600091612c5a575b506009612a85565b612bd5612bd0612bcb6008611b2a565b610c7b565b6131c9565b612bef612bea612be56009612218565b610fcb565b6131c9565b612bfb6001600761168c565b612c0d612c086008611b2a565b610c7b565b612c1f612c1a6009612218565b610fcb565b7f3cd5ec01b1ae7cfec6ca1863e2cd6aa25d6d1702825803ff2b7cc95010fffdc291612c55612c4c6102f3565b92839283612aa5565b0390a1565b612c7b915060203d8111612c81575b612c738183611581565b810190612a4b565b38612bb3565b503d612c69565b6129b4565b612cae915060203d8111612cb4575b612ca68183611581565b810190612995565b38612b41565b503d612c9c565b6129b4565b612cc86102f3565b631499a6b760e21b815280612cdf600482016104e0565b0390fd5b612ceb612927565b565b90612d009291612cfb6133d3565b612d0a565b612d0861343f565b565b9190612d1e612d196008611b2a565b610c7b565b612d37612d31612d2c613157565b6103de565b916103de565b03612d4757612d4592612d74565b565b612d70612d52613157565b612d5a6102f3565b9182916332b2baa360e01b835260048301610bef565b0390fd5b612e2890929192612d84846131c9565b612d8d83613d41565b612d9684613453565b50612dbf83612db9612daa60058890610550565b91612db483611730565b611788565b90611c04565b612ddc612dd584612dd06004611730565b611788565b6004611c04565b612de584613db3565b612e16612e117f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f854611088565b611c90565b90612e20306122e1565b908492613e77565b612e30613be7565b612e3a6000611869565b919091612e85612e73612e6d7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b93612e7c6102f3565b918291826105bc565b0390a3565b90612e959291612ced565b565b600090565b612ea4612e97565b50612eaf60006122a1565b90565b612eba611476565b50612ec560036115cc565b90565b612ee590612ed4611711565b50612edf6012611730565b90611920565b90565b612f0591612ef46115ee565b50612efd613157565b9190916132e4565b600190565b612f1b90612f16613174565b612f1d565b565b612f26816131c9565b612f3c6000612f37601684906108b1565b61168c565b612f727f124b4488f16f954d5626769cbcab59a035cff89968908f4bbb90c264efcc9b8391612f696102f3565b91829182610bef565b0390a1565b612f8090612f0a565b565b612f99612f9e91612f916115ee565b5060166108b1565b61294d565b90565b612fb8612fbd91612fb0611711565b506015610953565b611730565b90565b612fd190612fcc6133d3565b612fdc565b90612fda61343f565b565b50612fed612fe8613157565b613453565b90565b613000612ffb611711565b612fc0565b90565b9061300d90610544565b600052602052604060002090565b6130409161303661303b9261302e611711565b506006613003565b610550565b611730565b90565b6130549061304f613174565b613079565b565b90565b9061306e61306961307592610544565b613056565b82546129c5565b9055565b613082816131c9565b61308c600a6122a1565b61309782600a613059565b907f430359a6d97ced2b6f93c77a91e7ce9dfd43252eb91e916adba170485cd8a6a4916130ce6130c56102f3565b92839283612aa5565b0390a1565b6130dc90613043565b565b6130ef906130ea613174565b6130f1565b565b8061310d6131076131026000611869565b6103de565b916103de565b1461311d5761311b90613ec7565b565b61314861312a6000611869565b6131326102f3565b91829163b20f76e360e01b835260048301610bef565b0390fd5b613155906130de565b565b61315f612e97565b503390565b916131729291600192613f59565b565b61317c612e9c565b61319561318f61318a613157565b6103de565b916103de565b0361319c57565b6131c56131a7613157565b6131af6102f3565b9182916332b2baa360e01b835260048301610bef565b0390fd5b6131e46131de6131d96000611869565b6103de565b916103de565b146131eb57565b6131f36102f3565b63d92e233d60e01b81528061320a600482016104e0565b0390fd5b60409061323861323f949695939661322e60608401986000850190610be2565b60208301906105af565b01906105af565b565b9061324c910361040e565b90565b92919261325d81839061301b565b908161327361326d60001961040e565b9161040e565b03613280575b5050509050565b8161329361328d8761040e565b9161040e565b106132ba576132b193946132a8919392613241565b90600092613f59565b80388080613279565b506132e0849291926132ca6102f3565b938493630c95cf2760e11b85526004850161320e565b0390fd5b91826133016132fb6132f66000611869565b6103de565b916103de565b14613378578161332261331c6133176000611869565b6103de565b916103de565b14613349578261333461334794613453565b5061333e83613453565b50919091614088565b565b6133746133566000611869565b61335e6102f3565b918291639cfea58360e01b835260048301610bef565b0390fd5b6133a36133856000611869565b61338d6102f3565b9182916313053d9360e21b835260048301610bef565b0390fd5b90565b6133be6133b96133c3926133a7565b610519565b61040e565b90565b6133d060026133aa565b90565b6133dd6001611730565b6133f66133f06133eb6133c6565b61040e565b9161040e565b1461340f5761340d6134066133c6565b6001611c04565b565b6134176102f3565b6306fda65d60e31b81528061342e600482016104e0565b0390fd5b61343c6001611756565b90565b61345161344a613432565b6001611c04565b565b61345b611711565b908061347861347261346d6000611869565b6103de565b916103de565b1480156136e4575b6136d55761349861349360058390610550565b611730565b6134ac6134a7600f8490610550565b611730565b806134c06134ba6000611875565b9161040e565b146136a7575b6134d0600e611730565b6134e26134dc8361040e565b9161040e565b1015600014613697576134fe906134f9600e611730565b611891565b5b908161351461350e6000611875565b9161040e565b11613520575b50505090565b61357f92935061354a91613533916118b6565b613544670de0b6b3a76400006118ee565b90611920565b918261355f6135596000611875565b9161040e565b11613587575b61357a613572600e611730565b91600f610550565b611c04565b38808061351a565b6135af836135a961359a60058590610550565b916135a483611730565b611788565b90611c04565b6135d7836135d16135c2600b8590610550565b916135cc83611730565b611788565b90611c04565b6135f46135ed846135e86004611730565b611788565b6004611c04565b6135fe6000611869565b8184916136496136376136317fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b936136406102f3565b918291826105bc565b0390a38083904261367a7f1ac537f0ad67b64ac68a04587ff3a4cb6977de22eb2c37ee560897a92c6d07c792610544565b9261368f6136866102f3565b928392836127e2565b0390a2613565565b506136a26000611875565b6134ff565b506136c66136b5600e611730565b6136c1600f8590610550565b611c04565b6136d0600e611730565b6134c6565b50506136e16000611875565b90565b506136f96136f460058390610550565b611730565b61370c6137066000611875565b9161040e565b14613480565b806137266137206000611875565b9161040e565b1480156137b4575b6137b05761373b90612ec8565b8161376161375b61375661375160158690610953565b611730565b61040e565b9161040e565b1161378f5761378761377861378d93926015610953565b9161378283611730565b611891565b90611c04565b565b6137ae91506137a96137a16000611875565b916015610953565b611c04565b565b5050565b50816137c96137c36000611875565b9161040e565b1461372e565b6137d881612547565b8210156137f3576137ea600191612554565b91020190600090565b6120e6565b9190600861381891029161381260018060a01b0384611c24565b92611c24565b9181191691161790565b919061383861383361384093610544565b613056565b9083546137f8565b9055565b90565b634e487b7160e01b600052603160045260246000fd5b5490565b600052602060002090565b6138758161385d565b82101561389057613887600191613861565b91020190600090565b6120e6565b6138a7916138a1612e97565b91613822565b565b6138b28161385d565b80156138d35760019003906138d06138ca838361386c565b90613895565b55565b613847565b6138ec6138e7600c83906108b1565b61294d565b6138f4575b50565b61397f9061390c613907600d8390610550565b611730565b6139296139196010612547565b6139236001611756565b90611891565b908061393d6139378461040e565b9161040e565b03613985575b50506139576139526010613844565b6138a9565b61396d6000613968600d8490610550565b611c70565b61397a600091600c6108b1565b61168c565b386138f1565b6139be61399f6139996139c39460106137cf565b90610bc4565b916139b6836139b0601084906137cf565b90613822565b91600d610550565b611c04565b3880613943565b6139d390610538565b90565b63ffffffff1690565b63ffffffff60e01b1690565b6139ff6139fa613a04926139d6565b61295f565b6139df565b90565b916020613a29929493613a2260408201966000830190610be2565b01906105af565b565b90613a72613a7793613a6360049493613a4a63a9059cbb9193916139eb565b92613a536102f3565b9687946020860190815201613a07565b60208201810382520383611581565b614262565b565b60081c90565b613a8b613a9091613a79565b6113cc565b90565b613a9d9054613a7f565b90565b600080fd5b67ffffffffffffffff8111613abd5760208091020190565b61156b565b600080fd5b90505190613ad4826103ea565b565b90929192613aeb613ae682613aa5565b612062565b9381855260208086019202830192818411613b2857915b838310613b0f5750505050565b60208091613b1d8486613ac7565b815201920191613b02565b613ac2565b9080601f83011215613b4b57816020613b4893519101613ad6565b90565b613aa0565b90602082820312613b8157600082015167ffffffffffffffff8111613b7c57613b799201613b2d565b90565b6103ce565b6102fe565b90613b9082610cdf565b811015613ba1576020809102010190565b6120e6565b613bb090516103de565b90565b613bbc9061051c565b90565b613bc890613bb3565b90565b613bd490610538565b90565b6000910312613be257565b6102fe565b613c146000613bfe613bf96007613a93565b61140d565b63b4e8a6c490613c0c6102f3565b93849261295f565b82528180613c24600482016104e0565b03915afa908115613d3c57600091613d19575b50613c4181610cdf565b91613c4a611711565b5b80613c5e613c588661040e565b9161040e565b1015613d1357613c87613c82613c7d613c78868590613b86565b613ba6565b613bbf565b613bcb565b9063f8ba4cff91803b15613d0e57613cac92600091613ca46102f3565b94859261295f565b8252818381613cbd600482016104e0565b03925af1918215613d0957613cd792613cdc575b506120d7565b613c4b565b613cfc9060003d8111613d02575b613cf48183611581565b810190613bd7565b38613cd1565b503d613cea565b6129b4565b61295a565b50915050565b613d3691503d806000833e613d2e8183611581565b810190613b50565b38613c37565b6129b4565b613d54613d4e6000611875565b9161040e565b14613d5b57565b613d636102f3565b631f2a200560e01b815280613d7a600482016104e0565b0390fd5b9081549168010000000000000000831015613dae5782613da6916001613dac9501815561386c565b90613822565b565b61156b565b613dd0613dca613dc5600c84906108b1565b61294d565b15610463565b613dd8575b50565b613e3e90613dfa613de96010612547565b613df5600d8490610550565b611c04565b613e0e613e076010613844565b8290613d7e565b613e246001613e1f600c84906108b1565b61168c565b613e39613e31600e611730565b91600f610550565b611c04565b38613dd5565b604090613e6e613e759496959396613e6460608401986000850190610be2565b6020830190610be2565b01906105af565b565b600492613eb1613ec59593613ec09394613e986323b872dd929491926139eb565b93613ea16102f3565b9788956020870190815201613e44565b60208201810382520383611581565b614262565b565b613ed160006122a1565b613edc826000613059565b90613f10613f0a7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e093610544565b91610544565b91613f196102f3565b80613f23816104e0565b0390a3565b90613f51613f42613f3b613f5794612ec8565b6015610953565b91613f4c83611730565b611788565b90611c04565b565b909281613f77613f71613f6c6000611869565b6103de565b916103de565b1461404b5783613f98613f92613f8d6000611869565b6103de565b916103de565b1461401c57613fbc83613fb7613fb060068690613003565b8790610550565b611c04565b613fc6575b505050565b919091614011613fff613ff97f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92593610544565b93610544565b936140086102f3565b918291826105bc565b0390a3388080613fc1565b6140476140296000611869565b6140316102f3565b91829163270af7ed60e11b835260048301610bef565b0390fd5b6140766140586000611869565b6140606102f3565b9182916322f051b160e21b835260048301610bef565b0390fd5b90614085910161040e565b90565b919091806140a76140a161409c6000611869565b6103de565b916103de565b14600014614195576140cc6140c5836140c06004611730565b611788565b6004611c04565b5b826140e96140e36140de6000611869565b6103de565b916103de565b1460001461415f5761410e614107836141026004611730565b613241565b6004611c04565b5b91909161415a6141486141427fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93610544565b93610544565b936141516102f3565b918291826105bc565b0390a3565b6141878261418161417260058790610550565b9161417c83611730565b61407a565b90611c04565b61419083613db3565b61410f565b6141a96141a460058390610550565b611730565b806141bc6141b68561040e565b9161040e565b1061423f576141e06141cf828590613241565b6141db60058590610550565b611c04565b6141f26141ec8461040e565b9161040e565b146141fd575b6140cd565b61421b61420a6000611875565b614216600b8490610550565b611c04565b614224816138d8565b61423a6000614235600f8490610550565b611c70565b6141f8565b6142476102f3565b631e9acf1760e31b81528061425e600482016104e0565b0390fd5b906000602091614270611711565b50614279611711565b50828151910182855af115614317573d600051906142a061429a6000611875565b9161040e565b146000146142fd57506142b2816139ca565b3b6142c66142c06000611875565b9161040e565b145b6142cf5750565b6142db6142f9916139ca565b6142e36102f3565b918291635274afe760e01b835260048301610bef565b0390fd5b61431061430a6001611756565b9161040e565b14156142c8565b6040513d6000823e3d90fdfea264697066735822122084b5a5e8ba9dee653411d0330aea5c6edd8fa180f07c4cd00cd21500e9ea71bb64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c00000000000000000000000012684d18bdba8e31936f40abce1175366874114f000000000000000000000000000000000000000000000000000000000000000b5374616b6564204455535800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067374445553580000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name_ (string): Staked DUSX
Arg [1] : symbol_ (string): stDUSX
Arg [2] : baseContracts_ (address): 0x5Ce899AEd04c656776148fc3b1Adbe59e5f13D5c
Arg [3] : treasury_ (address): 0x12684d18BDBA8e31936f40aBcE1175366874114f
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c
Arg [3] : 00000000000000000000000012684d18bdba8e31936f40abce1175366874114f
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [5] : 5374616b65642044555358000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [7] : 7374445553580000000000000000000000000000000000000000000000000000
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.