ETH Price: $2,059.34 (+3.97%)

Contract

0x592DD52CBF8271723E4e225ac0235D47e697A11c

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Fund X1Vault USD...165089852024-10-02 16:28:20173 days ago1727886500IN
CygnusDAO : DAO Reserves
0 ETH0.000564330.57
Fund X1Vault USD...138505042024-07-01 13:13:56266 days ago1719839636IN
CygnusDAO : DAO Reserves
0 ETH0.000118750.12
Fund X1Vault USD...122181082024-05-05 13:41:23323 days ago1714916483IN
CygnusDAO : DAO Reserves
0 ETH0.000237310.24
Fund X1Vault USD...97677492024-02-07 15:28:58411 days ago1707319738IN
CygnusDAO : DAO Reserves
0 ETH0.006942986.98
Fund X1Vault USD...97677262024-02-07 15:28:17411 days ago1707319697IN
CygnusDAO : DAO Reserves
0 ETH0.00695066.98
Fund X1Vault USD...97676552024-02-07 15:25:45411 days ago1707319545IN
CygnusDAO : DAO Reserves
0 ETH0.008314828.35
Switch Private B...95825452024-01-31 15:37:28418 days ago1706715448IN
CygnusDAO : DAO Reserves
0 ETH0.000123516.7
Set Cygnus X1Vau...95825402024-01-31 15:37:08418 days ago1706715428IN
CygnusDAO : DAO Reserves
0 ETH0.000342696.7
Set CYG Token93035362024-01-18 23:50:46431 days ago1705621846IN
CygnusDAO : DAO Reserves
0 ETH0.00018773.68
Set Cygnus DAO S...91226032024-01-09 23:53:04440 days ago1704844384IN
CygnusDAO : DAO Reserves
0 ETH0.000113032.2

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

Contract Source Code Verified (Exact Match)

Contract Name:
CygnusDAOReserves

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion
File 1 of 9 : CygnusDAOReserves.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.17;

// Dependencies
import {ICygnusDAOReserves} from "./interfaces/ICygnusDAOReserves.sol";
import {ReentrancyGuard} from "./utils/ReentrancyGuard.sol";

// Libraries
import {SafeTransferLib} from "./libraries/SafeTransferLib.sol";
import {FixedPointMathLib} from "./libraries/FixedPointMathLib.sol";
import {IHangar18} from "./interfaces/core/IHangar18.sol";

// Interfaces
import {ICygnusTerminal} from "./interfaces/core/ICygnusTerminal.sol";

/**
 *  @notice This contract receives all reserves and fees (if applicable) from Core contracts.
 *
 *          From the borrowable, this contract receives the reserve rate from borrows in the form of CygUSD. Note
 *          that the reserves are actually kept in CygUSD. The reserve rate is manually updatable at core contracts
 *          by admin, it is by default set to 10% with the option to set between 0% to 20%.
 *
 *          From the collateral, this contract receives liquidation fees in the form of CygLP. The liquidation fee
 *          is also an updatable parameter by admins, and can be set anywhere between 0% and 10%. It is by default
 *          set to 1%. This means that when CygLP is seized from the borrower, an extra 1% of CygLP is taken also.
 *
 *  @title  CygnusDAOReserves
 *  @author CygnusDAO
 *
 *                                              3.A. Harvest LP rewards
 *                   +------------------------------------------------------------------------------+
 *                   |                                                                              |
 *                   |                                                                              ▼
 *            +------------+                         +----------------------+            +--------------------+
 *            |            |  3.B. Mint USD reserves |                      |            |                    |
 *            |    CORE    |>----------------------► |     DAO RESERVES     |>---------► |      X1 VAULT      |
 *            |            |                         |   (this contract)    |            |                    |
 *            +------------+                         +----------------------+            +--------------------+
 *               ▲      |                                                                      ▲         |
 *               |      |    2. Track borrow/lend    +----------------------+                  |         |
 *               |      +--------------------------► |     CYG REWARDER     |                  |         |  6. Claim LP rewards + USDC
 *               |                                   +----------------------+                  |         |
 *               |                                            ▲    |                           |         |
 *               |                                            |    | 4. Claim CYG              |         |
 *               |                                            |    |                           |         |
 *               |                                            |    ▼                           |         |
 *               |                                   +------------------------+                |         |
 *               |    1. Deposit USDC / Liquidity    |                        |  5. Stake CYG  |         |
 *               +-----------------------------------|    LENDERS/BORROWERS   |>---------------+         |
 *                                                   |         ʕ•ᴥ•ʔ          |                          |
 *                                                   +------------------------+                          |
 *                                                              ▲                                        |
 *                                                              |                                        |
 *                                                              +----------------------------------------+
 *                                                                        LP Rewards + USDC
 *
 *       Important: Main functionality of this contract is to split the reserves received to two main addresses:
 *                  `daoReserves` and `cygnusX1Vault`
 *
 *                  This contract receives only CygUSD and CygLP (vault tokens of the Core contracts). The amount of
 *                  assets received by the X1 Vault depends on the `x1VaultWeight` variable. Basically this contract
 *                  redeems an amount of CygUSD shares for USDC and sends it to the vault so users can claim USD from
 *                  reserves. The DAO receives the leftover shares which are NOT to be redeemed. These shares sit in
 *                  the DAO reserves accruing interest (in the case of CygUSD) or earning from trading fees (in the
 *                  case of CygLP).
 */
