ETH Price: $2,946.99 (+0.20%)
 

Overview

Max Total Supply

74,750,182.290523 cgUSD

Holders

2,001,678 (0.00%)

Market

Price

$0.9988 @ 0.000339 ETH (+0.01%)

Onchain Market Cap

-

Circulating Supply Market Cap

$74,661,708.00

Other Info

Token Contract (WITH 6 Decimals)

Filtered by Token Holder
bbb11.base.eth
Balance
1.337129 cgUSD

Value
$1.34 ( ~0.000454700535016369 ETH) [0.0000%]
0x96437141fd19ba767f037e8dbbacd2bad7a08bab
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Cygnus Finance is a RWA stablecoin protocol built on pure, short-term U.S. debt assets. It is also the first native interest-bearing stablecoin protocol and the first native RWA protocol on Base.

Contract Source Code Verified (Exact Match)

Contract Name:
CgUSD

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 2000 runs

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

pragma solidity ^0.8.20;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IBurner } from "./interfaces/IBurner.sol";
import { ILocator } from "./interfaces/ILocator.sol";
import { IOracleReportSanityChecker } from "./interfaces/IOracleReportSanityChecker.sol";
import { IWithdrawVault } from "./interfaces/IWithdrawVault.sol";
import { IWithdrawQueueERC721 } from "./interfaces/IWithdrawQueueERC721.sol";
import { ICgUSD } from "./interfaces/ICgUSD.sol";
import { IPausable } from "./interfaces/IPausable.sol";
import { UnstructuredStorage } from "./lib/UnstructuredStorage.sol";
import { StToken } from "./StToken.sol";