contract CygnusDAOReserves is ICygnusDAOReserves, ReentrancyGuard {
    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            1. LIBRARIES
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /// @custom:library SafeTransferLib ERC20 transfer library that gracefully handles missing return values.
    using SafeTransferLib for address;

    /// @custom:library FixedPointMathLib Arithmetic library with operations for fixed-point numbers
    using FixedPointMathLib for uint256;

    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            2. STORAGE
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /// @inheritdoc ICygnusDAOReserves
    Shuttle[] public override allShuttles;

    /// @inheritdoc ICygnusDAOReserves
    string public override name = "Cygnus: DAO Reserves";

    /// @inheritdoc ICygnusDAOReserves
    address public override cygnusDAOSafe;
    /// @inheritdoc ICygnusDAOReserves
    address public override cygnusX1Vault;
    /// @inheritdoc ICygnusDAOReserves
    uint256 public override daoWeight;
    /// @inheritdoc ICygnusDAOReserves
    uint256 public override x1VaultWeight;

    /// @inheritdoc ICygnusDAOReserves
    address public override cygToken;
    /// @inheritdoc ICygnusDAOReserves
    uint256 public override daoLock;

    /// @inheritdoc ICygnusDAOReserves
    address public immutable override usd;

    /// @inheritdoc ICygnusDAOReserves
    IHangar18 public immutable override hangar18;

    /// @inheritdoc ICygnusDAOReserves
    bool public override privateBanker = true; // If true only admin can move

    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            3. CONSTRUCTOR
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /// @notice Constructs the DAO Reserves contract
    constructor(IHangar18 _hangar18) {
        // Set the Hangar18 contract address
        hangar18 = _hangar18;

        // Set the USD contract
        usd = _hangar18.usd(); // This is underlying for all borrowables

        // Set the weight of the shares that are redeemed and sent to the vault
        x1VaultWeight = 1e18;

        // Set the weight of the shares that this contract receives that are sent to the dao positions address
        daoWeight = 1e18 - x1VaultWeight;

        // CYG tokens for the DAO are locked from moving for the first 3 months
        daoLock = block.timestamp + 90 days;
    }

    /**
     *  @dev This function is called for plain Ether transfers
     */
    receive() external payable {}

    /**
     *  @dev Fallback function is executed if none of the other functions match the function identifier or no data was provided
     */
    fallback() external payable {}

    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            4. MODIFIERS
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /// @custom:modifier cygnusAdmin Controls important parameters in both Collateral and Borrow contracts 👽
    modifier cygnusAdmin() {
        _checkAdmin();
        _;
    }

    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            5. CONSTANT FUNCTIONS
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /*  ────────────────────────────────────────────── Private ────────────────────────────────────────────────  */

    /// @notice Internal check for msg.sender admin, checks factory's current admin 👽
    function _checkAdmin() private view {
        // Current admin from the factory
        address admin = hangar18.admin();

        /// @custom:error MsgSenderNotAdmin Avoid unless caller is Cygnus Admin
        if (msg.sender != admin) {
            revert CygnusDAOReserves__MsgSenderNotAdmin({admin: admin, sender: msg.sender});
        }
    }

    /// @notice Checks the `token` balance of this contract
    /// @param token The token to view balance of
    /// @return amount This contract's `token` balance
    function _checkBalance(address token) private view returns (uint256) {
        // Our balance of `token` (uses solady lib)
        return token.balanceOf(address(this));
    }

    /*  ─────────────────────────────────────────────── Public ────────────────────────────────────────────────  */

    /// @inheritdoc ICygnusDAOReserves
    function allShuttlesLength() public view returns (uint256) {
        return allShuttles.length;
    }

    /// @inheritdoc ICygnusDAOReserves
    function cygTokenBalance() public view returns (uint256) {
        // Return CYG balance
        return _checkBalance(cygToken);
    }

    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            6. NON-CONSTANT FUNCTIONS
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /*  ────────────────────────────────────────────── Private ────────────────────────────────────────────────  */

    /// @notice Redeems vault token (CygUSD)
    /// @param borrowable The address of the CygUSD vault token
    /// @return shares The amount of shares sent to the safe
    /// @return assets The amount of assets sent to the vault
    function _redeemAndFundUSD(address borrowable) private returns (uint256 shares, uint256 assets) {
        /// @custom:error CantRedeemAddressZero Avoid if shuttle does not exist
        if (borrowable == address(0)) revert CygnusDAOReserves__CantRedeemAddressZero();

        // Sync and mint new reserves if needed
        ICygnusTerminal(borrowable).sync();

        // Get balance of vault shares we own
        uint256 totalShares = _checkBalance(borrowable);

        // Shares for the X1 Vault
        uint256 x1Shares = totalShares.mulWad(x1VaultWeight);

        // Shares for the DAO
        shares = totalShares - x1Shares;

        // Redeem USDC to the X1 vault
        if (x1Shares > 0) assets = ICygnusTerminal(borrowable).redeem(x1Shares, cygnusX1Vault, address(this));

        // Send CygUSD to the DAO safe
        if (shares > 0) borrowable.safeTransfer(cygnusDAOSafe, shares);
    }

    /// @notice Redeems vault token (CygLP)
    /// @param collateral The address of the CygLP vault token
    /// @return shares The amount of shares sent to the safe
    function _redeemAndFundCygLP(address collateral) private returns (uint256 shares) {
        // Get balance of this CygLP we own
        shares = _checkBalance(collateral);

        // Transfer CygLP to the safe
        if (shares > 0) collateral.safeTransfer(cygnusDAOSafe, shares);
    }

    /*  ────────────────────────────────────────────── External ───────────────────────────────────────────────  */

    // USDC: Have 100 CygUSD. We redeem 50 CygUSD for USDC and send the USDC to the X1 Vault.
    //       The 50 leftover CygUSD we send to the DAO to not be redeemed, kept as reserves.

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security non-reentrant
    function fundX1VaultUSD(uint256 shuttleId) external override nonReentrant returns (uint256 daoShares, uint256 x1Assets) {
        // If the private banker is set to "TRUE" then we revert if msg.sender is not admin
        if (privateBanker) _checkAdmin();

        // Address of borrowable at index `i`
        address borrowable = allShuttles[shuttleId].borrowable;

        // Redeem CygUSD for USD
        (daoShares, x1Assets) = _redeemAndFundUSD(borrowable);

        /// @custom:event FundX1Vault
        emit FundX1Vault(borrowable, cygnusDAOSafe, cygnusX1Vault, daoShares, x1Assets);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security non-reentrant
    function fundX1VaultUSDAll() external override nonReentrant returns (uint256 daoShares, uint256 x1Assets) {
        // If the private banker is set to "TRUE" then we revert if msg.sender is not admin
        if (privateBanker) _checkAdmin();

        // Get shuttles length
        uint256 shuttlesLength = allShuttles.length;

        // Gas savings
        Shuttle[] memory _shuttles = allShuttles;

        // Loop over each lending borrowable and redeem CygUSD for USD
        for (uint256 i = 0; i < shuttlesLength; ) {
            // Address of borrowable at index `i`
            address borrowable = _shuttles[i].borrowable;

            // Redeem CygUSD for USD
            (uint256 _shares, uint256 _assets) = _redeemAndFundUSD(borrowable);

            unchecked {
                // Increase shares redeemed
                daoShares += _shares;

                // Increase assets received
                x1Assets += _assets;

                i++;
            }
        }

        /// @custom:event FundX1VaultAll
        emit FundX1VaultAll(shuttlesLength, cygnusX1Vault, daoShares, x1Assets);
    }

    // LP Tokens: Function only used if `liquidationFee` is active, meaning we receive from each Liquidation.

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security non-reentrant
    function fundDAOPositionsCygLP(uint256 shuttleId) external override nonReentrant returns (uint256 daoShares) {
        // If the private banker is set to "TRUE" then we revert if msg.sender is not admin
        if (privateBanker) _checkAdmin();

        // Get this shuttle's collateral address
        address collateral = allShuttles[shuttleId].collateral;

        // Send CygLP to the safe if we have any
        daoShares = _redeemAndFundCygLP(collateral);

        /// @custom:event FundDAOCygLP
        emit FundDAOReserves(collateral, cygnusDAOSafe, daoShares);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security non-reentrant
    function fundDAOPositionsCygLPAll() external override nonReentrant returns (uint256 daoShares) {
        // If the private banker is set to "TRUE" then we revert if msg.sender is not admin
        if (privateBanker) _checkAdmin();

        // Get shuttles length
        uint256 shuttlesLength = allShuttles.length;

        // Gas savings
        Shuttle[] memory _shuttles = allShuttles;

        // Loop over each collateral and check for our CygLP balance
        for (uint256 i = 0; i < shuttlesLength; ) {
            // Get collateral for shuttle at index `i`
            address collateral = _shuttles[i].collateral;

            unchecked {
                // Send CygLP to the safe if we have any
                daoShares += _redeemAndFundCygLP(collateral);

                // Next iteration
                i++;
            }
        }

        /// @custom:event FundDAOPositions
        emit FundDAOReservesAll(shuttlesLength, cygnusDAOSafe, daoShares);
    }

    // Hangar18 only

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security non-reentrant only-hangar
    function addShuttle(uint256 shuttleId, address borrowable, address collateral) external override {
        /// @custom:error MsgSenderNotHangar Can only be added after deployment
        if (msg.sender != address(hangar18)) revert CygnusDAOReserves__MsgSenderNotHangar();

        // Create Lending pool with borrowable and collateral
        Shuttle memory shuttle = Shuttle({initialized: true, shuttleId: shuttleId, borrowable: borrowable, collateral: collateral});

        // Push to array
        allShuttles.push(shuttle);

        /// @custom:event NewShuttleAdded
        emit NewShuttleAdded(shuttle);
    }

    // Admin only

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security non-reentrant only-admin
    function setX1VaultWeight(uint256 weight) external override cygnusAdmin {
        /// @custom:error WeightNotAllowed Avoid setting new weight above 100%
        if (weight > 1e18) revert CygnusDAOReserves__WeightNotAllowed({weight: weight});

        // Old weight
        uint256 oldWeight = x1VaultWeight;

        // New weight
        x1VaultWeight = weight;

        // Adjust DAO Positions
        daoWeight = 1e18 - weight;

        /// @custom:event NewX1VaultWeight
        emit NewX1VaultWeight(oldWeight, x1VaultWeight);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security only-admin
    function setCYGToken(address _token) external override cygnusAdmin {
        // Important: Can only be set once!
        if (cygToken != address(0)) return;

        // Assign the CYG token
        cygToken = _token;

        /// @custom:event CygTokenAdded
        emit CygTokenAdded(_token);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security only-admin
    function sweepToken(address token) external override cygnusAdmin {
        // Escape if the token is CygToken OR if cygToken has not been set yet, cannot sweep
        if (token == cygToken || cygToken == address(0)) return;

        // Balance this contract has of the erc20 token we are recovering
        uint256 balance = token.balanceOf(address(this));

        // Transfer token
        if (balance > 0) token.safeTransfer(msg.sender, balance);

        /// @custom:event SweepToken
        emit SweepToken(token, balance);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security only-admin
    function sweepNative() external override cygnusAdmin {
        // Get native balance
        uint256 balance = address(this).balance;

        // Get native out
        if (balance > 0) SafeTransferLib.safeTransferETH(msg.sender, balance);

        /// @custom:event SweepToken
        emit SweepToken(address(0), balance);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security only-admin
    function claimCygTokenDAO(uint256 amount, address to) external override cygnusAdmin {
        // Current timestamp of withdrawal
        uint256 currentTime = block.timestamp;

        /// @custom:error CantClaimCygYet
        if (currentTime < daoLock) revert CygnusDAOReserves__CantClaimCygYet({time: currentTime, claimAt: daoLock});

        // Balance of CYG
        uint256 balance = cygTokenBalance();

        /// @custom:error NotEnoughCyg
        if (amount > balance) revert CygnusDAOReserves__NotEnoughCyg({amount: amount, balance: balance});

        // Transfer to `to`
        cygToken.safeTransfer(to, amount);

        /// @custom:event ClaimCygToken
        emit ClaimCygToken(amount, to);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security only-admin
    function switchPrivateBanker() external override cygnusAdmin {
        /// @custom:event SwitchPrivateBanker
        emit SwitchPrivateBanker(privateBanker = !privateBanker);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security only-admin
    function setCygnusDAOSafe(address _newSafe) external override cygnusAdmin {
        /// @custom:error SafeCantBeZero
        if (_newSafe == address(0)) revert CygnusDAOReserves__SafeCantBeZero();

        // Safe up to now
        address oldSafe = cygnusDAOSafe;

        /// @custom;event NewDAOSafe
        emit NewDAOSafe(oldSafe, cygnusDAOSafe = _newSafe);
    }

    /// @inheritdoc ICygnusDAOReserves
    /// @custom:security only-admin
    function setCygnusX1Vault(address _x1Vault) external override cygnusAdmin {
        /// @custom:error X1VaultCantBeZero
        if (_x1Vault == address(0)) revert CygnusDAOReserves__X1VaultCantBeZero();

        // Old vault up to now
        address oldVault = cygnusX1Vault;

        /// @custom:event NewX1Vault
        emit NewX1Vault(oldVault, cygnusX1Vault = _x1Vault);
    }
}

File 2 of 9 : ICygnusTerminal.sol
//  SPDX-License-Identifier: AGPL-3.0-or-later
//
//  ICygnusTerminal.sol
//
//  Copyright (C) 2023 CygnusDAO
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.8.17;

// Dependencies
import {IERC20Permit} from "./IERC20Permit.sol";

/**
 *  @title ICygnusTerminal
 *  @notice The interface to mint/redeem pool tokens (CygLP and CygUSD)
 */
interface ICygnusTerminal is IERC20Permit {

    /**
     *  @notice Redeems the specified amount of `shares` for the underlying asset and transfers it to `recipient`.
     *
     *  @dev shares must be greater than 0.
     *  @dev If the function is called by someone other than `owner`, then the function will reduce the allowance
     *       granted to the caller by `shares`.
     *
     *  @param shares The number of shares to redeem for the underlying asset.
     *  @param recipient The address that will receive the underlying asset.
     *  @param owner The address that owns the shares.
     *
     *  @return assets The amount of underlying assets received by the `recipient`.
     */
    function redeem(uint256 shares, address recipient, address owner) external returns (uint256 assets);

    /**
     *  @notice Exchange Rate between the pool token and the asset
     */
    function exchangeRate() external view returns (uint256);

    /**
     *  @notice The lending pool ID (shared by borrowable/collateral)
     */
    function shuttleId() external view returns (uint256);

    /**
     *  @notice Get the collateral address from the borrowable
     */
    function collateral() external view returns (address);

    /**
     *  @notice Get the borrowable address from the collateral
     */
    function borrowable() external view returns (address);

    /**
     *  @notice Syncs the totalBalance in terms of its underlying (accrues interest in borrowable)
     */
    function sync() external;
}

File 3 of 9 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.8.17;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` 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 amount) external returns (bool);

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

    // Mint
    function mint(address, uint256) external;
}

File 4 of 9 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity >=0.8.17;

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

/**
 * @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.
 */
interface IERC20Permit is IERC20 {
    /**
     * @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.
     */
    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);
}

File 5 of 9 : IHangar18.sol
//  SPDX-License-Identifier: AGPL-3.0-or-later
//
//  IHangar18.sol
//
//  Copyright (C) 2023 CygnusDAO
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.8.17;

// Oracles

/**
 *  @title The interface for the Cygnus Factory
 *  @notice The Cygnus factory facilitates creation of collateral and borrow pools
 */
interface IHangar18 {

    /**
     *  @notice Array of LP Token pairs deployed
     *  @param _shuttleId The ID of the shuttle deployed
     *  @return launched Whether this pair exists or not
     *  @return shuttleId The ID of this shuttle
     *  @return borrowable The address of the borrow contract
     *  @return collateral The address of the collateral contract
     *  @return orbiterId The ID of the orbiters used to deploy this lending pool
     */
    function allShuttles(
        uint256 _shuttleId
    ) external view returns (bool launched, uint88 shuttleId, address borrowable, address collateral, uint96 orbiterId);

    /**
     *  @return usd The address of the borrowable token (stablecoin)
     */
    function usd() external view returns (address);

    /**
     *  @return admin The address of the Cygnus Admin which grants special permissions in collateral/borrow contracts
     */
    function admin() external view returns (address);

    /**
     *  @return daoReserves The address that handles Cygnus reserves from all pools
     */
    function daoReserves() external view returns (address);
}

File 6 of 9 : ICygnusDAOReserves.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.17;

import {IHangar18} from "./core/IHangar18.sol";

interface ICygnusDAOReserves {
    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            1. CUSTOM ERRORS
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /// @dev Reverts when attempting to call Admin-only functions
    /// @param admin The address of the admin of hangar18
    /// @param sender Address of msg.sender
    /// @custom:error MsgSenderNotAdmin
    error CygnusDAOReserves__MsgSenderNotAdmin(address admin, address sender);

    /// @dev Reverts when adding new shuttle to the reserves
    /// @param shuttleId The ID for the lending pool we are initializing
    /// @custom:error ShuttleNotInitialized
    error CygnusDAOReserves__ShuttleDoesntExist(uint256 shuttleId);

    /// @dev Reverts when adding new shuttle to the reserves
    /// @param shuttleId The ID for the lending pool we are initializing
    /// @custom:error ShuttleAlreadyInitialized
    error CygnusDAOReserves__ShuttleAlreadyInitialized(uint256 shuttleId);

    /// @dev Reverts when setting a new weight outside range allowed
    /// @param weight The weight of the X1 Vault
    /// @custom:error WeightNotAllowed
    error CygnusDAOReserves__WeightNotAllowed(uint256 weight);

    /// @dev Reverts when trying to claim cyg before lock period ends
    /// @custom:error CantClaimCygYet
    error CygnusDAOReserves__CantClaimCygYet(uint256 time, uint256 claimAt);

    /// @dev Reverts when theres not enough cyg to claim
    /// @custom:error NotEnoughCyg
    error CygnusDAOReserves__NotEnoughCyg(uint256 amount, uint256 balance);

    /// @dev Reverts if borrowable is not set
    /// @custom:error CantRedeemAddressZero
    error CygnusDAOReserves__CantRedeemAddressZero();

    /// @dev Reverts if Safe is 0
    /// @custom:error SafeCantBeZero
    error CygnusDAOReserves__SafeCantBeZero();

    /// @dev Reverts if X1 vault is 0
    /// @custom:error X1VaultCantBeZero
    error CygnusDAOReserves__X1VaultCantBeZero();

    /// @dev Reverts if sender is not Hangar18
    /// @custom:error MsgSenderNotHangar
    error CygnusDAOReserves__MsgSenderNotHangar();

    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            2. CUSTOM EVENTS
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /// @dev Logs when the X1 Vault is funded with assets
    /// @param vaultToken The address of the vault token
    /// @param positions The address receiving the left over shares
    /// @param vault The address receiving the assets
    /// @param shares The amount of shares being redeemed
    /// @param assets The amount of assets funded to
    /// @custom:event FundX1Vault
    event FundX1Vault(address indexed vaultToken, address indexed positions, address indexed vault, uint256 shares, uint256 assets);

    /// @dev Logs when the DAO Positions receives CygLP
    /// @param vaultToken The address of the vault token
    /// @param positions The address of the DAO Positions
    /// @param shares The amount of shares transfered to DAO Positions
    /// @custom:event FundDAOPositions
    event FundDAOReserves(address indexed vaultToken, address indexed positions, uint256 shares);

    /// @dev Logs when admin sets a new weight for the vault
    /// @param oldWeight The old X1 Vault weight
    /// @param newWeight The new X1 Vault weight
    /// @custom:event NewX1VaultWeight
    event NewX1VaultWeight(uint256 oldWeight, uint256 newWeight);

    /// @dev Logs when a new shuttle is added
    /// @param shuttle The Shuttle struct record
    /// @custom:event NewShuttleAdded
    event NewShuttleAdded(Shuttle shuttle);

    /// @dev Logs When the Cygnus X1 Vault is funded by all shuttles
    /// @param totalShuttles The amount of lending pools we harvested
    /// @param vault The address of the X1 Vault
    /// @param shares The amount of CygUSD redeemed
    /// @param assets The amount of assets received
    /// @custom:event FundX1VaultAll
    event FundX1VaultAll(uint256 totalShuttles, address vault, uint256 shares, uint256 assets);

    /// @dev Logs When the Cygnus X1 Vault is funded by all shuttles
    /// @param totalShuttles The amount of lending pools we harvested
    /// @param positions The address of the DAO Positions
    /// @param shares The amount of shares transfered to DAO Positions
    /// @custom:event FundDAOReservesAll
    event FundDAOReservesAll(uint256 totalShuttles, address positions, uint256 shares);

    /// @dev Logs when permissions for splitting shares and assets are switched
    /// @param _privateBanker Whether only admin can split or anyone can (true = only admin)
    /// @custom:event SwitchPrivateBanker
    event SwitchPrivateBanker(bool _privateBanker);

    /// @dev Logs when the DAO claims their shares of CYG token
    /// @param amount Amount claimed of CYG token
    /// @param to Address who received the CYG tokens
    /// @custom:event ClaimCygToken
    event ClaimCygToken(uint256 amount, address to);

    /// @dev Logs when admin sweeps a token (throws is the token is CYG)
    /// @param token The address of the token
    /// @param balance The balance of the token claimed
    /// @custom:event SweepToken
    event SweepToken(address token, uint256 balance);

    /// @dev Logs when admin adds the CYG token
    /// @param token The address of the CYG token
    /// @custom:event CygTokenAdded
    event CygTokenAdded(address token);

    /// @dev Logs when admin replaces the dao safe
    /// @param oldSafe the address of the safe up to now
    /// @param newSafe the address of the new safe
    /// @custom:event NewDAOSafe
    event NewDAOSafe(address oldSafe, address newSafe);

    /// @dev Logs when admin replaces the X1 Vault
    /// @param oldVault the address of the X1 Vault up to now
    /// @param newVault the address of the new X1 Vault
    /// @custom:event NewX1Vault
    event NewX1Vault(address oldVault, address newVault);

    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            3. CONSTANT FUNCTIONS
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /// @notice The shuttle struct for each lending pool
    /// @custom:struct Shuttle Information of each lending pool
    /// @custom:member initialized Whether the shuttle is initialized or not
    /// @custom:member shuttleId The unique identifier of the shuttle
    /// @custom:member borrowable The address of the borrowable asset
    /// @custom:member collateral The address of the collateral asset
    struct Shuttle {
        bool initialized;
        uint256 shuttleId;
        address borrowable;
        address collateral;
    }

    /// @dev Retrieves information about a specific shuttle.
    /// @param _shuttleId The ID of the shuttle to retrieve information about.
    /// @return initialized Whether the shuttle is initialized or not.
    /// @return shuttleId The unique identifier of the shuttle.
    /// @return borrowable The address of the borrowable asset.
    /// @return collateral The address of the collateral asset.
    function allShuttles(
        uint256 _shuttleId
    ) external view returns (bool initialized, uint256 shuttleId, address borrowable, address collateral);

    /// @dev Name of the contract
    function name() external view returns (string memory);

    /// @dev Retrieves the address of the Hangar18 contract.
    /// @return The address of the Hangar18 contract.
    function hangar18() external view returns (IHangar18);

    /// @dev Retrieves the address of the Cygnus DAO positions.
    /// @return The address of the CygnusDAO positions.
    function cygnusDAOSafe() external view returns (address);

    /// @dev Retrieves the address of the CygnusX1Vault contract.
    /// @return The address of the CygnusX1Vault contract.
    function cygnusX1Vault() external view returns (address);

    /// @dev Retrieves the address of the USD contract.
    /// @return The address of the USD contract.
    function usd() external view returns (address);

    /// @dev Retrieves the weight of the X1 vault.
    /// @return The weight of the X1 vault.
    function x1VaultWeight() external view returns (uint256);

    /// @dev Retrieves the weight of the DAO positions
    /// @return The weight of the DAO positions.
    function daoWeight() external view returns (uint256);

    /// @dev Retrieves the length of the allShuttles array.
    /// @return The length of the allShuttles array.
    function allShuttlesLength() external view returns (uint256);

    /// @dev Address of the CYG token
    function cygToken() external view returns (address);

    /// @dev current balance of CYg
    function cygTokenBalance() external view returns (uint256);

    /// @dev The unlock cyg DAO time
    function daoLock() external view returns (uint256);

    /// @dev Whether anyone can split shares and assets
    function privateBanker() external view returns (bool);

    /*  ═══════════════════════════════════════════════════════════════════════════════════════════════════════ 
            4. NON-CONSTANT FUNCTIONS
        ═══════════════════════════════════════════════════════════════════════════════════════════════════════  */

    /// @dev Funds the CygnusX1Vault with all the available USD tokens from `shuttleId`
    /// @param shuttleId The ID of the lending pool
    /// @return shares The total amount of shares transferred to CygnusDAOPositions.
    /// @return assets The total amount of assets transferred to CygnusX1Vault.
    function fundX1VaultUSD(uint256 shuttleId) external returns (uint256 shares, uint256 assets);

    /// @dev Funds the CygnusX1Vault with all the available LP tokens from `shuttleId`
    /// @param shuttleId The ID of the lending pool
    /// @return shares The total amount of shares transfered to CygnusDAOPositions
    function fundDAOPositionsCygLP(uint256 shuttleId) external returns (uint256 shares);

    /// @dev Funds the CygnusX1Vault with all the available tokens from all shuttles.
    /// @return shares The total amount of shares transferred to CygnusDAOPositions.
    /// @return assets The total amount of assets transferred to CygnusX1Vault.
    function fundX1VaultUSDAll() external returns (uint256 shares, uint256 assets);

    /// @dev Funds the DAO Positions with all the available tokens from all shuttles.
    /// @return shares The total amount of shares transferred to CygnusDAOPositions.
    function fundDAOPositionsCygLPAll() external returns (uint256 shares);

    /// @dev Sets the weight of the X1 vault.
    /// @param weight The new weight to be set for the X1 vault.
    function setX1VaultWeight(uint256 weight) external;

    /// @notice Adds a shuttle to the record
    /// @param shuttleId The ID for the shuttle we are adding
    /// @custom:security non-reentrant only-admin
    function addShuttle(uint256 shuttleId, address borrowable, address collateral) external;

    /// @notice Sweeps any token sent to this contract except the CYG token
    /// @param token The address of the token being swept
    function sweepToken(address token) external;

    /// @notice Sends an amount of `cygToken` to `to`
    function claimCygTokenDAO(uint256 amount, address to) external;

    /// @notice Sets the CYG token
    function setCYGToken(address _token) external;

    /// @notice Admin allows anyone to split the shares/assets between the DAO Reserves and X1 Vault
    /// @custom:security only-admin
    function switchPrivateBanker() external;

    /// @notice Admin assigns new safe address
    /// @custom:security only-admin
    function setCygnusDAOSafe(address _safe) external;

    /// @notice Admin assigns new X1 vault address
    /// @custom:security only-admin
    function setCygnusX1Vault(address _vault) external;

    /// @notice Sweep ETH
    function sweepNative() external;
}

File 7 of 9 : FixedPointMathLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
library FixedPointMathLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The operation failed, as the output exceeds the maximum value of uint256.
    error ExpOverflow();

    /// @dev The operation failed, as the output exceeds the maximum value of uint256.
    error FactorialOverflow();

    /// @dev The operation failed, due to an multiplication overflow.
    error MulWadFailed();

    /// @dev The operation failed, either due to a
    /// multiplication overflow, or a division by a zero.
    error DivWadFailed();

    /// @dev The multiply-divide operation failed, either due to a
    /// multiplication overflow, or a division by a zero.
    error MulDivFailed();

    /// @dev The division failed, as the denominator is zero.
    error DivFailed();

    /// @dev The full precision multiply-divide operation failed, either due
    /// to the result being larger than 256 bits, or a division by a zero.
    error FullMulDivFailed();

    /// @dev The output is undefined, as the input is less-than-or-equal to zero.
    error LnWadUndefined();

    /// @dev The output is undefined, as the input is zero.
    error Log2Undefined();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              SIMPLIFIED FIXED POINT OPERATIONS             */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `(x * y) / WAD` rounded down.
    function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
            if mul(y, gt(x, div(not(0), y))) {
                // Store the function selector of `MulWadFailed()`.
                mstore(0x00, 0xbac65e5b)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            z := div(mul(x, y), WAD)
        }
    }

    /// @dev Equivalent to `(x * y) / WAD` rounded up.
    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
            if mul(y, gt(x, div(not(0), y))) {
                // Store the function selector of `MulWadFailed()`.
                mstore(0x00, 0xbac65e5b)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded down.
    function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.
            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
                // Store the function selector of `DivWadFailed()`.
                mstore(0x00, 0x7c5f487d)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            z := div(mul(x, WAD), y)
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded up.
    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.
            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
                // Store the function selector of `DivWadFailed()`.
                mstore(0x00, 0x7c5f487d)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))
        }
    }

    /// @dev Equivalent to `x` to the power of `y`.
    /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`.
    function powWad(int256 x, int256 y) internal pure returns (int256) {
        // Using `ln(x)` means `x` must be greater than 0.
        return expWad((lnWad(x) * y) / int256(WAD));
    }

    /// @dev Returns `exp(x)`, denominated in `WAD`.
    function expWad(int256 x) internal pure returns (int256 r) {
        unchecked {
            // When the result is < 0.5 we return zero. This happens when
            // x <= floor(log(0.5e18) * 1e18) ~ -42e18
            if (x <= -42139678854452767551) return r;

            /// @solidity memory-safe-assembly
            assembly {
                // When the result is > (2**255 - 1) / 1e18 we can not represent it as an
                // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.
                if iszero(slt(x, 135305999368893231589)) {
                    // Store the function selector of `ExpOverflow()`.
                    mstore(0x00, 0xa37bfec9)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
            }

            // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96
            // for more intermediate precision and a binary basis. This base conversion
            // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.
            x = (x << 78) / 5 ** 18;

            // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers
            // of two such that exp(x) = exp(x') * 2**k, where k is an integer.
            // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).
            int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;
            x = x - k * 54916777467707473351141471128;

            // k is in the range [-61, 195].

            // Evaluate using a (6, 7)-term rational approximation.
            // p is made monic, we'll multiply by a scale factor later.
            int256 y = x + 1346386616545796478920950773328;
            y = ((y * x) >> 96) + 57155421227552351082224309758442;
            int256 p = y + x - 94201549194550492254356042504812;
            p = ((p * y) >> 96) + 28719021644029726153956944680412240;
            p = p * x + (4385272521454847904659076985693276 << 96);

            // We leave p in 2**192 basis so we don't need to scale it back up for the division.
            int256 q = x - 2855989394907223263936484059900;
            q = ((q * x) >> 96) + 50020603652535783019961831881945;
            q = ((q * x) >> 96) - 533845033583426703283633433725380;
            q = ((q * x) >> 96) + 3604857256930695427073651918091429;
            q = ((q * x) >> 96) - 14423608567350463180887372962807573;
            q = ((q * x) >> 96) + 26449188498355588339934803723976023;

            /// @solidity memory-safe-assembly
            assembly {
                // Div in assembly because solidity adds a zero check despite the unchecked.
                // The q polynomial won't have zeros in the domain as all its roots are complex.
                // No scaling is necessary because p is already 2**96 too large.
                r := sdiv(p, q)
            }

            // r should be in the range (0.09, 0.25) * 2**96.

            // We now need to multiply r by:
            // * the scale factor s = ~6.031367120.
            // * the 2**k factor from the range reduction.
            // * the 1e18 / 2**96 factor for base conversion.
            // We do this all at once, with an intermediate result in 2**213
            // basis, so the final right shift is always by a positive amount.
            r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));
        }
    }

    /// @dev Returns `ln(x)`, denominated in `WAD`.
    function lnWad(int256 x) internal pure returns (int256 r) {
        unchecked {
            /// @solidity memory-safe-assembly
            assembly {
                if iszero(sgt(x, 0)) {
                    // Store the function selector of `LnWadUndefined()`.
                    mstore(0x00, 0x1615e638)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
            }

            // We want to convert x from 10**18 fixed point to 2**96 fixed point.
            // We do this by multiplying by 2**96 / 10**18. But since
            // ln(x * C) = ln(x) + ln(C), we can simply do nothing here
            // and add ln(2**96 / 10**18) at the end.

            // Compute k = log2(x) - 96.
            int256 k;
            /// @solidity memory-safe-assembly
            assembly {
                let v := x
                k := shl(7, lt(0xffffffffffffffffffffffffffffffff, v))
                k := or(k, shl(6, lt(0xffffffffffffffff, shr(k, v))))
                k := or(k, shl(5, lt(0xffffffff, shr(k, v))))

                // For the remaining 32 bits, use a De Bruijn lookup.
                // See: https://graphics.stanford.edu/~seander/bithacks.html
                v := shr(k, v)
                v := or(v, shr(1, v))
                v := or(v, shr(2, v))
                v := or(v, shr(4, v))
                v := or(v, shr(8, v))
                v := or(v, shr(16, v))

                // forgefmt: disable-next-item
                k := sub(
                    or(k, byte(shr(251, mul(v, shl(224, 0x07c4acdd))), 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f)),
                    96
                )
            }

            // Reduce range of x to (1, 2) * 2**96
            // ln(2^k * x) = k * ln(2) + ln(x)
            x <<= uint256(159 - k);
            x = int256(uint256(x) >> 159);

            // Evaluate using a (8, 8)-term rational approximation.
            // p is made monic, we will multiply by a scale factor later.
            int256 p = x + 3273285459638523848632254066296;
            p = ((p * x) >> 96) + 24828157081833163892658089445524;
            p = ((p * x) >> 96) + 43456485725739037958740375743393;
            p = ((p * x) >> 96) - 11111509109440967052023855526967;
            p = ((p * x) >> 96) - 45023709667254063763336534515857;
            p = ((p * x) >> 96) - 14706773417378608786704636184526;
            p = p * x - (795164235651350426258249787498 << 96);

            // We leave p in 2**192 basis so we don't need to scale it back up for the division.
            // q is monic by convention.
            int256 q = x + 5573035233440673466300451813936;
            q = ((q * x) >> 96) + 71694874799317883764090561454958;
            q = ((q * x) >> 96) + 283447036172924575727196451306956;
            q = ((q * x) >> 96) + 401686690394027663651624208769553;
            q = ((q * x) >> 96) + 204048457590392012362485061816622;
            q = ((q * x) >> 96) + 31853899698501571402653359427138;
            q = ((q * x) >> 96) + 909429971244387300277376558375;
            /// @solidity memory-safe-assembly
            assembly {
                // Div in assembly because solidity adds a zero check despite the unchecked.
                // The q polynomial is known not to have zeros in the domain.
                // No scaling required because p is already 2**96 too large.
                r := sdiv(p, q)
            }

            // r is in the range (0, 0.125) * 2**96

            // Finalization, we need to:
            // * multiply by the scale factor s = 5.549…
            // * add ln(2**96 / 10**18)
            // * add k * ln(2)
            // * multiply by 10**18 / 2**96 = 5**18 >> 78

            // mul s * 5e18 * 2**96, base is now 5**18 * 2**192
            r *= 1677202110996718588342820967067443963516166;
            // add ln(2) * k * 5e18 * 2**192
            r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;
            // add ln(2**96 / 10**18) * 5e18 * 2**192
            r += 600920179829731861736702779321621459595472258049074101567377883020018308;
            // base conversion: mul 2**18 / 2**192
            r >>= 174;
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  GENERAL NUMBER UTILITIES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Calculates `floor(a * b / d)` with full precision.
    /// Throws if result overflows a uint256 or when `d` is zero.
    /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv
    function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // forgefmt: disable-next-item
            for {

            } 1 {

            } {
                // 512-bit multiply `[prod1 prod0] = x * y`.
                // Compute the product mod `2**256` and mod `2**256 - 1`
                // then use the Chinese Remainder Theorem to reconstruct
                // the 512 bit result. The result is stored in two 256
                // variables such that `product = prod1 * 2**256 + prod0`.

                // Least significant 256 bits of the product.
                let prod0 := mul(x, y)
                let mm := mulmod(x, y, not(0))
                // Most significant 256 bits of the product.
                let prod1 := sub(mm, add(prod0, lt(mm, prod0)))

                // Handle non-overflow cases, 256 by 256 division.
                if iszero(prod1) {
                    if iszero(d) {
                        // Store the function selector of `FullMulDivFailed()`.
                        mstore(0x00, 0xae47f702)
                        // Revert with (offset, size).
                        revert(0x1c, 0x04)
                    }
                    result := div(prod0, d)
                    break
                }

                // Make sure the result is less than `2**256`.
                // Also prevents `d == 0`.
                if iszero(gt(d, prod1)) {
                    // Store the function selector of `FullMulDivFailed()`.
                    mstore(0x00, 0xae47f702)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }

                ///////////////////////////////////////////////
                // 512 by 256 division.
                ///////////////////////////////////////////////

                // Make division exact by subtracting the remainder from `[prod1 prod0]`.
                // Compute remainder using mulmod.
                let remainder := mulmod(x, y, d)
                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
                // Factor powers of two out of `d`.
                // Compute largest power of two divisor of `d`.
                // Always greater or equal to 1.
                let twos := and(d, sub(0, d))
                // Divide d by power of two.
                d := div(d, twos)
                // Divide [prod1 prod0] by the factors of two.
                prod0 := div(prod0, twos)
                // Shift in bits from `prod1` into `prod0`. For this we need
                // to flip `twos` such that it is `2**256 / twos`.
                // If `twos` is zero, then it becomes one.
                prod0 := or(prod0, mul(prod1, add(div(sub(0, twos), twos), 1)))
                // Invert `d mod 2**256`
                // Now that `d` is an odd number, it has an inverse
                // modulo `2**256` such that `d * inv = 1 mod 2**256`.
                // Compute the inverse by starting with a seed that is correct
                // correct for four bits. That is, `d * inv = 1 mod 2**4`.
                let inv := xor(mul(3, d), 2)
                // Now use Newton-Raphson iteration to improve the precision.
                // Thanks to Hensel's lifting lemma, this also works in modular
                // arithmetic, doubling the correct bits in each step.
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128
                result := mul(prod0, mul(inv, sub(2, mul(d, inv)))) // inverse mod 2**256
                break
            }
        }
    }

    /// @dev Calculates `floor(x * y / d)` with full precision, rounded up.
    /// Throws if result overflows a uint256 or when `d` is zero.
    /// Credit to Uniswap-v3-core under MIT license:
    /// https://github.com/Uniswap/v3-core/blob/contracts/libraries/FullMath.sol
    function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
        result = fullMulDiv(x, y, d);
        /// @solidity memory-safe-assembly
        assembly {
            if mulmod(x, y, d) {
                if iszero(add(result, 1)) {
                    // Store the function selector of `FullMulDivFailed()`.
                    mstore(0x00, 0xae47f702)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
                result := add(result, 1)
            }
        }
    }

    /// @dev Returns `floor(x * y / d)`.
    /// Reverts if `x * y` overflows, or `d` is zero.
    function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
                // Store the function selector of `MulDivFailed()`.
                mstore(0x00, 0xad251c27)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            z := div(mul(x, y), d)
        }
    }

    /// @dev Returns `ceil(x * y / d)`.
    /// Reverts if `x * y` overflows, or `d` is zero.
    function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
                // Store the function selector of `MulDivFailed()`.
                mstore(0x00, 0xad251c27)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(mul(x, y), d))), div(mul(x, y), d))
        }
    }

    /// @dev Returns `ceil(x / d)`.
    /// Reverts if `d` is zero.
    function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(d) {
                // Store the function selector of `DivFailed()`.
                mstore(0x00, 0x65244e4e)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(x, d))), div(x, d))
        }
    }

    /// @dev Returns `max(0, x - y)`.
    function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(gt(x, y), sub(x, y))
        }
    }

    /// @dev Returns the square root of `x`.
    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.
            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.

            // Let `y = x / 2**r`.
            // We check `y >= 2**(k + 8)` but shift right by `k` bits
            // each branch to ensure that if `x >= 256`, then `y >= 256`.
            let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffffff, shr(r, x))))
            z := shl(shr(1, r), 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(shr(r, x), 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))
        }
    }

    /// @dev Returns the factorial of `x`.
    function factorial(uint256 x) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {

            } 1 {

            } {
                if iszero(lt(10, x)) {
                    // forgefmt: disable-next-item
                    result := and(shr(mul(22, x), 0x375f0016260009d80004ec0002d00001e0000180000180000200000400001), 0x3fffff)
                    break
                }
                if iszero(lt(57, x)) {
                    let end := 31
                    result := 8222838654177922817725562880000000
                    if iszero(lt(end, x)) {
                        end := 10
                        result := 3628800
                    }
                    for {
                        let w := not(0)
                    } 1 {

                    } {
                        result := mul(result, x)
                        x := add(x, w)
                        if eq(x, end) {
                            break
                        }
                    }
                    break
                }
                // Store the function selector of `FactorialOverflow()`.
                mstore(0x00, 0xaba0f2a2)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns the log2 of `x`.
    /// Equivalent to computing the index of the most significant bit (MSB) of `x`.
    function log2(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(x) {
                // Store the function selector of `Log2Undefined()`.
                mstore(0x00, 0x5be3aa5c)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))

            // For the remaining 32 bits, use a De Bruijn lookup.
            // See: https://graphics.stanford.edu/~seander/bithacks.html
            x := shr(r, x)
            x := or(x, shr(1, x))
            x := or(x, shr(2, x))
            x := or(x, shr(4, x))
            x := or(x, shr(8, x))
            x := or(x, shr(16, x))

            // forgefmt: disable-next-item
            r := or(r, byte(shr(251, mul(x, shl(224, 0x07c4acdd))), 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f))
        }
    }

    /// @dev Returns the log2 of `x`, rounded up.
    function log2Up(uint256 x) internal pure returns (uint256 r) {
        unchecked {
            uint256 isNotPo2;
            assembly {
                isNotPo2 := iszero(iszero(and(x, sub(x, 1))))
            }
            return log2(x) + isNotPo2;
        }
    }

    /// @dev Returns the average of `x` and `y`.
    function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = (x & y) + ((x ^ y) >> 1);
        }
    }

    /// @dev Returns the average of `x` and `y`.
    function avg(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1);
        }
    }

    /// @dev Returns the absolute value of `x`.
    function abs(int256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let mask := sub(0, shr(255, x))
            z := xor(mask, add(mask, x))
        }
    }

    /// @dev Returns the absolute distance between `x` and `y`.
    function dist(int256 x, int256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let a := sub(y, x)
            z := xor(a, mul(xor(a, sub(x, y)), sgt(x, y)))
        }
    }

    /// @dev Returns the minimum of `x` and `y`.
    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), lt(y, x)))
        }
    }

    /// @dev Returns the minimum of `x` and `y`.
    function min(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), slt(y, x)))
        }
    }

    /// @dev Returns the maximum of `x` and `y`.
    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), gt(y, x)))
        }
    }

    /// @dev Returns the maximum of `x` and `y`.
    function max(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), sgt(y, x)))
        }
    }

    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.
    function clamp(uint256 x, uint256 minValue, uint256 maxValue) internal pure returns (uint256 z) {
        z = min(max(x, minValue), maxValue);
    }

    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.
    function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {
        z = min(max(x, minValue), maxValue);
    }

    /// @dev Returns greatest common divisor of `x` and `y`.
    function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // forgefmt: disable-next-item
            for {
                z := x
            } y {

            } {
                let t := y
                y := mod(z, y)
                z := t
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   RAW NUMBER OPERATIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `x + y`, without checking for overflow.
    function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x + y;
        }
    }

    /// @dev Returns `x + y`, without checking for overflow.
    function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x + y;
        }
    }

    /// @dev Returns `x - y`, without checking for underflow.
    function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x - y;
        }
    }

    /// @dev Returns `x - y`, without checking for underflow.
    function rawSub(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x - y;
        }
    }

    /// @dev Returns `x * y`, without checking for overflow.
    function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x * y;
        }
    }

    /// @dev Returns `x * y`, without checking for overflow.
    function rawMul(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x * y;
        }
    }

    /// @dev Returns `x / y`, returning 0 if `y` is zero.
    function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := div(x, y)
        }
    }

    /// @dev Returns `x / y`, returning 0 if `y` is zero.
    function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := sdiv(x, y)
        }
    }

    /// @dev Returns `x % y`, returning 0 if `y` is zero.
    function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mod(x, y)
        }
    }

    /// @dev Returns `x % y`, returning 0 if `y` is zero.
    function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := smod(x, y)
        }
    }

    /// @dev Returns `(x + y) % d`, return 0 if `d` if zero.
    function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := addmod(x, y, d)
        }
    }

    /// @dev Returns `(x * y) % d`, return 0 if `d` if zero.
    function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mulmod(x, y, d)
        }
    }
}

File 8 of 9 : SafeTransferLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH
    /// that disallows any storage writes.
    uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    /// Multiply by a small constant (e.g. 2), if needed.
    uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` (in wei) ETH to `to`.
    /// Reverts upon failure.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, amount, 0, 0, 0, 0)) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    /// The `gasStipend` can be set to a low enough value to prevent
    /// storage writes or gas griefing.
    ///
    /// If sending via the normal procedure fails, force sends the ETH by
    /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
    ///
    /// Reverts if the current contract has insufficient balance.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // If insufficient balance, revert.
            if lt(selfbalance(), amount) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                // We can directly use `SELFDESTRUCT` in the contract creation.
                // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758
                pop(create(amount, 0x0b, 0x16))
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend
    /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default
    /// for 99% of cases and can be overriden with the three-argument version of this
    /// function if necessary.
    ///
    /// If sending via the normal procedure fails, force sends the ETH by
    /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
    ///
    /// Reverts if the current contract has insufficient balance.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        // Manually inlined because the compiler doesn't inline functions with branches.
        /// @solidity memory-safe-assembly
        assembly {
            // If insufficient balance, revert.
            if lt(selfbalance(), amount) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                // We can directly use `SELFDESTRUCT` in the contract creation.
                // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758
                pop(create(amount, 0x0b, 0x16))
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    /// The `gasStipend` can be set to a low enough value to prevent
    /// storage writes or gas griefing.
    ///
    /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend.
    ///
    /// Note: Does NOT revert upon failure.
    /// Returns whether the transfer of ETH is successful instead.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and check if it succeeded or not.
            success := call(gasStipend, to, amount, 0, 0, 0, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.

            // Store the function selector of `transferFrom(address,address,uint256)`.
            mstore(0x00, 0x23b872dd)
            mstore(0x20, from) // Store the `from` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x60, amount) // Store the `amount` argument.

            if iszero(
                and(
                    // The arguments of `and` are evaluated from right to left.
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `TransferFromFailed()`.
                mstore(0x00, 0x7939f424)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.

            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, from) // Store the `from` argument.
            if iszero(
                and(
                    // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                // Store the function selector of `TransferFromFailed()`.
                mstore(0x00, 0x7939f424)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            // Store the function selector of `transferFrom(address,address,uint256)`.
            mstore(0x00, 0x23b872dd)
            mstore(0x40, to) // Store the `to` argument.
            // The `amount` argument is already written to the memory word at 0x6a.
            amount := mload(0x60)

            if iszero(
                and(
                    // The arguments of `and` are evaluated from right to left.
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `TransferFromFailed()`.
                mstore(0x00, 0x7939f424)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1a, to) // Store the `to` argument.
            mstore(0x3a, amount) // Store the `amount` argument.
            // Store the function selector of `transfer(address,uint256)`,
            // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer).
            // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL).
            mstore(0x00, 0xa9059cbb000000000000)

            if iszero(
                and(
                    // The arguments of `and` are evaluated from right to left.
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `TransferFailed()`.
                mstore(0x00, 0x90b8ec18)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the part of the free memory pointer that was overwritten,
            // which is guaranteed to be zero, if less than 8tb of memory is used.
            mstore(0x3a, 0)
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            if iszero(
                and(
                    // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x3a, 0x20)
                )
            ) {
                // Store the function selector of `TransferFailed()`.
                mstore(0x00, 0x90b8ec18)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x1a, to) // Store the `to` argument.
            // The `amount` argument is already written to the memory word at 0x3a.
            amount := mload(0x3a)
            // Store the function selector of `transfer(address,uint256)`,
            // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer).
            // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL).
            mstore(0x00, 0xa9059cbb000000000000)

            if iszero(
                and(
                    // The arguments of `and` are evaluated from right to left.
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `TransferFailed()`.
                mstore(0x00, 0x90b8ec18)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the part of the free memory pointer that was overwritten,
            // which is guaranteed to be zero, if less than 8tb of memory is used.
            mstore(0x3a, 0)
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1a, to) // Store the `to` argument.
            mstore(0x3a, amount) // Store the `amount` argument.
            // Store the function selector of `approve(address,uint256)`,
            // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer).
            // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL).
            mstore(0x00, 0x095ea7b3000000000000)

            if iszero(
                and(
                    // The arguments of `and` are evaluated from right to left.
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `ApproveFailed()`.
                mstore(0x00, 0x3e3f8f73)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the part of the free memory pointer that was overwritten,
            // which is guaranteed to be zero, if less than 8tb of memory is used.
            mstore(0x3a, 0)
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, account) // Store the `account` argument.
            amount := mul(
                mload(0x20),
                and(
                    // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x20, 0x20)
                )
            )
        }
    }
}

File 9 of 9 : ReentrancyGuard.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.17;

/// @title ReentrancyGuard
/// @author Paul Razvan Berg
/// @notice Contract module that helps prevent reentrant calls to a function.
///
/// Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied
/// to functions to make sure there are no nested (reentrant) calls to them.
///
/// Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not
/// call one another. This can be worked around by making those functions `private`, and then adding
/// `external` `nonReentrant` entry points to them.
///
/// @dev Forked from OpenZeppelin
/// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/utils/ReentrancyGuard.sol
abstract contract ReentrancyGuard {
    /// CUSTOM ERRORS ///

    /// @notice Emitted when there is a reentrancy call.
    error ReentrantCall();

    /// PRIVATE STORAGE ///

    bool private notEntered;

    /// CONSTRUCTOR ///

    /// Storing an initial non-zero value makes deployment a bit more expensive but in exchange the
    /// refund on every call to nonReentrant will be lower in amount. Since refunds are capped to a
    /// percetange of the total transaction's gas, it is best to keep them low in cases like this one,
    /// to increase the likelihood of the full refund coming into effect.
    constructor() {
        notEntered = true;
    }

    /// MODIFIERS ///

    /// @notice Prevents a contract from calling itself, directly or indirectly.
    /// @dev Calling a `nonReentrant` function from another `nonReentrant` function
    /// is not supported. It is possible to prevent this from happening by making
    /// the `nonReentrant` function external, and make it call a `private`
    /// function that does the actual work.
    modifier nonReentrant() {
        // On the first call to nonReentrant, notEntered will be true.
        if (!notEntered) {
            revert ReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail.
        notEntered = false;

        _;

        // By storing the original value once again, a refund is triggered (https://eips.ethereum.org/EIPS/eip-2200).
        notEntered = true;
    }
}

Settings
{
  "viaIR": true,
  "optimizer": {
    "enabled": true,
    "runs": 1000000,
    "details": {
      "peephole": true,
      "inliner": true,
      "jumpdestRemover": true,
      "orderLiterals": true,
      "deduplicate": true,
      "cse": true,
      "constantOptimizer": true,
      "yulDetails": {
        "stackAllocation": true,
        "optimizerSteps": "dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul[j]Tpeulxa[rul]xa[r]cLgvifCTUca[r]LSsTOtfDnca[r]Iulc]jmul[jul]VcTOculjmul"
      }
    }
  },
  "metadata": {
    "bytecodeHash": "none"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IHangar18","name":"_hangar18","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"uint256","name":"claimAt","type":"uint256"}],"name":"CygnusDAOReserves__CantClaimCygYet","type":"error"},{"inputs":[],"name":"CygnusDAOReserves__CantRedeemAddressZero","type":"error"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"sender","type":"address"}],"name":"CygnusDAOReserves__MsgSenderNotAdmin","type":"error"},{"inputs":[],"name":"CygnusDAOReserves__MsgSenderNotHangar","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"}],"name":"CygnusDAOReserves__NotEnoughCyg","type":"error"},{"inputs":[],"name":"CygnusDAOReserves__SafeCantBeZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"shuttleId","type":"uint256"}],"name":"CygnusDAOReserves__ShuttleAlreadyInitialized","type":"error"},{"inputs":[{"internalType":"uint256","name":"shuttleId","type":"uint256"}],"name":"CygnusDAOReserves__ShuttleDoesntExist","type":"error"},{"inputs":[{"internalType":"uint256","name":"weight","type":"uint256"}],"name":"CygnusDAOReserves__WeightNotAllowed","type":"error"},{"inputs":[],"name":"CygnusDAOReserves__X1VaultCantBeZero","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"ClaimCygToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"CygTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultToken","type":"address"},{"indexed":true,"internalType":"address","name":"positions","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"FundDAOReserves","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalShuttles","type":"uint256"},{"indexed":false,"internalType":"address","name":"positions","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"FundDAOReservesAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultToken","type":"address"},{"indexed":true,"internalType":"address","name":"positions","type":"address"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"FundX1Vault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalShuttles","type":"uint256"},{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"FundX1VaultAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldSafe","type":"address"},{"indexed":false,"internalType":"address","name":"newSafe","type":"address"}],"name":"NewDAOSafe","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bool","name":"initialized","type":"bool"},{"internalType":"uint256","name":"shuttleId","type":"uint256"},{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"indexed":false,"internalType":"struct ICygnusDAOReserves.Shuttle","name":"shuttle","type":"tuple"}],"name":"NewShuttleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldVault","type":"address"},{"indexed":false,"internalType":"address","name":"newVault","type":"address"}],"name":"NewX1Vault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldWeight","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newWeight","type":"uint256"}],"name":"NewX1VaultWeight","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"SweepToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_privateBanker","type":"bool"}],"name":"SwitchPrivateBanker","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"shuttleId","type":"uint256"},{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"name":"addShuttle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allShuttles","outputs":[{"internalType":"bool","name":"initialized","type":"bool"},{"internalType":"uint256","name":"shuttleId","type":"uint256"},{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allShuttlesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"claimCygTokenDAO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cygToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cygTokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cygnusDAOSafe","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cygnusX1Vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"daoLock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"daoWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shuttleId","type":"uint256"}],"name":"fundDAOPositionsCygLP","outputs":[{"internalType":"uint256","name":"daoShares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundDAOPositionsCygLPAll","outputs":[{"internalType":"uint256","name":"daoShares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shuttleId","type":"uint256"}],"name":"fundX1VaultUSD","outputs":[{"internalType":"uint256","name":"daoShares","type":"uint256"},{"internalType":"uint256","name":"x1Assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundX1VaultUSDAll","outputs":[{"internalType":"uint256","name":"daoShares","type":"uint256"},{"internalType":"uint256","name":"x1Assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hangar18","outputs":[{"internalType":"contract IHangar18","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"privateBanker","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"setCYGToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newSafe","type":"address"}],"name":"setCygnusDAOSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_x1Vault","type":"address"}],"name":"setCygnusX1Vault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"weight","type":"uint256"}],"name":"setX1VaultWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sweepNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"sweepToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"switchPrivateBanker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usd","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"x1VaultWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c08060405234620001ea578062001ca78038038091620000218285620001ef565b8339602092839181010312620001ea57516001600160a01b038082169291838103620001ea5760019360ff19916000958084885416178755600254938185811c95168015620001df575b87861014620001cb579086939291601f86116200019c575b6004955060287f4379676e75733a2044414f20526573657276657300000000000000000000000001600255600954161760095560a0526040519283809263d63a6ccd60e01b82525afa9283156200019157849362000149575b505050608052670de0b6b3a7640000600655806005556276a700420190814211620001355750600855604051611a7d90816200022a823960805181610249015260a05181818161019601528181610953015261152a0152f35b634e487b7160e01b81526011600452602490fd5b9080929350813d831162000189575b620001648183620001ef565b8101031262000185575190811681036200018157388080620000dc565b5080fd5b8280fd5b503d62000158565b6040513d86823e3d90fd5b60028952601f858a20960160051c8601955b868110620001bd575062000083565b8981558895508201620001ae565b634e487b7160e01b88526022600452602488fd5b94607f16946200006b565b600080fd5b601f909101601f19168101906001600160401b038211908210176200021357604052565b634e487b7160e01b600052604160045260246000fdfe608060408181526004918236101561001f575b505050361561001d57005b005b600092833560e01c91826306fdde031461127457508163088906101461116c57816316dc4de6146110575781631ad4c8c314610fc55781631be1956014610f65578163326749d814610e39578163412b6d6314610de657816346866de314610d4d57816346bfbc5a14610cea5781634f4addd114610cad5781634f57368614610c5a5781636f6626f314610c1d578163728bba3314610b1257816378d837ca146108ed5781637aa724731461078a5781637ccf374b1461069c5781638f6c58e41461065f5781639bbbbb0214610536578163ab803a76146104ad578163b2f041ee14610470578163b7cd5cb41461031f578163be364cd1146102c2578163c73ef9e81461026d57508063d63a6ccd146101ff578063e58fb2ee146101be5763e8a24e1d1461014d5780610012565b346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5080fd5b50346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760209060ff6009541690519015158152f35b50346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b8284346102bf57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102bf575073ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b80fd5b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760209061031873ffffffffffffffffffffffffffffffffffffffff600754163090611a4e565b9051908152f35b8383346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5781549260ff84161561044957507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0080931682558160ff6009541661043c575b600180549461039c82611806565b83905b8782106104025750507f108a965b373d0981109fedaf413102492c0a2af803f7eaa69b7437399751db79606060209773ffffffffffffffffffffffffffffffffffffffff600354168751918252898201528787820152a182541617905551908152f35b9095839061043373ffffffffffffffffffffffffffffffffffffffff606061042a8b876118ac565b510151166118c0565b0196019061039f565b6104446114e5565b61038e565b90517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020906005549051908152f35b8383346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576104e56114e5565b478061051e575b907ff4a44a7f605c4971a27bcecb448108e6328b7fad34fab5bff4f69377294b826d918151908482526020820152a180f35b8280808084335af16104ec578363b12d13eb8452601cfd5b90503461065b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261065b5782549260ff841615610633576001600293947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00809116835560ff60095416610626575b6105b584358361149a565b5073ffffffffffffffffffffffffffffffffffffffff9586910154166105da816115fd565b9590968060035416915416917fade3bf209346b6d1156694638e3b8e94ecfddd117c76c53c26ea59898129a1c58980518a8152896020820152a482541617905582519182526020820152f35b61062e6114e5565b6105aa565b5090517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b8280fd5b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020906006549051908152f35b8383346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5782356106d76114e5565b670de0b6b3a76400009081811161075b57600654918160065581810390811161072f577fcdf0e2499be1cf2f4acff51a3c1b2e66af5d59c4d540bb5a36d9800d254a5c8094955060055582519182526020820152a180f35b6024856011887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b846024918451917f59848735000000000000000000000000000000000000000000000000000000008352820152fd5b905082346102bf57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102bf5780549060ff8216156108c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0080921681558092819260ff600954166108b8575b60019182549061080b84611806565b85905b83821061087b5750507fe29bc683c6472cac8ea38dbefc8cf71cf2e047d9cf51d0044f070025c1fc9d269173ffffffffffffffffffffffffffffffffffffffff6080925416895191825260208201528789820152866060820152a182541617905582519182526020820152f35b90969785906108ac73ffffffffffffffffffffffffffffffffffffffff8c6108a38c876118ac565b510151166115fd565b9101990197019061080e565b6108c06114e5565b6107fc565b8284517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b8383346101ba5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576024359073ffffffffffffffffffffffffffffffffffffffff90818316809303610b0e5760443590828216809203610b0a57827f0000000000000000000000000000000000000000000000000000000000000000163303610ae25780519361098760808661142a565b60019485815260208101908835825283810192835260608101948552865468010000000000000000811015610ab65780886109c5920189558861149a565b919091610a8b5792869492608097927f93a552e45a0701b212caf117ace04723a5f4137663aaa23c07cdd9dc0db05a01999795511515977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541660ff8a161782558251908201556003600282019185855116927fffffffffffffffffffffffff0000000000000000000000000000000000000000938482541617905501908487511690825416179055835196875251602087015251169084015251166060820152a180f35b602489808c7f4e487b7100000000000000000000000000000000000000000000000000000000825252fd5b60248960418c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8590517fbe7ab223000000000000000000000000000000000000000000000000000000008152fd5b8480fd5b8380fd5b8383346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5782359273ffffffffffffffffffffffffffffffffffffffff9182851691828603610b0a57610b6f6114e5565b8215610bf65750600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000811690931790555173ffffffffffffffffffffffffffffffffffffffff929091168216815292166020830152907f1ac7fff95e2a50ab5ec15d8cbfd2cf9ed10257cd022bbec16129e78496f7feba9080604081015b0390a180f35b90517f9e39ee29000000000000000000000000000000000000000000000000000000008152fd5b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020906008549051908152f35b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760209073ffffffffffffffffffffffffffffffffffffffff600754169051908152f35b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020906001549051908152f35b8390346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba573573ffffffffffffffffffffffffffffffffffffffff811681036101ba57610d4a90610d456114e5565b6118f9565b80f35b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760207f42065481224f945b66d417f15b8a593ed2b49464f94fd3071c345a483cd364b191610da96114e5565b6009549060ff821615917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060ff841691161760095551908152a180f35b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b8383346101ba57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5782356024359373ffffffffffffffffffffffffffffffffffffffff9081861691828703610f6157610e986114e5565b600854804210610f2b57506007541690610eb23083611a4e565b808511610ef6575050827fb4f44619fae7e18c058b157a3f2e33f47b66d0e2c42e2db2345371371735809b9596610ee892611a0b565b82519182526020820152a180f35b60449250848651927fd22a00510000000000000000000000000000000000000000000000000000000084528301526024820152fd5b826044918751917f6912df6a00000000000000000000000000000000000000000000000000000000835242908301526024820152fd5b8580fd5b8390346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba573573ffffffffffffffffffffffffffffffffffffffff811681036101ba57610d4a90610fc06114e5565b611978565b90503461065b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261065b5735916001548310156102bf5750611010608092600161149a565b509060ff8254169160018101549173ffffffffffffffffffffffffffffffffffffffff60038160028501541693015416928151941515855260208501528301526060820152f35b8284346102bf5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102bf57805460ff81161561114457906001600393926110d86020967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00809316855560ff60095416611137575b358361149a565b5073ffffffffffffffffffffffffffffffffffffffff9586910154166110fd816118c0565b9560035416907fb39a15ac1082534c5f6687437f0fd4ba55c34a96fd7231c683045c7d9f7bd115888751898152a382541617905551908152f35b61113f6114e5565b6110d1565b5050517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b8383346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5773ffffffffffffffffffffffffffffffffffffffff90833582811691828203610b0a576111c86114e5565b821561124c5785547fffffffffffffffffffffffff00000000000000000000000000000000000000008116909317909555935173ffffffffffffffffffffffffffffffffffffffff929091168216815292166020830152907fee536cbb080de2a8340fafaee947799b653dff18ad502b7f85dec917aa90dd88908060408101610bf0565b8590517f555681a5000000000000000000000000000000000000000000000000000000008152fd5b915092346102bf57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102bf5780600254600181811c918181168015611420575b60209889851082146113f457509183918995938895865290816000146113b45750600114611358575b50506112f4925095939295038261142a565b82519382859384528251928382860152825b84811061134257505050828201840152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168101030190f35b8181018301518882018801528795508201611306565b600286527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9492508591905b81831061139c5750889450508201016112f4386112e2565b85548884018501529485019487945091830191611384565b90506112f49593507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201018692386112e2565b8660226024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b92607f16926112b9565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761146b57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80548210156114b65760005260206000209060021b0190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040517ff851a44000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90602081600481857f0000000000000000000000000000000000000000000000000000000000000000165afa9081156115f1576000916115b7575b5090811633036115685750565b6040517f30a76f5f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff919091166004820152336024820152604490fd5b6020813d82116115e9575b816115cf6020938361142a565b810103126101ba57519082821682036102bf57503861155b565b3d91506115c2565b6040513d6000823e3d90fd5b906000906000928373ffffffffffffffffffffffffffffffffffffffff918281169586156117dc57863b1561065b576040517ffff6cae90000000000000000000000000000000000000000000000000000000081528381600481838c5af180156117d1579084916117bf575b50506116753083611a4e565b600654807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821181026117b257670de0b6b3a764000090820204918282039482861161178557508498836116e1575b5050036116d157505050565b6116df926003541690611a0b565b565b819298506020906064886004541660405194859384927fba08765200000000000000000000000000000000000000000000000000000000845289600485015260248401523060448401525af1918215611779578092611745575b50509538806116c5565b9091506020823d8211611771575b816117606020938361142a565b810103126102bf575051388061173b565b3d9150611753565b604051903d90823e3d90fd5b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b63bac65e5b83526004601cfd5b6117c9925061142a565b818238611669565b6040513d86823e3d90fd5b60046040517f5e2b2a53000000000000000000000000000000000000000000000000000000008152fd5b90815467ffffffffffffffff811161146b57604092835193602090611830828560051b018761142a565b8386526000928352818320908287015b85851061184f57505050505050565b600484600192845161186260808261142a565b60ff87541615158152848701548382015273ffffffffffffffffffffffffffffffffffffffff80600289015416878301526003880154166060820152815201930194019391611840565b80518210156114b65760209160051b010190565b906118cb3083611a4e565b9182806118d6575050565b6116df9173ffffffffffffffffffffffffffffffffffffffff6003541690611a0b565b6007549073ffffffffffffffffffffffffffffffffffffffff90818316611973577f9ef3a7e4c0fb35b248d2c9abf2c719f4c6167ce66b765d4c64e1e4aa1716bf35926020927fffffffffffffffffffffffff000000000000000000000000000000000000000092169182911617600755604051908152a1565b505050565b60075473ffffffffffffffffffffffffffffffffffffffff828116929116828114908115611a02575b506119fe577ff4a44a7f605c4971a27bcecb448108e6328b7fad34fab5bff4f69377294b826d916040916119d53082611a4e565b9081806119ec575b505082519182526020820152a1565b6119f7913390611a0b565b38816119dd565b5050565b905015386119a1565b601692602092601a52603a52604460009384809369a9059cbb00000000000082525af13d156001835114171615611a4157603a52565b6390b8ec1890526004601cfd5b6024601c6020939284936370a0823160005284525afa601f3d1116602051029056fea164736f6c6343000811000a0000000000000000000000008796747946871b6b8ea495cce8d7814b17959296

Deployed Bytecode

0x608060408181526004918236101561001f575b505050361561001d57005b005b600092833560e01c91826306fdde031461127457508163088906101461116c57816316dc4de6146110575781631ad4c8c314610fc55781631be1956014610f65578163326749d814610e39578163412b6d6314610de657816346866de314610d4d57816346bfbc5a14610cea5781634f4addd114610cad5781634f57368614610c5a5781636f6626f314610c1d578163728bba3314610b1257816378d837ca146108ed5781637aa724731461078a5781637ccf374b1461069c5781638f6c58e41461065f5781639bbbbb0214610536578163ab803a76146104ad578163b2f041ee14610470578163b7cd5cb41461031f578163be364cd1146102c2578163c73ef9e81461026d57508063d63a6ccd146101ff578063e58fb2ee146101be5763e8a24e1d1461014d5780610012565b346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008796747946871b6b8ea495cce8d7814b17959296168152f35b5080fd5b50346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760209060ff6009541690519015158152f35b50346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000037eaa0ef3549a5bb7d431be78a3d99bd360d19e5168152f35b8284346102bf57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102bf575073ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b80fd5b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760209061031873ffffffffffffffffffffffffffffffffffffffff600754163090611a4e565b9051908152f35b8383346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5781549260ff84161561044957507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0080931682558160ff6009541661043c575b600180549461039c82611806565b83905b8782106104025750507f108a965b373d0981109fedaf413102492c0a2af803f7eaa69b7437399751db79606060209773ffffffffffffffffffffffffffffffffffffffff600354168751918252898201528787820152a182541617905551908152f35b9095839061043373ffffffffffffffffffffffffffffffffffffffff606061042a8b876118ac565b510151166118c0565b0196019061039f565b6104446114e5565b61038e565b90517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020906005549051908152f35b8383346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576104e56114e5565b478061051e575b907ff4a44a7f605c4971a27bcecb448108e6328b7fad34fab5bff4f69377294b826d918151908482526020820152a180f35b8280808084335af16104ec578363b12d13eb8452601cfd5b90503461065b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261065b5782549260ff841615610633576001600293947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00809116835560ff60095416610626575b6105b584358361149a565b5073ffffffffffffffffffffffffffffffffffffffff9586910154166105da816115fd565b9590968060035416915416917fade3bf209346b6d1156694638e3b8e94ecfddd117c76c53c26ea59898129a1c58980518a8152896020820152a482541617905582519182526020820152f35b61062e6114e5565b6105aa565b5090517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b8280fd5b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020906006549051908152f35b8383346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5782356106d76114e5565b670de0b6b3a76400009081811161075b57600654918160065581810390811161072f577fcdf0e2499be1cf2f4acff51a3c1b2e66af5d59c4d540bb5a36d9800d254a5c8094955060055582519182526020820152a180f35b6024856011887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b846024918451917f59848735000000000000000000000000000000000000000000000000000000008352820152fd5b905082346102bf57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102bf5780549060ff8216156108c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0080921681558092819260ff600954166108b8575b60019182549061080b84611806565b85905b83821061087b5750507fe29bc683c6472cac8ea38dbefc8cf71cf2e047d9cf51d0044f070025c1fc9d269173ffffffffffffffffffffffffffffffffffffffff6080925416895191825260208201528789820152866060820152a182541617905582519182526020820152f35b90969785906108ac73ffffffffffffffffffffffffffffffffffffffff8c6108a38c876118ac565b510151166115fd565b9101990197019061080e565b6108c06114e5565b6107fc565b8284517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b8383346101ba5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576024359073ffffffffffffffffffffffffffffffffffffffff90818316809303610b0e5760443590828216809203610b0a57827f0000000000000000000000008796747946871b6b8ea495cce8d7814b17959296163303610ae25780519361098760808661142a565b60019485815260208101908835825283810192835260608101948552865468010000000000000000811015610ab65780886109c5920189558861149a565b919091610a8b5792869492608097927f93a552e45a0701b212caf117ace04723a5f4137663aaa23c07cdd9dc0db05a01999795511515977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541660ff8a161782558251908201556003600282019185855116927fffffffffffffffffffffffff0000000000000000000000000000000000000000938482541617905501908487511690825416179055835196875251602087015251169084015251166060820152a180f35b602489808c7f4e487b7100000000000000000000000000000000000000000000000000000000825252fd5b60248960418c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8590517fbe7ab223000000000000000000000000000000000000000000000000000000008152fd5b8480fd5b8380fd5b8383346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5782359273ffffffffffffffffffffffffffffffffffffffff9182851691828603610b0a57610b6f6114e5565b8215610bf65750600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000811690931790555173ffffffffffffffffffffffffffffffffffffffff929091168216815292166020830152907f1ac7fff95e2a50ab5ec15d8cbfd2cf9ed10257cd022bbec16129e78496f7feba9080604081015b0390a180f35b90517f9e39ee29000000000000000000000000000000000000000000000000000000008152fd5b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020906008549051908152f35b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760209073ffffffffffffffffffffffffffffffffffffffff600754169051908152f35b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba576020906001549051908152f35b8390346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba573573ffffffffffffffffffffffffffffffffffffffff811681036101ba57610d4a90610d456114e5565b6118f9565b80f35b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760207f42065481224f945b66d417f15b8a593ed2b49464f94fd3071c345a483cd364b191610da96114e5565b6009549060ff821615917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060ff841691161760095551908152a180f35b5050346101ba57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b8383346101ba57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5782356024359373ffffffffffffffffffffffffffffffffffffffff9081861691828703610f6157610e986114e5565b600854804210610f2b57506007541690610eb23083611a4e565b808511610ef6575050827fb4f44619fae7e18c058b157a3f2e33f47b66d0e2c42e2db2345371371735809b9596610ee892611a0b565b82519182526020820152a180f35b60449250848651927fd22a00510000000000000000000000000000000000000000000000000000000084528301526024820152fd5b826044918751917f6912df6a00000000000000000000000000000000000000000000000000000000835242908301526024820152fd5b8580fd5b8390346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba573573ffffffffffffffffffffffffffffffffffffffff811681036101ba57610d4a90610fc06114e5565b611978565b90503461065b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261065b5735916001548310156102bf5750611010608092600161149a565b509060ff8254169160018101549173ffffffffffffffffffffffffffffffffffffffff60038160028501541693015416928151941515855260208501528301526060820152f35b8284346102bf5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102bf57805460ff81161561114457906001600393926110d86020967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00809316855560ff60095416611137575b358361149a565b5073ffffffffffffffffffffffffffffffffffffffff9586910154166110fd816118c0565b9560035416907fb39a15ac1082534c5f6687437f0fd4ba55c34a96fd7231c683045c7d9f7bd115888751898152a382541617905551908152f35b61113f6114e5565b6110d1565b5050517f37ed32e8000000000000000000000000000000000000000000000000000000008152fd5b8383346101ba5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ba5773ffffffffffffffffffffffffffffffffffffffff90833582811691828203610b0a576111c86114e5565b821561124c5785547fffffffffffffffffffffffff00000000000000000000000000000000000000008116909317909555935173ffffffffffffffffffffffffffffffffffffffff929091168216815292166020830152907fee536cbb080de2a8340fafaee947799b653dff18ad502b7f85dec917aa90dd88908060408101610bf0565b8590517f555681a5000000000000000000000000000000000000000000000000000000008152fd5b915092346102bf57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102bf5780600254600181811c918181168015611420575b60209889851082146113f457509183918995938895865290816000146113b45750600114611358575b50506112f4925095939295038261142a565b82519382859384528251928382860152825b84811061134257505050828201840152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168101030190f35b8181018301518882018801528795508201611306565b600286527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9492508591905b81831061139c5750889450508201016112f4386112e2565b85548884018501529485019487945091830191611384565b90506112f49593507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201018692386112e2565b8660226024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b92607f16926112b9565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761146b57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80548210156114b65760005260206000209060021b0190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040517ff851a44000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90602081600481857f0000000000000000000000008796747946871b6b8ea495cce8d7814b17959296165afa9081156115f1576000916115b7575b5090811633036115685750565b6040517f30a76f5f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff919091166004820152336024820152604490fd5b6020813d82116115e9575b816115cf6020938361142a565b810103126101ba57519082821682036102bf57503861155b565b3d91506115c2565b6040513d6000823e3d90fd5b906000906000928373ffffffffffffffffffffffffffffffffffffffff918281169586156117dc57863b1561065b576040517ffff6cae90000000000000000000000000000000000000000000000000000000081528381600481838c5af180156117d1579084916117bf575b50506116753083611a4e565b600654807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821181026117b257670de0b6b3a764000090820204918282039482861161178557508498836116e1575b5050036116d157505050565b6116df926003541690611a0b565b565b819298506020906064886004541660405194859384927fba08765200000000000000000000000000000000000000000000000000000000845289600485015260248401523060448401525af1918215611779578092611745575b50509538806116c5565b9091506020823d8211611771575b816117606020938361142a565b810103126102bf575051388061173b565b3d9150611753565b604051903d90823e3d90fd5b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b63bac65e5b83526004601cfd5b6117c9925061142a565b818238611669565b6040513d86823e3d90fd5b60046040517f5e2b2a53000000000000000000000000000000000000000000000000000000008152fd5b90815467ffffffffffffffff811161146b57604092835193602090611830828560051b018761142a565b8386526000928352818320908287015b85851061184f57505050505050565b600484600192845161186260808261142a565b60ff87541615158152848701548382015273ffffffffffffffffffffffffffffffffffffffff80600289015416878301526003880154166060820152815201930194019391611840565b80518210156114b65760209160051b010190565b906118cb3083611a4e565b9182806118d6575050565b6116df9173ffffffffffffffffffffffffffffffffffffffff6003541690611a0b565b6007549073ffffffffffffffffffffffffffffffffffffffff90818316611973577f9ef3a7e4c0fb35b248d2c9abf2c719f4c6167ce66b765d4c64e1e4aa1716bf35926020927fffffffffffffffffffffffff000000000000000000000000000000000000000092169182911617600755604051908152a1565b505050565b60075473ffffffffffffffffffffffffffffffffffffffff828116929116828114908115611a02575b506119fe577ff4a44a7f605c4971a27bcecb448108e6328b7fad34fab5bff4f69377294b826d916040916119d53082611a4e565b9081806119ec575b505082519182526020820152a1565b6119f7913390611a0b565b38816119dd565b5050565b905015386119a1565b601692602092601a52603a52604460009384809369a9059cbb00000000000082525af13d156001835114171615611a4157603a52565b6390b8ec1890526004601cfd5b6024601c6020939284936370a0823160005284525afa601f3d1116602051029056fea164736f6c6343000811000a

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

0000000000000000000000008796747946871b6b8ea495cce8d7814b17959296

-----Decoded View---------------
Arg [0] : _hangar18 (address): 0x8796747946871B6b8ea495CCE8d7814b17959296

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000008796747946871b6b8ea495cce8d7814b17959296


Block Transaction Gas Used Reward
view all blocks sequenced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.