contract CgUSD is StToken, Ownable, Initializable, ICgUSD, IPausable {
    using SafeERC20 for IERC20;
    using UnstructuredStorage for bytes32;

    address public asset;

    bytes32 internal constant LOCATOR_POSITION =
        0x1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e42625; // keccak256("cygnus.CgUSD.locator")

    bytes32 internal constant BUFFERED_ASSET_POSITION =
        0x0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a6; // keccak256("cygnus.CgUSD.bufferedAsset");

    bytes32 internal constant INVESTED_ASSET_POSITION =
        0x2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b; // keccak256("cygnus.CgUSD.investedAsset");

    struct OracleReportedData {
        uint256 reportTimestamp;
        uint256 timeElapsed;
        uint256 newInvestedAssets;
        uint256 withdrawalVaultBalance;
        uint256 sharesRequestedToBurn;
        uint256[] withdrawalFinalizationBatches;
        uint256 simulatedShareRate;
    }

    struct OracleReportContracts {
        address accountingOracle;
        address oracleReportSanityChecker;
        address burner;
        address withdrawQueue;
        address withdrawVault;
    }

    struct OracleReportContext {
        uint256 preTotalPooledAssets;
        uint256 preTotalShares;
        uint256 assetsToLockOnWithdrawalQueue;
        uint256 sharesToBurnFromWithdrawalQueue;
        uint256 simulatedSharesToBurn;
        uint256 sharesToBurn;
    }

    event AssetsDistributed(
        uint256 indexed reportTimestamp,
        uint256 withdrawalsWithdrawn,
        uint256 postBufferedAssets,
        uint256 postInvestedAssets
    );

    event TokenRebased(
        uint256 indexed reportTimestamp,
        uint256 timeElapsed,
        uint256 preTotalShares,
        uint256 preTotalAssets,
        uint256 postTotalShares,
        uint256 postTotalAssets
    );

    event LocatorSet(address locator);

    event WithdrawalsReceived(uint256 amount);

    event Submitted(address indexed sender, uint256 amount, address referral);

    event Invested(uint256 amount, uint256 postBufferedAssets, uint256 postInvestedAssets);

    constructor(
        address _asset,
        address _owner
    ) Ownable(_owner) {
        asset = _asset;
    }

    function initialize(address _locator) external initializer {
        _bootstrapInitialHolder();

        LOCATOR_POSITION.setStorageAddress(_locator);
        _approve(
            ILocator(_locator).withdrawQueue(),
            ILocator(_locator).burner(),
            INFINITE_ALLOWANCE
        );

        emit LocatorSet(_locator);
    }

    function decimals() external view override returns (uint8) {
        return IERC20Metadata(asset).decimals();
    }

    function resume() external onlyOwner {
        _unpause();
    }

    function pause() external onlyOwner {
        _pause();
    }

    function _getTotalPooledAssets() internal view override returns (uint256) {
        return _getBufferedAssets() + _getInvestedAssets();
    }

    function getTotalAssets() external view returns (uint256, uint256) {
        return (_getBufferedAssets(), _getInvestedAssets());
    }

    function canDeposit() public view returns (bool) {
        return !_withdrawalQueue().isBunkerModeActive() && !paused();
    }

    function mint(address _referral, uint256 _assetsAmount)
        external
        returns (uint256 sharesAmount)
    {
        require((sharesAmount = previewDeposit(_assetsAmount)) != 0, "ZERO_SHARES");

        // TODO: check if oracle price deviated

        IERC20(asset).safeTransferFrom(msg.sender, address(this), _assetsAmount);

        _mintShares(msg.sender, sharesAmount);

        _setBufferedAssets(_getBufferedAssets() + _assetsAmount);
        emit Submitted(msg.sender, _assetsAmount, _referral);

        _emitTransferAfterMintingShares(msg.sender, sharesAmount);
    }

    function invest(address _to, uint256 _assetsAmount) external onlyOwner {
        require(canDeposit(), "CAN_NOT_INVEST");

        IERC20(asset).safeTransfer(_to, _assetsAmount);

        uint256 postBufferedAssets = _getBufferedAssets() - _assetsAmount;
        uint256 postInvestedAssets = _getInvestedAssets() + _assetsAmount;
        _setBufferedAssets(postBufferedAssets);
        _setInvestedAssets(postInvestedAssets);
        emit Invested(_assetsAmount, postBufferedAssets, postInvestedAssets);
    }

    function handleOracleReport(
        uint256 _reportTimestamp,
        uint256 _timeElapsed,
        uint256 _newInvestedAssets,
        uint256 _withdrawalVaultBalance,
        uint256 _sharesRequestedToBurn,
        uint256[] calldata _withdrawalFinalizationBatches,
        uint256 _simulatedShareRate
    ) external whenNotPaused returns (uint256[3] memory postRebaseAmounts) {
        return _handleOracleReport(
            OracleReportedData(
                _reportTimestamp,
                _timeElapsed,
                _newInvestedAssets,
                _withdrawalVaultBalance,
                _sharesRequestedToBurn,
                _withdrawalFinalizationBatches,
                _simulatedShareRate
            )
        );
    }

    function _handleOracleReport(OracleReportedData memory _reportedData) internal returns (uint256[3] memory) {
        OracleReportContracts memory contracts = _loadOracleReportContracts();

        require(msg.sender == contracts.accountingOracle, "APP_AUTH_FAILED");
        require(_reportedData.reportTimestamp <= block.timestamp, "INVALID_REPORT_TIMESTAMP");

        OracleReportContext memory reportContext;

        // Step 1.
        // Take a snapshot of the current (pre-) state
        reportContext.preTotalPooledAssets = _getTotalPooledAssets();
        reportContext.preTotalShares = _getTotalShares();

        // Step 2.
        // Pass the report data to sanity checker (reverts if malformed)
        _checkAccountingOracleReport(contracts, _reportedData);

        // Step 3.
        // Pre-calculate the ether to lock for withdrawal queue and shares to be burnt
        // due to withdrawal requests to finalize
        if (_reportedData.withdrawalFinalizationBatches.length != 0) {
            (
                reportContext.assetsToLockOnWithdrawalQueue,
                reportContext.sharesToBurnFromWithdrawalQueue
            ) = _calculateWithdrawals(contracts, _reportedData);

            if (reportContext.sharesToBurnFromWithdrawalQueue > 0) {
                IBurner(contracts.burner).requestBurnShares(
                    contracts.withdrawQueue,
                    reportContext.sharesToBurnFromWithdrawalQueue
                );
            }
        }

        // Step 4.
        // Pass the accounting values to sanity checker to smoothen positive token rebase

        uint256 withdrawals;
        (
            withdrawals, reportContext.simulatedSharesToBurn, reportContext.sharesToBurn
        ) = IOracleReportSanityChecker(contracts.oracleReportSanityChecker).smoothenTokenRebase(
            reportContext.preTotalPooledAssets,
            reportContext.preTotalShares,
            _reportedData.withdrawalVaultBalance,
            _reportedData.sharesRequestedToBurn,
            reportContext.assetsToLockOnWithdrawalQueue,
            reportContext.sharesToBurnFromWithdrawalQueue
        );

        // Step 5.
        // Invoke finalization of the withdrawal requests (send ether to withdrawal queue, assign shares to be burnt)
        _collectRewardsAndProcessWithdrawals(
            contracts,
            withdrawals,
            _reportedData.withdrawalFinalizationBatches,
            _reportedData.simulatedShareRate,
            reportContext.assetsToLockOnWithdrawalQueue
        );

        // Step 6.
        // Update invested assets
        _setInvestedAssets(_reportedData.newInvestedAssets);

        emit AssetsDistributed(
            _reportedData.reportTimestamp,
            withdrawals,
            _getBufferedAssets(),
            _getInvestedAssets()
        );

        // Step 7.
        // Burn the previously requested shares
        if (reportContext.sharesToBurn > 0) {
            IBurner(contracts.burner).commitSharesToBurn(reportContext.sharesToBurn);
            _burnShares(contracts.burner, reportContext.sharesToBurn);
        }

        // Step 8.
        // Complete token rebase (emit an event)
        (
            uint256 postTotalShares,
            uint256 postTotalPooledAssets
        ) = _completeTokenRebase(
            _reportedData,
            reportContext
        );

        // Step 9. Sanity check for the provided simulated share rate
        if (_reportedData.withdrawalFinalizationBatches.length != 0) {
            IOracleReportSanityChecker(contracts.oracleReportSanityChecker).checkSimulatedShareRate(
                postTotalPooledAssets,
                postTotalShares,
                reportContext.assetsToLockOnWithdrawalQueue,
                reportContext.sharesToBurn - reportContext.simulatedSharesToBurn,
                _reportedData.simulatedShareRate
            );
        }

        return [postTotalPooledAssets, postTotalShares, withdrawals];
    }

    function _collectRewardsAndProcessWithdrawals(
        OracleReportContracts memory _contracts,
        uint256 _withdrawalsToWithdraw,
        uint256[] memory _withdrawalFinalizationBatches,
        uint256 _simulatedShareRate,
        uint256 _assetsToLockOnWithdrawalQueue
    ) internal {
        // withdraw withdrawals and put them to the buffer
        if (_withdrawalsToWithdraw > 0) {
            IWithdrawVault(_contracts.withdrawVault).withdrawWithdrawals(_withdrawalsToWithdraw);
        }

        // finalize withdrawals (send ether, assign shares for burning)
        if (_assetsToLockOnWithdrawalQueue > 0) { // TODO
            IWithdrawQueueERC721 withdrawalQueue = IWithdrawQueueERC721(_contracts.withdrawQueue);
            IERC20(asset).safeTransfer(_contracts.withdrawQueue, _assetsToLockOnWithdrawalQueue);
            withdrawalQueue.finalize(
                _withdrawalFinalizationBatches[_withdrawalFinalizationBatches.length - 1],
                _simulatedShareRate,
                _assetsToLockOnWithdrawalQueue
            );
        }

        uint256 postBufferedAssets = _getBufferedAssets() + _withdrawalsToWithdraw - _assetsToLockOnWithdrawalQueue;

        _setBufferedAssets(postBufferedAssets);
    }

    function _calculateWithdrawals(
        OracleReportContracts memory _contracts,
        OracleReportedData memory _reportedData
    ) internal view returns (
        uint256 assetsToLock, uint256 sharesToBurn
    ) {
        IWithdrawQueueERC721 withdrawalQueue = IWithdrawQueueERC721(_contracts.withdrawQueue);

        //if (!withdrawalQueue.isPaused()) { TODO
        {
            IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkWithdrawalQueueOracleReport(
                _reportedData.withdrawalFinalizationBatches[_reportedData.withdrawalFinalizationBatches.length - 1],
                _reportedData.reportTimestamp
            );

            (assetsToLock, sharesToBurn) = withdrawalQueue.prefinalize(
                _reportedData.withdrawalFinalizationBatches,
                _reportedData.simulatedShareRate
            );
        }
    }

    function _checkAccountingOracleReport(
        OracleReportContracts memory _contracts,
        OracleReportedData memory _reportedData
    ) internal view {
        IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkAccountingOracleReport(
            _reportedData.timeElapsed,
            _reportedData.withdrawalVaultBalance,
            _reportedData.sharesRequestedToBurn
        );
    }

    function _completeTokenRebase(
        OracleReportedData memory _reportedData,
        OracleReportContext memory _reportContext
    ) internal returns (uint256 postTotalShares, uint256 postTotalPooledAssets) {
        postTotalShares = _getTotalShares();
        postTotalPooledAssets = _getTotalPooledAssets();

        emit TokenRebased(
            _reportedData.reportTimestamp,
            _reportedData.timeElapsed,
            _reportContext.preTotalShares,
            _reportContext.preTotalPooledAssets,
            postTotalShares,
            postTotalPooledAssets
        );
    }

    function _loadOracleReportContracts() internal view returns (OracleReportContracts memory ret) {
        (
            ret.accountingOracle,
            ret.oracleReportSanityChecker,
            ret.burner,
            ret.withdrawQueue,
            ret.withdrawVault
        ) = getLocator().oracleReportComponents();
    }

    function getLocator() public view returns (ILocator) {
        return ILocator(LOCATOR_POSITION.getStorageAddress());
    }

    function _withdrawalQueue() internal view returns (IWithdrawQueueERC721) {
        return IWithdrawQueueERC721(getLocator().withdrawQueue());
    }

    function _getBufferedAssets() internal view returns (uint256) {
        return BUFFERED_ASSET_POSITION.getStorageUint256();
    }

    function _setBufferedAssets(uint256 _newBufferedAssets) internal {
        BUFFERED_ASSET_POSITION.setStorageUint256(_newBufferedAssets);
    }

    function _getInvestedAssets() internal view returns (uint256) {
        return INVESTED_ASSET_POSITION.getStorageUint256();
    }

    function _setInvestedAssets(uint256 _newInvestedAssets) internal {
        INVESTED_ASSET_POSITION.setStorageUint256(_newInvestedAssets);
    }

    function _bootstrapInitialHolder() internal {
        uint256 balance = IERC20(asset).balanceOf(address(this));
        assert(balance != 0);

        if (_getTotalShares() == 0) {
            _setBufferedAssets(balance);
            emit Submitted(INITIAL_TOKEN_HOLDER, balance, address(0));
            _mintInitialShares(balance);
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

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

/**
 * @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.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

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

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reininitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        assembly {
            $.slot := INITIALIZABLE_STORAGE
        }
    }
}

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

pragma solidity ^0.8.20;

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

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

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

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

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

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
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.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 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 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 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.
     */
    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.
     */
    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.
     */
    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 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).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            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 silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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, since 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).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    bool private _paused;

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IBurner {
    function commitSharesToBurn(uint256 _stETHSharesToBurn) external;

    function requestBurnShares(address _from, uint256 _sharesAmount) external;

    function getSharesRequestedToBurn() external view returns (uint256 coverShares, uint256 nonCoverShares);

    function getCoverSharesBurnt() external view returns (uint256);

    function getNonCoverSharesBurnt() external view returns (uint256);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface ICgUSD {
    function asset() external view returns (address);

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

    function mint(address _referral, uint256 _assetsAmount)
        external
        returns (uint256);

    function invest(address _to, uint256 _assetsAmount) external;

    function handleOracleReport(
        uint256 _reportTimestamp,
        uint256 _timeElapsed,
        uint256 _newInvestedAssets,
        uint256 _withdrawalVaultBalance,
        uint256 _sharesRequestedToBurn,
        uint256[] calldata _withdrawalFinalizationBatches,
        uint256 _simulatedShareRate
    ) external returns (uint256[3] memory);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface ILocator {
    function accountingOracle() external view returns (address);
    function burner() external view returns (address);
    function priceOracle() external view returns (address);
    function withdrawQueue() external view returns (address);
    function withdrawVault() external view returns (address);
    function underlyingToken() external view returns (address);
    function stToken() external view returns (address);
    function treasury() external view returns (address);
    function oracleReportSanityChecker() external view returns (address);

    function coreComponents() external view returns (
        address oracleReportSanityChecker,
        address treasury,
        address withdrawalQueue,
        address withdrawalVault
    );

    function oracleReportComponents() external view returns (
        address accountingOracle,
        address oracleReportSanityChecker,
        address burner,
        address withdrawalQueue,
        address withdrawalVault
    );
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IOracleReportSanityChecker {
    function checkAccountingOracleReport(
        uint256 _timeElapsed,
        uint256 _withdrawalVaultBalance,
        uint256 _sharesRequestedToBurn
    ) external view;

    function smoothenTokenRebase(
        uint256 _preTotalPooledAssets,
        uint256 _preTotalShares,
        uint256 _withdrawalVaultBalance,
        uint256 _sharesRequestedToBurn,
        uint256 _assetsToLockForWithdrawals,
        uint256 _newSharesToBurnForWithdrawals
    ) external view returns (
        uint256 withdrawals,
        uint256 simulatedSharesToBurn,
        uint256 sharesToBurn
    );

    function checkWithdrawalQueueOracleReport(
        uint256 _lastFinalizableRequestId,
        uint256 _reportTimestamp
    ) external view;

    function checkSimulatedShareRate(
        uint256 _postTotalPooledAssets,
        uint256 _postTotalShares,
        uint256 _assetsLockedOnWithdrawalQueue,
        uint256 _sharesBurntDueToWithdrawals,
        uint256 _simulatedShareRate
    ) external view;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IPausable {
    function pause() external;

    function resume() external;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

interface IWithdrawQueue is IWithdrawQueueBase {
    struct PermitInput {
        uint256 value;
        uint256 deadline;
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    function requestWithdrawals(
        uint256[] calldata _amounts,
        address _owner
    ) external returns (uint256[] memory);

    function requestWithdrawalsWstToken(
        uint256[] calldata _amounts,
        address _owner
    ) external returns (uint256[] memory);

    function requestWithdrawalsWithPermit(
        uint256[] calldata _amounts,
        address _owner,
        PermitInput calldata _permit
    ) external returns (uint256[] memory);

    function requestWithdrawalsWstTokenWithPermit(
        uint256[] calldata _amounts,
        address _owner,
        PermitInput calldata _permit
    ) external returns (uint256[] memory);

    function getWithdrawalRequests(address _owner) external view returns (uint256[] memory);

    function getWithdrawalStatus(uint256[] calldata _requestIds)
        external
        view
        returns (WithdrawalRequestStatus[] memory);

    function getClaimableAssets(uint256[] calldata _requestIds, uint256[] calldata _hints)
        external
        view
        returns (uint256[] memory);

    function claimWithdrawalsTo(
        uint256[] calldata _requestIds,
        uint256[] calldata _hints,
        address _recipient
    ) external;

    function claimWithdrawals(uint256[] calldata _requestIds, uint256[] calldata _hints) external;

    function claimWithdrawal(uint256 _requestId) external;

    function findCheckpointHints(uint256[] calldata _requestIds, uint256 _firstIndex, uint256 _lastIndex)
        external
        view
        returns (uint256[] memory);

    function onOracleReport(
        bool _isBunkerModeNow,
        uint256 _bunkerStartTimestamp,
        uint256 _currentReportTimestamp
    ) external;

    function isBunkerModeActive() external view returns (bool);

    function bunkerModeSinceTimestamp() external view returns (uint256);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IWithdrawQueueBase {
    struct WithdrawalRequestStatus {
        uint256 amountOfAssets;
        uint256 amountOfShares;
        address owner;
        uint256 timestamp;
        bool isFinalized;
        bool isClaimed;
    }

    struct BatchesCalculationState {
        uint256 remainingAssetsBudget;
        bool finished;
        uint256[36] batches;
        uint256 batchesLength;
    }

    function getLastRequestId() external view returns (uint256);

    function getLastFinalizedRequestId() external view returns (uint256);

    function getLockedAssetsAmount() external view returns (uint256);

    function getLastCheckpointIndex() external view returns (uint256);

    function unfinalizedRequestNumber() external view returns (uint256);

    function unfinalizedAssets() external view returns (uint256);

    function calculateFinalizationBatches(
        uint256 _maxShareRate,
        uint256 _maxTimestamp,
        uint256 _maxRequestsPerCall,
        BatchesCalculationState memory _state
    ) external view returns (BatchesCalculationState memory);

    function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate)
        external
        view
        returns (uint256 assetsToLock, uint256 sharesToBurn);
}

File 18 of 22 : IWithdrawQueueERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

interface IWithdrawQueueERC721 is IWithdrawQueue {
    function finalize(
        uint256 _lastRequestIdToBeFinalized,
        uint256 _maxShareRate,
        uint256 _amount
    ) external;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IWithdrawVault {
    function asset() external view returns (address);
    function withdrawWithdrawals(uint256 _amount) external;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

library UnstructuredStorage {
    function getStorageBool(bytes32 position) internal view returns (bool data) {
        assembly { data := sload(position) }
    }

    function getStorageAddress(bytes32 position) internal view returns (address data) {
        assembly { data := sload(position) }
    }

    function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) {
        assembly { data := sload(position) }
    }

    function getStorageUint256(bytes32 position) internal view returns (uint256 data) {
        assembly { data := sload(position) }
    }

    function setStorageBool(bytes32 position, bool data) internal {
        assembly { sstore(position, data) }
    }

    function setStorageAddress(bytes32 position, address data) internal {
        assembly { sstore(position, data) }
    }

    function setStorageBytes32(bytes32 position, bytes32 data) internal {
        assembly { sstore(position, data) }
    }

    function setStorageUint256(bytes32 position, uint256 data) internal {
        assembly { sstore(position, data) }
    }
}

File 21 of 22 : StToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol";
import { FixedPointMathLib } from "solmate/src/utils/FixedPointMathLib.sol";
import { UnstructuredStorage } from "./lib/UnstructuredStorage.sol";

abstract contract StToken is IERC20, Pausable {
    using FixedPointMathLib for uint256;
    using UnstructuredStorage for bytes32;

    address constant internal INITIAL_TOKEN_HOLDER = address(0xDEAD);
    uint256 constant internal INFINITE_ALLOWANCE = type(uint256).max;

    mapping (address => uint256) private shares;

    mapping (address => mapping (address => uint256)) private allowances;

    bytes32 internal constant TOTAL_SHARES_POSITION =
        0x83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be; // keccak256('cygnus.StToken.totalShares')

    event TransferShares(
        address indexed from,
        address indexed to,
        uint256 sharesValue
    );

    event SharesBurnt(
        address indexed account,
        uint256 preRebaseTokenAmount,
        uint256 postRebaseTokenAmount,
        uint256 sharesAmount
    );

    function name() external pure returns (string memory) {
        return "Cygnus Global USD";
    }

    function symbol() external pure returns (string memory) {
        return "cgUSD";
    }

    function decimals() external view virtual returns (uint8);

    function totalSupply() external view returns (uint256) {
        return _getTotalPooledAssets();
    }

    function getTotalPooledAssets() external view returns (uint256) {
        return _getTotalPooledAssets();
    }

    function balanceOf(address _account) external view returns (uint256) {
        return convertToAssets(_sharesOf(_account));
    }

    function transfer(address _recipient, uint256 _amount) external returns (bool) {
        _transfer(msg.sender, _recipient, _amount);
        return true;
    }

    function allowance(address _owner, address _spender) external view returns (uint256) {
        return allowances[_owner][_spender];
    }

    function approve(address _spender, uint256 _amount) external returns (bool) {
        _approve(msg.sender, _spender, _amount);
        return true;
    }

    function transferFrom(address _sender, address _recipient, uint256 _amount) external returns (bool) {
        _spendAllowance(_sender, msg.sender, _amount);
        _transfer(_sender, _recipient, _amount);
        return true;
    }

    function increaseAllowance(address _spender, uint256 _addedValue) external returns (bool) {
        _approve(msg.sender, _spender, allowances[msg.sender][_spender] + _addedValue);
        return true;
    }

    function decreaseAllowance(address _spender, uint256 _subtractedValue) external returns (bool) {
        uint256 currentAllowance = allowances[msg.sender][_spender];
        require(currentAllowance >= _subtractedValue, "ALLOWANCE_BELOW_ZERO");
        _approve(msg.sender, _spender, currentAllowance - _subtractedValue);
        return true;
    }

    function getTotalShares() external view returns (uint256) {
        return _getTotalShares();
    }

    function sharesOf(address _account) external view returns (uint256) {
        return _sharesOf(_account);
    }

    function transferShares(address _recipient, uint256 _sharesAmount) external returns (uint256) {
        _transferShares(msg.sender, _recipient, _sharesAmount);
        uint256 tokensAmount = convertToAssets(_sharesAmount);
        _emitTransferEvents(msg.sender, _recipient, tokensAmount, _sharesAmount);
        return tokensAmount;
    }

    function transferSharesFrom(
        address _sender, address _recipient, uint256 _sharesAmount
    ) external returns (uint256) {
        uint256 tokensAmount = convertToAssets(_sharesAmount);
        _spendAllowance(_sender, msg.sender, tokensAmount);
        _transferShares(_sender, _recipient, _sharesAmount);
        _emitTransferEvents(_sender, _recipient, tokensAmount, _sharesAmount);
        return tokensAmount;
    }

    function _getTotalPooledAssets() internal view virtual returns (uint256);

    function _transfer(address _sender, address _recipient, uint256 _amount) internal {
        uint256 _sharesToTransfer = convertToShares(_amount);
        _transferShares(_sender, _recipient, _sharesToTransfer);
        _emitTransferEvents(_sender, _recipient, _amount, _sharesToTransfer);
    }

    function _approve(address _owner, address _spender, uint256 _amount) internal {
        require(_owner != address(0), "APPROVE_FROM_ZERO_ADDR");
        require(_spender != address(0), "APPROVE_TO_ZERO_ADDR");

        allowances[_owner][_spender] = _amount;
        emit Approval(_owner, _spender, _amount);
    }

    function _spendAllowance(address _owner, address _spender, uint256 _amount) internal {
        uint256 currentAllowance = allowances[_owner][_spender];
        if (currentAllowance != INFINITE_ALLOWANCE) {
            require(currentAllowance >= _amount, "ALLOWANCE_EXCEEDED");
            _approve(_owner, _spender, currentAllowance - _amount);
        }
    }

    function _getTotalShares() internal view returns (uint256) {
        return TOTAL_SHARES_POSITION.getStorageUint256();
    }

    function _sharesOf(address _account) internal view returns (uint256) {
        return shares[_account];
    }

    function _transferShares(address _sender, address _recipient, uint256 _sharesAmount) internal {
        _requireNotPaused();
        require(_sender != address(0), "TRANSFER_FROM_ZERO_ADDR");
        require(_recipient != address(0), "TRANSFER_TO_ZERO_ADDR");
        require(_recipient != address(this), "TRANSFER_TO_STETH_CONTRACT");

        uint256 currentSenderShares = shares[_sender];
        require(_sharesAmount <= currentSenderShares, "BALANCE_EXCEEDED");

        shares[_sender] = currentSenderShares - _sharesAmount;
        shares[_recipient] = shares[_recipient] + _sharesAmount;
    }

    function _mintShares(address _recipient, uint256 _sharesAmount) internal returns (uint256 newTotalShares) {
        require(_recipient != address(0), "MINT_TO_ZERO_ADDR");

        newTotalShares = _getTotalShares() + _sharesAmount;
        TOTAL_SHARES_POSITION.setStorageUint256(newTotalShares);

        shares[_recipient] = shares[_recipient] + _sharesAmount;
    }

    function _burnShares(address _account, uint256 _sharesAmount) internal returns (uint256 newTotalShares) {
        require(_account != address(0), "BURN_FROM_ZERO_ADDR");

        uint256 accountShares = shares[_account];
        require(_sharesAmount <= accountShares, "BALANCE_EXCEEDED");

        uint256 preRebaseTokenAmount = convertToAssets(_sharesAmount);

        newTotalShares = _getTotalShares() - _sharesAmount;
        TOTAL_SHARES_POSITION.setStorageUint256(newTotalShares);

        shares[_account] = accountShares - _sharesAmount;

        uint256 postRebaseTokenAmount = convertToAssets(_sharesAmount);

        emit SharesBurnt(_account, preRebaseTokenAmount, postRebaseTokenAmount, _sharesAmount);
    }

    function convertToShares(uint256 _assetsAmount) public view virtual returns (uint256) {
        return _assetsAmount.mulDivDown(_getTotalShares(), _getTotalPooledAssets());
    }

    function convertToAssets(uint256 _sharesAmount) public view virtual returns (uint256) {
        return _sharesAmount.mulDivDown(_getTotalPooledAssets(), _getTotalShares());
    }

    function _emitTransferEvents(address _from, address _to, uint _tokenAmount, uint256 _sharesAmount) internal {
        emit Transfer(_from, _to, _tokenAmount);
        emit TransferShares(_from, _to, _sharesAmount);
    }

    function _emitTransferAfterMintingShares(address _to, uint256 _sharesAmount) internal {
        _emitTransferEvents(address(0), _to, convertToAssets(_sharesAmount), _sharesAmount);
    }

    function _mintInitialShares(uint256 _sharesAmount) internal {
        _mintShares(INITIAL_TOKEN_HOLDER, _sharesAmount);
        _emitTransferAfterMintingShares(INITIAL_TOKEN_HOLDER, _sharesAmount);
    }

    function previewDeposit(uint256 _assetsAmount) public view virtual returns (uint256) {
        return convertToShares(_assetsAmount);
    }

    function previewMint(uint256 _sharesAmount) public view virtual returns (uint256) {
        return _sharesAmount.mulDivUp(_getTotalPooledAssets(), _getTotalShares());
    }

    function previewWithdraw(uint256 _assetsAmount) public view virtual returns (uint256) {
        return _assetsAmount.mulDivUp(_getTotalShares(), _getTotalPooledAssets());
    }

    function previewRedeem(uint256 _sharesAmount) public view virtual returns (uint256) {
        return convertToAssets(_sharesAmount);
    }
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant MAX_UINT256 = 2**256 - 1;

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // Divide x * y by the denominator.
            z := div(mul(x, y), denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // If x * y modulo the denominator is strictly greater than 0,
            // 1 is added to round up the division of x * y by the denominator.
            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let y := x // We start y at x, which will help us make our initial estimate.

            z := 181 // The "correct" value is 1, but this saves a multiplication later.

            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.

            // We check y >= 2^(k + 8) but shift right by k bits
            // each branch to ensure that if x >= 256, then y >= 256.
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
                y := shr(128, y)
                z := shl(64, z)
            }
            if iszero(lt(y, 0x1000000000000000000)) {
                y := shr(64, y)
                z := shl(32, z)
            }
            if iszero(lt(y, 0x10000000000)) {
                y := shr(32, y)
                z := shl(16, z)
            }
            if iszero(lt(y, 0x1000000)) {
                y := shr(16, y)
                z := shl(8, z)
            }

            // Goal was to get z*z*y within a small factor of x. More iterations could
            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).
            // We ensured y >= 256 so that the relative difference between y and y+1 is small.
            // That's not possible if x < 256 but we can just verify those cases exhaustively.

            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.

            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.

            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.

            // There is no overflow risk here since y < 2^136 after the first branch above.
            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.

            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // If x+1 is a perfect square, the Babylonian method cycles between
            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.
            z := sub(z, lt(div(x, z), z))
        }
    }

    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Mod x by y. Note this will return
            // 0 instead of reverting if y is zero.
            z := mod(x, y)
        }
    }

    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Divide x by y. Note this will return
            // 0 instead of reverting if y is zero.
            r := div(x, y)
        }
    }

    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Add 1 to x * y if x % y > 0. Note this will
            // return 0 instead of reverting if y is zero.
            z := add(gt(mod(x, y), 0), div(x, y))
        }
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","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":"uint256","name":"reportTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawalsWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postBufferedAssets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postInvestedAssets","type":"uint256"}],"name":"AssetsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postBufferedAssets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postInvestedAssets","type":"uint256"}],"name":"Invested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"locator","type":"address"}],"name":"LocatorSet","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":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"reportTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timeElapsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"preTotalShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"preTotalAssets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postTotalShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postTotalAssets","type":"uint256"}],"name":"TokenRebased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalsReceived","type":"event"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getLocator","outputs":[{"internalType":"contract ILocator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalPooledAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"},{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_newInvestedAssets","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256[]","name":"_withdrawalFinalizationBatches","type":"uint256[]"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"internalType":"uint256[3]","name":"postRebaseAmounts","type":"uint256[3]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_locator","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"invest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referral","type":"address"},{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"sharesAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","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":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"transferSharesFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162002b1838038062002b18833981016040819052620000349162000110565b6000805460ff19169055806001600160a01b0381166200006e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200007981620000a1565b5050600480546001600160a01b0319166001600160a01b039290921691909117905562000148565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200010b57600080fd5b919050565b600080604083850312156200012457600080fd5b6200012f83620000f3565b91506200013f60208401620000f3565b90509250929050565b6129c080620001586000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c80638da5cb5b11610145578063c6e6f592116100bd578063e745ad191161008c578063ef8b30f711610071578063ef8b30f714610544578063f2fde38b14610557578063f5eb42dc1461056a57600080fd5b8063e745ad191461030d578063e78a58751461053c57600080fd5b8063c6e6f592146104e0578063d5002f2e146104f3578063d8343dcb146104fb578063dd62ed3e1461050357600080fd5b8063a9059cbb11610114578063b823fba2116100f9578063b823fba21461049a578063b9b8c246146104ba578063c4d66de8146104cd57600080fd5b8063a9059cbb14610474578063b3d7f6b91461048757600080fd5b80638da5cb5b146104045780638fcb4e5b1461041557806395d89b4114610428578063a457c2d71461046157600080fd5b806339509351116101d85780636d780459116101a757806370a082311161018c57806370a08231146103e1578063715018a6146103f45780638456cb59146103fc57600080fd5b80636d780459146103b15780636e07302b146103c457600080fd5b8063395093511461036d57806340c10f19146103805780634cdad506146103935780635c975abb146103a657600080fd5b80630a28a4771161022f57806323b872dd1161021457806323b872dd14610315578063313ce5671461032857806338d52e0f1461034257600080fd5b80630a28a477146102fa57806318160ddd1461030d57600080fd5b8063046f7da21461026157806306fdde031461026b57806307a2d13a146102b6578063095ea7b3146102d7575b600080fd5b61026961057d565b005b60408051808201909152601181527f4379676e757320476c6f62616c2055534400000000000000000000000000000060208201525b6040516102ad919061255a565b60405180910390f35b6102c96102c43660046125ab565b61058f565b6040519081526020016102ad565b6102ea6102e53660046125d9565b6105b2565b60405190151581526020016102ad565b6102c96103083660046125ab565b6105c8565b6102c96105e5565b6102ea610323366004612605565b6105f4565b610330610617565b60405160ff90911681526020016102ad565b600454610355906001600160a01b031681565b6040516001600160a01b0390911681526020016102ad565b6102ea61037b3660046125d9565b610690565b6102c961038e3660046125d9565b6106cc565b6102c96103a13660046125ab565b6107b9565b60005460ff166102ea565b6102c96103bf366004612605565b6107c4565b6103cc6107fc565b604080519283526020830191909152016102ad565b6102c96103ef366004612646565b610817565b610269610839565b61026961084b565b6003546001600160a01b0316610355565b6102c96104233660046125d9565b61085b565b60408051808201909152600581527f636755534400000000000000000000000000000000000000000000000000000060208201526102a0565b6102ea61046f3660046125d9565b610881565b6102ea6104823660046125d9565b610904565b6102c96104953660046125ab565b610911565b6104ad6104a8366004612663565b610926565b6040516102ad9190612712565b6102696104c83660046125d9565b6109b0565b6102696104db366004612646565b610aaa565b6102c96104ee3660046125ab565b610d31565b6102c9610d46565b610355610d50565b6102c9610511366004612743565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6102ea610d7a565b6102c96105523660046125ab565b610df8565b610269610565366004612646565b610e03565b6102c9610578366004612646565b610e5a565b610585610e78565b61058d610ebe565b565b60006105ac61059c610f10565b6105a4610f2c565b849190610f56565b92915050565b60006105bf338484610f74565b50600192915050565b60006105ac6105d5610f2c565b6105dd610f10565b849190611081565b60006105ef610f10565b905090565b60006106018433846110a7565b61060c84848461113b565b5060015b9392505050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561066c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef919061277c565b3360008181526002602090815260408083206001600160a01b038716845290915281205490916105bf9185906106c79086906127b5565b610f74565b60006106d782610df8565b90508060000361072e5760405162461bcd60e51b815260206004820152600b60248201527f5a45524f5f53484152455300000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600454610746906001600160a01b031633308561115f565b61075033826111db565b5061076c8261075d6112b6565b61076791906127b5565b6112e0565b604080518381526001600160a01b038516602082015233917f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a910160405180910390a26105ac3382611309565b60006105ac8261058f565b6000806107d08361058f565b90506107dd8533836110a7565b6107e8858585611322565b6107f4858583866114f3565b949350505050565b6000806108076112b6565b61080f611593565b915091509091565b6001600160a01b0381166000908152600160205260408120546105ac9061058f565b610841610e78565b61058d60006115bd565b610853610e78565b61058d611627565b6000610868338484611322565b60006108738361058f565b9050610610338583866114f3565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156108f55760405162461bcd60e51b815260206004820152601460248201527f414c4c4f57414e43455f42454c4f575f5a45524f0000000000000000000000006044820152606401610725565b61060c33856106c786856127c8565b60006105bf33848461113b565b60006105ac61091e610f10565b6105dd610f2c565b61092e612518565b610936611664565b6109a36040518060e001604052808b81526020018a81526020018981526020018881526020018781526020018686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506020018490526116a1565b9998505050505050505050565b6109b8610e78565b6109c0610d7a565b610a0c5760405162461bcd60e51b815260206004820152600e60248201527f43414e5f4e4f545f494e564553540000000000000000000000000000000000006044820152606401610725565b600454610a23906001600160a01b03168383611b3f565b600081610a2e6112b6565b610a3891906127c8565b9050600082610a45611593565b610a4f91906127b5565b9050610a5a826112e0565b610a6381611b75565b60408051848152602081018490529081018290527f15294ad9d42e2bbd446d4ff6ca28fef807d1631ad53c688303fe468410830f329060600160405180910390a150505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610af55750825b905060008267ffffffffffffffff166001148015610b125750303b155b905081158015610b20575080155b15610b57576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610ba257845468ff00000000000000001916680100000000000000001785555b610baa611b9e565b610bd37f1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e42625879055565b610ca2866001600160a01b03166351a2d6d16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3891906127db565b876001600160a01b03166327810b6e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9a91906127db565b600019610f74565b6040516001600160a01b03871681527f8cb16e06ecfafbed13687256a764058471060b490b62dc8b3e4ea2f395ec29599060200160405180910390a18315610d2957845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b60006105ac610d3e610f2c565b6105a4610f10565b60006105ef610f2c565b60006105ef7f1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e426255490565b6000610d84611c99565b6001600160a01b0316632b95b7816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de591906127f8565b1580156105ef57505060005460ff161590565b60006105ac82610d31565b610e0b610e78565b6001600160a01b038116610e4e576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610725565b610e57816115bd565b50565b6001600160a01b0381166000908152600160205260408120546105ac565b6003546001600160a01b0316331461058d576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610725565b610ec6611d04565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000610f1a611593565b610f226112b6565b6105ef91906127b5565b60006105ef7f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be5490565b6000826000190484118302158202610f6d57600080fd5b5091020490565b6001600160a01b038316610fca5760405162461bcd60e51b815260206004820152601660248201527f415050524f56455f46524f4d5f5a45524f5f41444452000000000000000000006044820152606401610725565b6001600160a01b0382166110205760405162461bcd60e51b815260206004820152601460248201527f415050524f56455f544f5f5a45524f5f414444520000000000000000000000006044820152606401610725565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600082600019048411830215820261109857600080fd5b50910281810615159190040190565b6001600160a01b03808416600090815260026020908152604080832093861683529290522054600019811461113557818110156111265760405162461bcd60e51b815260206004820152601260248201527f414c4c4f57414e43455f455843454544454400000000000000000000000000006044820152606401610725565b61113584846106c785856127c8565b50505050565b600061114682610d31565b9050611153848483611322565b611135848484846114f3565b6040516001600160a01b0384811660248301528381166044830152606482018390526111359186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d40565b60006001600160a01b0383166112335760405162461bcd60e51b815260206004820152601160248201527f4d494e545f544f5f5a45524f5f414444520000000000000000000000000000006044820152606401610725565b8161123c610f2c565b61124691906127b5565b90506112717f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be829055565b6001600160a01b0383166000908152600160205260409020546112959083906127b5565b6001600160a01b039093166000908152600160205260409020929092555090565b60006105ef7f0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a65490565b610e577f0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a6829055565b61131e6000836113188461058f565b846114f3565b5050565b61132a611664565b6001600160a01b0383166113805760405162461bcd60e51b815260206004820152601760248201527f5452414e534645525f46524f4d5f5a45524f5f414444520000000000000000006044820152606401610725565b6001600160a01b0382166113d65760405162461bcd60e51b815260206004820152601560248201527f5452414e534645525f544f5f5a45524f5f4144445200000000000000000000006044820152606401610725565b306001600160a01b0383160361142e5760405162461bcd60e51b815260206004820152601a60248201527f5452414e534645525f544f5f53544554485f434f4e54524143540000000000006044820152606401610725565b6001600160a01b038316600090815260016020526040902054808211156114975760405162461bcd60e51b815260206004820152601060248201527f42414c414e43455f4558434545444544000000000000000000000000000000006044820152606401610725565b6114a182826127c8565b6001600160a01b0380861660009081526001602052604080822093909355908516815220546114d19083906127b5565b6001600160a01b03909316600090815260016020526040902092909255505050565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161153891815260200190565b60405180910390a3826001600160a01b0316846001600160a01b03167f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb8360405161158591815260200190565b60405180910390a350505050565b60006105ef7f2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b5490565b600380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61162f611664565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610ef33390565b60005460ff161561058d576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116a9612518565b60006116b3611dbc565b80519091506001600160a01b0316331461170f5760405162461bcd60e51b815260206004820152600f60248201527f4150505f415554485f4641494c454400000000000000000000000000000000006044820152606401610725565b82514210156117605760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5245504f52545f54494d455354414d5000000000000000006044820152606401610725565b6117996040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6117a1610f10565b81526117ab610f2c565b60208201526117ba8285611e7e565b60a0840151511561186e576117cf8285611f0e565b6060830181905260408301919091521561186e576040808301516060808501519084015192517f461149280000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260248101939093521690634611492890604401600060405180830381600087803b15801561185557600080fd5b505af1158015611869573d6000803e3d6000fd5b505050505b60208083015182519183015160608088015160808901516040808801519388015190517f3cf7df960000000000000000000000000000000000000000000000000000000081526004810197909752602487019490945260448601919091526064850152608484015260a48301526000916001600160a01b0390911690633cf7df969060c401606060405180830381865afa158015611910573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611934919061281a565b846080018560a001828152508281525082935050505061196383828760a001518860c001518660400151612050565b6119708560400151611b75565b84517f224918cef3c8dd950405e7cd332c2d23ff756244eb4ae4f3e81f6bf8f14d78ad8261199c6112b6565b6119a4611593565b6040805193845260208401929092529082015260600160405180910390a260a082015115611a485782604001516001600160a01b031663636e6b668360a001516040518263ffffffff1660e01b8152600401611a0291815260200190565b600060405180830381600087803b158015611a1c57600080fd5b505af1158015611a30573d6000803e3d6000fd5b50505050611a4683604001518360a001516121b8565b505b600080611a55878561234b565b915091508660a0015151600014611b1b5784602001516001600160a01b03166363e56b9f8284876040015188608001518960a00151611a9491906127c8565b60c08d01516040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1681526004810195909552602485019390935260448401919091526064830152608482015260a40160006040518083038186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050505b60408051606081018252918252602082019290925290810191909152949350505050565b6040516001600160a01b03838116602483015260448201839052611b7091859182169063a9059cbb90606401611194565b505050565b610e577f2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b829055565b600480546040517f70a0823100000000000000000000000000000000000000000000000000000000815230928101929092526000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c299190612848565b905080600003611c3b57611c3b612861565b611c43610f2c565b600003610e5757611c53816112e0565b604080518281526000602082015261dead917f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a910160405180910390a2610e57816123c6565b6000611ca3610d50565b6001600160a01b03166351a2d6d16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ce0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef91906127db565b60005460ff1661058d576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611d556001600160a01b038416836123df565b90508051600014158015611d7a575080806020019051810190611d7891906127f8565b155b15611b70576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610725565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611def610d50565b6001600160a01b031663b2ad11046040518163ffffffff1660e01b815260040160a060405180830381865afa158015611e2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e509190612877565b6001600160a01b03908116608087015290811660608601529081166040850152908116602084015216815290565b60208083015190820151606083015160808401516040517f848b2d7c0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526001600160a01b039091169063848b2d7c9060640160006040518083038186803b158015611efa57600080fd5b505afa158015610d29573d6000803e3d6000fd5b60008060008460600151905084602001516001600160a01b0316636a84f2fd8560a0015160018760a0015151611f4491906127c8565b81518110611f5457611f546128ec565b602002602001015186600001516040518363ffffffff1660e01b8152600401611f87929190918252602082015260400190565b60006040518083038186803b158015611f9f57600080fd5b505afa158015611fb3573d6000803e3d6000fd5b5050505060a084015160c08501516040517fa52e9c9f0000000000000000000000000000000000000000000000000000000081526001600160a01b0384169263a52e9c9f9261200492600401612902565b6040805180830381865afa158015612020573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612044919061294a565b90969095509350505050565b83156120d05760808501516040517f3194528a000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b0390911690633194528a90602401600060405180830381600087803b1580156120b757600080fd5b505af11580156120cb573d6000803e3d6000fd5b505050505b801561218d5760608501516004546120f2906001600160a01b03168284611b3f565b806001600160a01b0316635b206ec5856001875161211091906127c8565b81518110612120576121206128ec565b602002602001015185856040518463ffffffff1660e01b8152600401612159939291909283526020830191909152604082015260600190565b600060405180830381600087803b15801561217357600080fd5b505af1158015612187573d6000803e3d6000fd5b50505050505b600081856121996112b6565b6121a391906127b5565b6121ad91906127c8565b9050610d29816112e0565b60006001600160a01b0383166122105760405162461bcd60e51b815260206004820152601360248201527f4255524e5f46524f4d5f5a45524f5f41444452000000000000000000000000006044820152606401610725565b6001600160a01b038316600090815260016020526040902054808311156122795760405162461bcd60e51b815260206004820152601060248201527f42414c414e43455f4558434545444544000000000000000000000000000000006044820152606401610725565b60006122848461058f565b90508361228f610f2c565b61229991906127c8565b92506122c47f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be849055565b6122ce84836127c8565b6001600160a01b0386166000908152600160205260408120919091556122f38561058f565b60408051848152602081018390529081018790529091506001600160a01b038716907f8b2a1e1ad5e0578c3dd82494156e985dade827a87c573b5c1c7716a32162ad649060600160405180910390a250505092915050565b600080612356610f2c565b9150612360610f10565b84516020808701518682015187516040805193845293830191909152818301526060810186905260808101849052905192935090917f56a90fb9987084b721919e7e877c8c06757ce01d02952ca54cb1155774abfaea9181900360a00190a29250929050565b6123d261dead826111db565b50610e5761dead82611309565b60606106108383600084600080856001600160a01b03168486604051612405919061296e565b60006040518083038185875af1925050503d8060008114612442576040519150601f19603f3d011682016040523d82523d6000602084013e612447565b606091505b5091509150612457868383612461565b9695505050505050565b60608261247657612471826124d6565b610610565b815115801561248d57506001600160a01b0384163b155b156124cf576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610725565b5080610610565b8051156124e65780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180606001604052806003906020820280368337509192915050565b60005b83811015612551578181015183820152602001612539565b50506000910152565b6020815260008251806020840152612579816040850160208701612536565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156125bd57600080fd5b5035919050565b6001600160a01b0381168114610e5757600080fd5b600080604083850312156125ec57600080fd5b82356125f7816125c4565b946020939093013593505050565b60008060006060848603121561261a57600080fd5b8335612625816125c4565b92506020840135612635816125c4565b929592945050506040919091013590565b60006020828403121561265857600080fd5b8135610610816125c4565b60008060008060008060008060e0898b03121561267f57600080fd5b883597506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff808211156126ba57600080fd5b818b0191508b601f8301126126ce57600080fd5b8135818111156126dd57600080fd5b8c60208260051b85010111156126f257600080fd5b60208301955080945050505060c089013590509295985092959890939650565b60608101818360005b600381101561273a57815183526020928301929091019060010161271b565b50505092915050565b6000806040838503121561275657600080fd5b8235612761816125c4565b91506020830135612771816125c4565b809150509250929050565b60006020828403121561278e57600080fd5b815160ff8116811461061057600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156105ac576105ac61279f565b818103818111156105ac576105ac61279f565b6000602082840312156127ed57600080fd5b8151610610816125c4565b60006020828403121561280a57600080fd5b8151801515811461061057600080fd5b60008060006060848603121561282f57600080fd5b8351925060208401519150604084015190509250925092565b60006020828403121561285a57600080fd5b5051919050565b634e487b7160e01b600052600160045260246000fd5b600080600080600060a0868803121561288f57600080fd5b855161289a816125c4565b60208701519095506128ab816125c4565b60408701519094506128bc816125c4565b60608701519093506128cd816125c4565b60808701519092506128de816125c4565b809150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b8281101561293b5781518452928401929084019060010161291f565b50505092019290925292915050565b6000806040838503121561295d57600080fd5b505080516020909101519092909150565b60008251612980818460208701612536565b919091019291505056fea2646970667358221220850d22b1ba11f035bf015364ee858924d9af209cfdf73e7b69f4938235c7c48264736f6c63430008140033000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000fecab866b450b97db38500898e9272c1d18918b7

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061025c5760003560e01c80638da5cb5b11610145578063c6e6f592116100bd578063e745ad191161008c578063ef8b30f711610071578063ef8b30f714610544578063f2fde38b14610557578063f5eb42dc1461056a57600080fd5b8063e745ad191461030d578063e78a58751461053c57600080fd5b8063c6e6f592146104e0578063d5002f2e146104f3578063d8343dcb146104fb578063dd62ed3e1461050357600080fd5b8063a9059cbb11610114578063b823fba2116100f9578063b823fba21461049a578063b9b8c246146104ba578063c4d66de8146104cd57600080fd5b8063a9059cbb14610474578063b3d7f6b91461048757600080fd5b80638da5cb5b146104045780638fcb4e5b1461041557806395d89b4114610428578063a457c2d71461046157600080fd5b806339509351116101d85780636d780459116101a757806370a082311161018c57806370a08231146103e1578063715018a6146103f45780638456cb59146103fc57600080fd5b80636d780459146103b15780636e07302b146103c457600080fd5b8063395093511461036d57806340c10f19146103805780634cdad506146103935780635c975abb146103a657600080fd5b80630a28a4771161022f57806323b872dd1161021457806323b872dd14610315578063313ce5671461032857806338d52e0f1461034257600080fd5b80630a28a477146102fa57806318160ddd1461030d57600080fd5b8063046f7da21461026157806306fdde031461026b57806307a2d13a146102b6578063095ea7b3146102d7575b600080fd5b61026961057d565b005b60408051808201909152601181527f4379676e757320476c6f62616c2055534400000000000000000000000000000060208201525b6040516102ad919061255a565b60405180910390f35b6102c96102c43660046125ab565b61058f565b6040519081526020016102ad565b6102ea6102e53660046125d9565b6105b2565b60405190151581526020016102ad565b6102c96103083660046125ab565b6105c8565b6102c96105e5565b6102ea610323366004612605565b6105f4565b610330610617565b60405160ff90911681526020016102ad565b600454610355906001600160a01b031681565b6040516001600160a01b0390911681526020016102ad565b6102ea61037b3660046125d9565b610690565b6102c961038e3660046125d9565b6106cc565b6102c96103a13660046125ab565b6107b9565b60005460ff166102ea565b6102c96103bf366004612605565b6107c4565b6103cc6107fc565b604080519283526020830191909152016102ad565b6102c96103ef366004612646565b610817565b610269610839565b61026961084b565b6003546001600160a01b0316610355565b6102c96104233660046125d9565b61085b565b60408051808201909152600581527f636755534400000000000000000000000000000000000000000000000000000060208201526102a0565b6102ea61046f3660046125d9565b610881565b6102ea6104823660046125d9565b610904565b6102c96104953660046125ab565b610911565b6104ad6104a8366004612663565b610926565b6040516102ad9190612712565b6102696104c83660046125d9565b6109b0565b6102696104db366004612646565b610aaa565b6102c96104ee3660046125ab565b610d31565b6102c9610d46565b610355610d50565b6102c9610511366004612743565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6102ea610d7a565b6102c96105523660046125ab565b610df8565b610269610565366004612646565b610e03565b6102c9610578366004612646565b610e5a565b610585610e78565b61058d610ebe565b565b60006105ac61059c610f10565b6105a4610f2c565b849190610f56565b92915050565b60006105bf338484610f74565b50600192915050565b60006105ac6105d5610f2c565b6105dd610f10565b849190611081565b60006105ef610f10565b905090565b60006106018433846110a7565b61060c84848461113b565b5060015b9392505050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561066c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef919061277c565b3360008181526002602090815260408083206001600160a01b038716845290915281205490916105bf9185906106c79086906127b5565b610f74565b60006106d782610df8565b90508060000361072e5760405162461bcd60e51b815260206004820152600b60248201527f5a45524f5f53484152455300000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600454610746906001600160a01b031633308561115f565b61075033826111db565b5061076c8261075d6112b6565b61076791906127b5565b6112e0565b604080518381526001600160a01b038516602082015233917f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a910160405180910390a26105ac3382611309565b60006105ac8261058f565b6000806107d08361058f565b90506107dd8533836110a7565b6107e8858585611322565b6107f4858583866114f3565b949350505050565b6000806108076112b6565b61080f611593565b915091509091565b6001600160a01b0381166000908152600160205260408120546105ac9061058f565b610841610e78565b61058d60006115bd565b610853610e78565b61058d611627565b6000610868338484611322565b60006108738361058f565b9050610610338583866114f3565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156108f55760405162461bcd60e51b815260206004820152601460248201527f414c4c4f57414e43455f42454c4f575f5a45524f0000000000000000000000006044820152606401610725565b61060c33856106c786856127c8565b60006105bf33848461113b565b60006105ac61091e610f10565b6105dd610f2c565b61092e612518565b610936611664565b6109a36040518060e001604052808b81526020018a81526020018981526020018881526020018781526020018686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506020018490526116a1565b9998505050505050505050565b6109b8610e78565b6109c0610d7a565b610a0c5760405162461bcd60e51b815260206004820152600e60248201527f43414e5f4e4f545f494e564553540000000000000000000000000000000000006044820152606401610725565b600454610a23906001600160a01b03168383611b3f565b600081610a2e6112b6565b610a3891906127c8565b9050600082610a45611593565b610a4f91906127b5565b9050610a5a826112e0565b610a6381611b75565b60408051848152602081018490529081018290527f15294ad9d42e2bbd446d4ff6ca28fef807d1631ad53c688303fe468410830f329060600160405180910390a150505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610af55750825b905060008267ffffffffffffffff166001148015610b125750303b155b905081158015610b20575080155b15610b57576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610ba257845468ff00000000000000001916680100000000000000001785555b610baa611b9e565b610bd37f1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e42625879055565b610ca2866001600160a01b03166351a2d6d16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3891906127db565b876001600160a01b03166327810b6e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9a91906127db565b600019610f74565b6040516001600160a01b03871681527f8cb16e06ecfafbed13687256a764058471060b490b62dc8b3e4ea2f395ec29599060200160405180910390a18315610d2957845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b60006105ac610d3e610f2c565b6105a4610f10565b60006105ef610f2c565b60006105ef7f1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e426255490565b6000610d84611c99565b6001600160a01b0316632b95b7816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de591906127f8565b1580156105ef57505060005460ff161590565b60006105ac82610d31565b610e0b610e78565b6001600160a01b038116610e4e576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610725565b610e57816115bd565b50565b6001600160a01b0381166000908152600160205260408120546105ac565b6003546001600160a01b0316331461058d576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610725565b610ec6611d04565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000610f1a611593565b610f226112b6565b6105ef91906127b5565b60006105ef7f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be5490565b6000826000190484118302158202610f6d57600080fd5b5091020490565b6001600160a01b038316610fca5760405162461bcd60e51b815260206004820152601660248201527f415050524f56455f46524f4d5f5a45524f5f41444452000000000000000000006044820152606401610725565b6001600160a01b0382166110205760405162461bcd60e51b815260206004820152601460248201527f415050524f56455f544f5f5a45524f5f414444520000000000000000000000006044820152606401610725565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600082600019048411830215820261109857600080fd5b50910281810615159190040190565b6001600160a01b03808416600090815260026020908152604080832093861683529290522054600019811461113557818110156111265760405162461bcd60e51b815260206004820152601260248201527f414c4c4f57414e43455f455843454544454400000000000000000000000000006044820152606401610725565b61113584846106c785856127c8565b50505050565b600061114682610d31565b9050611153848483611322565b611135848484846114f3565b6040516001600160a01b0384811660248301528381166044830152606482018390526111359186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d40565b60006001600160a01b0383166112335760405162461bcd60e51b815260206004820152601160248201527f4d494e545f544f5f5a45524f5f414444520000000000000000000000000000006044820152606401610725565b8161123c610f2c565b61124691906127b5565b90506112717f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be829055565b6001600160a01b0383166000908152600160205260409020546112959083906127b5565b6001600160a01b039093166000908152600160205260409020929092555090565b60006105ef7f0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a65490565b610e577f0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a6829055565b61131e6000836113188461058f565b846114f3565b5050565b61132a611664565b6001600160a01b0383166113805760405162461bcd60e51b815260206004820152601760248201527f5452414e534645525f46524f4d5f5a45524f5f414444520000000000000000006044820152606401610725565b6001600160a01b0382166113d65760405162461bcd60e51b815260206004820152601560248201527f5452414e534645525f544f5f5a45524f5f4144445200000000000000000000006044820152606401610725565b306001600160a01b0383160361142e5760405162461bcd60e51b815260206004820152601a60248201527f5452414e534645525f544f5f53544554485f434f4e54524143540000000000006044820152606401610725565b6001600160a01b038316600090815260016020526040902054808211156114975760405162461bcd60e51b815260206004820152601060248201527f42414c414e43455f4558434545444544000000000000000000000000000000006044820152606401610725565b6114a182826127c8565b6001600160a01b0380861660009081526001602052604080822093909355908516815220546114d19083906127b5565b6001600160a01b03909316600090815260016020526040902092909255505050565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161153891815260200190565b60405180910390a3826001600160a01b0316846001600160a01b03167f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb8360405161158591815260200190565b60405180910390a350505050565b60006105ef7f2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b5490565b600380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61162f611664565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610ef33390565b60005460ff161561058d576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116a9612518565b60006116b3611dbc565b80519091506001600160a01b0316331461170f5760405162461bcd60e51b815260206004820152600f60248201527f4150505f415554485f4641494c454400000000000000000000000000000000006044820152606401610725565b82514210156117605760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5245504f52545f54494d455354414d5000000000000000006044820152606401610725565b6117996040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6117a1610f10565b81526117ab610f2c565b60208201526117ba8285611e7e565b60a0840151511561186e576117cf8285611f0e565b6060830181905260408301919091521561186e576040808301516060808501519084015192517f461149280000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260248101939093521690634611492890604401600060405180830381600087803b15801561185557600080fd5b505af1158015611869573d6000803e3d6000fd5b505050505b60208083015182519183015160608088015160808901516040808801519388015190517f3cf7df960000000000000000000000000000000000000000000000000000000081526004810197909752602487019490945260448601919091526064850152608484015260a48301526000916001600160a01b0390911690633cf7df969060c401606060405180830381865afa158015611910573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611934919061281a565b846080018560a001828152508281525082935050505061196383828760a001518860c001518660400151612050565b6119708560400151611b75565b84517f224918cef3c8dd950405e7cd332c2d23ff756244eb4ae4f3e81f6bf8f14d78ad8261199c6112b6565b6119a4611593565b6040805193845260208401929092529082015260600160405180910390a260a082015115611a485782604001516001600160a01b031663636e6b668360a001516040518263ffffffff1660e01b8152600401611a0291815260200190565b600060405180830381600087803b158015611a1c57600080fd5b505af1158015611a30573d6000803e3d6000fd5b50505050611a4683604001518360a001516121b8565b505b600080611a55878561234b565b915091508660a0015151600014611b1b5784602001516001600160a01b03166363e56b9f8284876040015188608001518960a00151611a9491906127c8565b60c08d01516040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1681526004810195909552602485019390935260448401919091526064830152608482015260a40160006040518083038186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050505b60408051606081018252918252602082019290925290810191909152949350505050565b6040516001600160a01b03838116602483015260448201839052611b7091859182169063a9059cbb90606401611194565b505050565b610e577f2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b829055565b600480546040517f70a0823100000000000000000000000000000000000000000000000000000000815230928101929092526000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c299190612848565b905080600003611c3b57611c3b612861565b611c43610f2c565b600003610e5757611c53816112e0565b604080518281526000602082015261dead917f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a910160405180910390a2610e57816123c6565b6000611ca3610d50565b6001600160a01b03166351a2d6d16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ce0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef91906127db565b60005460ff1661058d576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611d556001600160a01b038416836123df565b90508051600014158015611d7a575080806020019051810190611d7891906127f8565b155b15611b70576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610725565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611def610d50565b6001600160a01b031663b2ad11046040518163ffffffff1660e01b815260040160a060405180830381865afa158015611e2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e509190612877565b6001600160a01b03908116608087015290811660608601529081166040850152908116602084015216815290565b60208083015190820151606083015160808401516040517f848b2d7c0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526001600160a01b039091169063848b2d7c9060640160006040518083038186803b158015611efa57600080fd5b505afa158015610d29573d6000803e3d6000fd5b60008060008460600151905084602001516001600160a01b0316636a84f2fd8560a0015160018760a0015151611f4491906127c8565b81518110611f5457611f546128ec565b602002602001015186600001516040518363ffffffff1660e01b8152600401611f87929190918252602082015260400190565b60006040518083038186803b158015611f9f57600080fd5b505afa158015611fb3573d6000803e3d6000fd5b5050505060a084015160c08501516040517fa52e9c9f0000000000000000000000000000000000000000000000000000000081526001600160a01b0384169263a52e9c9f9261200492600401612902565b6040805180830381865afa158015612020573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612044919061294a565b90969095509350505050565b83156120d05760808501516040517f3194528a000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b0390911690633194528a90602401600060405180830381600087803b1580156120b757600080fd5b505af11580156120cb573d6000803e3d6000fd5b505050505b801561218d5760608501516004546120f2906001600160a01b03168284611b3f565b806001600160a01b0316635b206ec5856001875161211091906127c8565b81518110612120576121206128ec565b602002602001015185856040518463ffffffff1660e01b8152600401612159939291909283526020830191909152604082015260600190565b600060405180830381600087803b15801561217357600080fd5b505af1158015612187573d6000803e3d6000fd5b50505050505b600081856121996112b6565b6121a391906127b5565b6121ad91906127c8565b9050610d29816112e0565b60006001600160a01b0383166122105760405162461bcd60e51b815260206004820152601360248201527f4255524e5f46524f4d5f5a45524f5f41444452000000000000000000000000006044820152606401610725565b6001600160a01b038316600090815260016020526040902054808311156122795760405162461bcd60e51b815260206004820152601060248201527f42414c414e43455f4558434545444544000000000000000000000000000000006044820152606401610725565b60006122848461058f565b90508361228f610f2c565b61229991906127c8565b92506122c47f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be849055565b6122ce84836127c8565b6001600160a01b0386166000908152600160205260408120919091556122f38561058f565b60408051848152602081018390529081018790529091506001600160a01b038716907f8b2a1e1ad5e0578c3dd82494156e985dade827a87c573b5c1c7716a32162ad649060600160405180910390a250505092915050565b600080612356610f2c565b9150612360610f10565b84516020808701518682015187516040805193845293830191909152818301526060810186905260808101849052905192935090917f56a90fb9987084b721919e7e877c8c06757ce01d02952ca54cb1155774abfaea9181900360a00190a29250929050565b6123d261dead826111db565b50610e5761dead82611309565b60606106108383600084600080856001600160a01b03168486604051612405919061296e565b60006040518083038185875af1925050503d8060008114612442576040519150601f19603f3d011682016040523d82523d6000602084013e612447565b606091505b5091509150612457868383612461565b9695505050505050565b60608261247657612471826124d6565b610610565b815115801561248d57506001600160a01b0384163b155b156124cf576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610725565b5080610610565b8051156124e65780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180606001604052806003906020820280368337509192915050565b60005b83811015612551578181015183820152602001612539565b50506000910152565b6020815260008251806020840152612579816040850160208701612536565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156125bd57600080fd5b5035919050565b6001600160a01b0381168114610e5757600080fd5b600080604083850312156125ec57600080fd5b82356125f7816125c4565b946020939093013593505050565b60008060006060848603121561261a57600080fd5b8335612625816125c4565b92506020840135612635816125c4565b929592945050506040919091013590565b60006020828403121561265857600080fd5b8135610610816125c4565b60008060008060008060008060e0898b03121561267f57600080fd5b883597506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff808211156126ba57600080fd5b818b0191508b601f8301126126ce57600080fd5b8135818111156126dd57600080fd5b8c60208260051b85010111156126f257600080fd5b60208301955080945050505060c089013590509295985092959890939650565b60608101818360005b600381101561273a57815183526020928301929091019060010161271b565b50505092915050565b6000806040838503121561275657600080fd5b8235612761816125c4565b91506020830135612771816125c4565b809150509250929050565b60006020828403121561278e57600080fd5b815160ff8116811461061057600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156105ac576105ac61279f565b818103818111156105ac576105ac61279f565b6000602082840312156127ed57600080fd5b8151610610816125c4565b60006020828403121561280a57600080fd5b8151801515811461061057600080fd5b60008060006060848603121561282f57600080fd5b8351925060208401519150604084015190509250925092565b60006020828403121561285a57600080fd5b5051919050565b634e487b7160e01b600052600160045260246000fd5b600080600080600060a0868803121561288f57600080fd5b855161289a816125c4565b60208701519095506128ab816125c4565b60408701519094506128bc816125c4565b60608701519093506128cd816125c4565b60808701519092506128de816125c4565b809150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b8281101561293b5781518452928401929084019060010161291f565b50505092019290925292915050565b6000806040838503121561295d57600080fd5b505080516020909101519092909150565b60008251612980818460208701612536565b919091019291505056fea2646970667358221220850d22b1ba11f035bf015364ee858924d9af209cfdf73e7b69f4938235c7c48264736f6c63430008140033

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

000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000fecab866b450b97db38500898e9272c1d18918b7

-----Decoded View---------------
Arg [0] : _asset (address): 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Arg [1] : _owner (address): 0xfECAB866b450b97dB38500898e9272c1D18918b7

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913
Arg [1] : 000000000000000000000000fecab866b450b97db38500898e9272c1d18918b7


Loading...
Loading
Loading...
Loading
[ 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.