ETH Price: $2,316.21 (-2.75%)
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Viewer

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 500 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity 0.8.20;

import {SignedMath} from "@openzeppelin/contracts/utils/math/SignedMath.sol";
import {DecimalMath} from "../libraries/DecimalMath.sol";
import {IFlatcoinVault} from "../interfaces/IFlatcoinVault.sol";
import {ILeverageModule} from "../interfaces/ILeverageModule.sol";
import {IStableModule} from "../interfaces/IStableModule.sol";
import {IOracleModule} from "../interfaces/IOracleModule.sol";
import {ILiquidationModule} from "../interfaces/ILiquidationModule.sol";
import {ILimitOrder} from "../interfaces/ILimitOrder.sol";
import {FlatcoinStructs} from "../libraries/FlatcoinStructs.sol";
import {FlatcoinModuleKeys} from "../libraries/FlatcoinModuleKeys.sol";

/// @title Viewer contract for Flatcoin
/// @notice Contains functions to view details about Flatcoin and related data.
/// @dev Should only be used by 3rd party integrations and frontends.
contract Viewer {
    using SignedMath for int256;
    using DecimalMath for int256;

    IFlatcoinVault public vault;

    constructor(IFlatcoinVault _vault) {
        vault = _vault;
    }

    /////////////////////////////////////////////
    //             View Functions              //
    /////////////////////////////////////////////

    function getAccountLeveragePositionData(
        address account
    ) external view returns (FlatcoinStructs.LeveragePositionData[] memory positionData) {
        ILeverageModule leverageModule = ILeverageModule(vault.moduleAddress(FlatcoinModuleKeys._LEVERAGE_MODULE_KEY));

        uint256 balance = leverageModule.balanceOf(account);
        positionData = new FlatcoinStructs.LeveragePositionData[](balance);

        for (uint256 i = 0; i < balance; i++) {
            uint256 tokenId = leverageModule.tokenOfOwnerByIndex(account, i);
            positionData[i] = getPositionData(tokenId);
        }
    }

    /// @notice Returns leverage position data for a range of position IDs
    /// @dev For a closed position, the token is burned and position data will be 0
    function getPositionData(
        uint256 tokenIdFrom,
        uint256 tokenIdTo
    ) external view returns (FlatcoinStructs.LeveragePositionData[] memory positionData) {
        uint256 length = tokenIdTo - tokenIdFrom + 1;
        positionData = new FlatcoinStructs.LeveragePositionData[](length);

        for (uint256 i = 0; i < length; i++) {
            positionData[i] = getPositionData(i + tokenIdFrom);
        }
    }

    /// @notice Returns leverage position data for a specific position ID
    /// @dev For a closed position, the token is burned and position data will be 0
    function getPositionData(
        uint256 tokenId
    ) public view returns (FlatcoinStructs.LeveragePositionData memory positionData) {
        ILeverageModule leverageModule = ILeverageModule(vault.moduleAddress(FlatcoinModuleKeys._LEVERAGE_MODULE_KEY));
        ILiquidationModule liquidationModule = ILiquidationModule(
            vault.moduleAddress(FlatcoinModuleKeys._LIQUIDATION_MODULE_KEY)
        );
        ILimitOrder limitOrderModule = ILimitOrder(vault.moduleAddress(FlatcoinModuleKeys._LIMIT_ORDER_KEY));

        FlatcoinStructs.Position memory position = vault.getPosition(tokenId);
        FlatcoinStructs.PositionSummary memory positionSummary = leverageModule.getPositionSummary(tokenId);

        uint256 limitOrderPriceLowerThreshold;
        uint256 limitOrderPriceUpperThreshold;

        {
            FlatcoinStructs.Order memory order = limitOrderModule.getLimitOrder(tokenId);

            if (order.orderType == FlatcoinStructs.OrderType.LimitClose) {
                FlatcoinStructs.LimitClose memory limitClose = abi.decode(
                    order.orderData,
                    (FlatcoinStructs.LimitClose)
                );

                limitOrderPriceLowerThreshold = limitClose.priceLowerThreshold;
                limitOrderPriceUpperThreshold = limitClose.priceUpperThreshold;
            }
        }

        uint256 liquidationPrice = liquidationModule.liquidationPrice(tokenId);

        positionData = FlatcoinStructs.LeveragePositionData({
            tokenId: tokenId,
            averagePrice: position.averagePrice,
            marginDeposited: position.marginDeposited,
            additionalSize: position.additionalSize,
            entryCumulativeFunding: position.entryCumulativeFunding,
            profitLoss: positionSummary.profitLoss,
            accruedFunding: positionSummary.accruedFunding,
            marginAfterSettlement: positionSummary.marginAfterSettlement,
            liquidationPrice: liquidationPrice,
            limitOrderPriceLowerThreshold: limitOrderPriceLowerThreshold,
            limitOrderPriceUpperThreshold: limitOrderPriceUpperThreshold
        });
    }

    function getFlatcoinTVL() external view returns (uint256 tvl) {
        IOracleModule oracleModule = IOracleModule(vault.moduleAddress(FlatcoinModuleKeys._ORACLE_MODULE_KEY));
        IStableModule stableModule = IStableModule(vault.moduleAddress(FlatcoinModuleKeys._STABLE_MODULE_KEY));
        FlatcoinStructs.VaultSummary memory vaultSummary = vault.getVaultSummary();

        (uint256 price, ) = oracleModule.getPrice();
        tvl = (vaultSummary.stableCollateralTotal * price) / (10 ** stableModule.decimals());
    }

    /// @notice Returns the market skew in percentage terms.
    /// @return skewPercent The market skew in percentage terms [-1e18, (1 - skewFractionMax)*1e18].
    /// @dev When the `skewPercent` is -1e18 it means the market is fully skewed towards stable LPs.
    ///      When the `skewPercent` is (1 - skewFractionMax)*1e18 it means the market is skewed max towards leverage LPs.
    ///      When the `skewPercent` is 0 it means the market is either perfectly hedged or there is no stable collateral.
    /// @dev Note that this `skewPercent` is relative to the stable collateral.
    ///      So it's max value is (1 - skewFractionMax)*1e18. For example, if the `skewFractionMax` is 1.2e18,
    ///      the max value of `skewPercent` is 0.2e18. This means that the market is skewed 20% towards leverage LPs
    ///      relative to the stable collateral.
    function getMarketSkewPercentage() external view returns (int256 skewPercent) {
        FlatcoinStructs.VaultSummary memory vaultSummary = vault.getVaultSummary();

        int256 marketSkew = vault.getCurrentSkew();
        uint256 stableCollateralTotal = vaultSummary.stableCollateralTotal;

        // Technically, the market skew is undefined when there are no open positions.
        // Since no leverage position can be opened when there is no stable collateral in the vault,
        // it also means stable collateral == leverage long margin and hence no skew.
        if (stableCollateralTotal == 0) {
            return 0;
        } else {
            return marketSkew._divideDecimal(int256(stableCollateralTotal));
        }
    }

    function getFlatcoinPriceInUSD() external view returns (uint256 priceInUSD) {
        IStableModule stableModule = IStableModule(vault.moduleAddress(FlatcoinModuleKeys._STABLE_MODULE_KEY));
        uint256 tokenPriceInCollateral = stableModule.stableCollateralPerShare();
        (uint256 collateralPriceInUSD, ) = IOracleModule(vault.moduleAddress(FlatcoinModuleKeys._ORACLE_MODULE_KEY))
            .getPrice();

        priceInUSD = (tokenPriceInCollateral * collateralPriceInUSD) / (10 ** stableModule.decimals());
    }
}

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

pragma solidity ^0.8.20;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

/// @title DecimalMath
/// @author dHEDGE
/// @author Adapted from Synthetix <https://github.com/Synthetixio/synthetix/blob/cbd8666f4331ee95fcc667ec7345d13c8ba77efb/contracts/SignedSafeDecimalMath.sol>
///         and  <https://github.com/Synthetixio/synthetix/blob/cbd8666f4331ee95fcc667ec7345d13c8ba77efb/contracts/SafeDecimalMath.sol>
/// @notice Library for fixed point math.
// TODO: Explore if Solmate FixedPointMathLib can be used instead. <https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol>
// solhint-disable gas-named-return-values
library DecimalMath {
    /* Number of decimal places in the representations. */
    uint8 public constant DECIMALS = 18;
    uint8 public constant HIGH_PRECISION_DECIMALS = 27;

    /* The number representing 1.0. */
    int256 public constant UNIT = 1e18;

    /* The number representing 1.0 for higher fidelity numbers. */
    int256 public constant PRECISE_UNIT = int256(10 ** uint256(HIGH_PRECISION_DECIMALS));
    int256 private constant _UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR =
        int256(10 ** uint256(HIGH_PRECISION_DECIMALS - DECIMALS));

    /**
     * @return The result of multiplying x and y, interpreting the operands as fixed-point
     * decimals.
     *
     * @dev A unit factor is divided out after the product of x and y is evaluated,
     * so that product must be less than 2**256. As this is an integer division,
     * the internal division always rounds down. This helps save on gas. Rounding
     * is more expensive on gas.
     */
    function _multiplyDecimal(int256 x, int256 y) internal pure returns (int256) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        return (x * y) / UNIT;
    }

    /**
     * @return The result of multiplying x and y, interpreting the operands as fixed-point
     * decimals.
     *
     * @dev A unit factor is divided out after the product of x and y is evaluated,
     * so that product must be less than 2**256. As this is an integer division,
     * the internal division always rounds down. This helps save on gas. Rounding
     * is more expensive on gas.
     */
    function _multiplyDecimal(uint256 x, uint256 y) internal pure returns (uint256) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        return (x * y) / uint256(UNIT);
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a precise unit.
     *
     * @dev The operands should be in the precise unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRoundPrecise(int256 x, int256 y) internal pure returns (int256) {
        return _multiplyDecimalRound(x, y, PRECISE_UNIT);
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a precise unit.
     *
     * @dev The operands should be in the precise unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRoundPrecise(uint256 x, uint256 y) internal pure returns (uint256) {
        return _multiplyDecimalRound(x, y, uint256(PRECISE_UNIT));
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a standard unit.
     *
     * @dev The operands should be in the standard unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRound(int256 x, int256 y) internal pure returns (int256) {
        return _multiplyDecimalRound(x, y, UNIT);
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a standard unit.
     *
     * @dev The operands should be in the standard unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRound(uint256 x, uint256 y) internal pure returns (uint256) {
        return _multiplyDecimalRound(x, y, uint256(UNIT));
    }

    /**
     * @return The result of safely dividing x and y. The return value is a high
     * precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and UNIT must be less than 2**256. As
     * this is an integer division, the result is always rounded down.
     * This helps save on gas. Rounding is more expensive on gas.
     */
    function _divideDecimal(int256 x, int256 y) internal pure returns (int256) {
        /* Reintroduce the UNIT factor that will be divided out by y. */
        return (x * UNIT) / y;
    }

    /**
     * @return The result of safely dividing x and y. The return value is a high
     * precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and UNIT must be less than 2**256. As
     * this is an integer division, the result is always rounded down.
     * This helps save on gas. Rounding is more expensive on gas.
     */
    function _divideDecimal(uint256 x, uint256 y) internal pure returns (uint256) {
        /* Reintroduce the UNIT factor that will be divided out by y. */
        return (x * uint256(UNIT)) / y;
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * standard precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and the standard precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function _divideDecimalRound(int256 x, int256 y) internal pure returns (int256) {
        return _divideDecimalRound(x, y, UNIT);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * high precision decimal.
     *
     * @dev y is divided after the product of x and the high precision unit
     * is evaluated, so the product of x and the high precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function _divideDecimalRoundPrecise(int256 x, int256 y) internal pure returns (int256) {
        return _divideDecimalRound(x, y, PRECISE_UNIT);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * high precision decimal.
     *
     * @dev y is divided after the product of x and the high precision unit
     * is evaluated, so the product of x and the high precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function _divideDecimalRoundPrecise(uint256 x, uint256 y) internal pure returns (uint256) {
        return _divideDecimalRound(x, y, uint256(PRECISE_UNIT));
    }

    /**
     * @dev Convert a standard decimal representation to a high precision one.
     */
    function _decimalToPreciseDecimal(int256 i) internal pure returns (int256) {
        return i * _UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR;
    }

    /**
     * @dev Convert a standard decimal representation to a high precision one.
     */
    function _decimalToPreciseDecimal(uint256 i) internal pure returns (uint256) {
        return i * uint256(_UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
    }

    /**
     * @dev Convert a high precision decimal to a standard decimal representation.
     */
    function _preciseDecimalToDecimal(int256 i) internal pure returns (int256) {
        int256 quotientTimesTen = i / (_UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);
        return _roundDividingByTen(quotientTimesTen);
    }

    /**
     * @dev Convert a high precision decimal to a standard decimal representation.
     */
    function _preciseDecimalToDecimal(uint256 i) internal pure returns (uint256) {
        uint256 quotientTimesTen = i / (uint256(_UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR) / 10);

        if (quotientTimesTen % 10 >= 5) {
            quotientTimesTen += 10;
        }

        return quotientTimesTen / 10;
    }

    /**
     * @dev Rounds an input with an extra zero of precision, returning the result without the extra zero.
     * Half increments round away from zero; positive numbers at a half increment are rounded up,
     * while negative such numbers are rounded down. This behaviour is designed to be consistent with the
     * unsigned version of this library (SafeDecimalMath).
     */
    function _roundDividingByTen(int256 valueTimesTen) private pure returns (int256) {
        int256 increment;
        if (valueTimesTen % 10 >= 5) {
            increment = 10;
        } else if (valueTimesTen % 10 <= -5) {
            increment = -10;
        }
        return (valueTimesTen + increment) / 10;
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of the specified precision unit.
     *
     * @dev The operands should be in the form of a the specified unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRound(int256 x, int256 y, int256 precisionUnit) private pure returns (int256) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        int256 quotientTimesTen = (x * y) / (precisionUnit / 10);
        return _roundDividingByTen(quotientTimesTen);
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of the specified precision unit.
     *
     * @dev The operands should be in the form of a the specified unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRound(uint256 x, uint256 y, uint256 precisionUnit) private pure returns (uint256) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        uint256 quotientTimesTen = (x * y) / (precisionUnit / 10);

        if (quotientTimesTen % 10 >= 5) {
            quotientTimesTen += 10;
        }

        return quotientTimesTen / 10;
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * decimal in the precision unit specified in the parameter.
     *
     * @dev y is divided after the product of x and the specified precision unit
     * is evaluated, so the product of x and the specified precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function _divideDecimalRound(int256 x, int256 y, int256 precisionUnit) private pure returns (int256) {
        int256 resultTimesTen = (x * precisionUnit * 10) / y;
        return _roundDividingByTen(resultTimesTen);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * decimal in the precision unit specified in the parameter.
     *
     * @dev y is divided after the product of x and the specified precision unit
     * is evaluated, so the product of x and the specified precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function _divideDecimalRound(uint256 x, uint256 y, uint256 precisionUnit) private pure returns (uint256) {
        uint256 resultTimesTen = (x * (precisionUnit * 10)) / y;

        if (resultTimesTen % 10 >= 5) {
            resultTimesTen += 10;
        }

        return resultTimesTen / 10;
    }
}

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {FlatcoinStructs} from "../libraries/FlatcoinStructs.sol";

interface IFlatcoinVault {
    function collateral() external view returns (IERC20 collateral);

    function lastRecomputedFundingTimestamp() external view returns (uint64 lastRecomputedFundingTimestamp);

    function minExecutabilityAge() external view returns (uint64 minExecutabilityAge);

    function maxExecutabilityAge() external view returns (uint64 maxExecutabilityAge);

    function lastRecomputedFundingRate() external view returns (int256 lastRecomputedFundingRate);

    function cumulativeFundingRate() external view returns (int256 cumulativeFundingRate);

    function maxFundingVelocity() external view returns (uint256 maxFundingVelocity);

    function maxVelocitySkew() external view returns (uint256 maxVelocitySkew);

    function stableCollateralTotal() external view returns (uint256 totalAmount);

    function skewFractionMax() external view returns (uint256 skewFractionMax);

    function moduleAddress(bytes32 _moduleKey) external view returns (address moduleAddress);

    function isAuthorizedModule(address _address) external view returns (bool status);

    function isModulePaused(bytes32 moduleKey) external view returns (bool paused);

    function sendCollateral(address to, uint256 amount) external;

    function getVaultSummary() external view returns (FlatcoinStructs.VaultSummary memory _vaultSummary);

    function getGlobalPositions() external view returns (FlatcoinStructs.GlobalPositions memory _globalPositions);

    function setPosition(FlatcoinStructs.Position memory _position, uint256 _tokenId) external;

    function updateGlobalPositionData(uint256 price, int256 marginDelta, int256 additionalSizeDelta) external;

    function updateStableCollateralTotal(int256 _stableCollateralAdjustment) external;

    function addAuthorizedModules(FlatcoinStructs.AuthorizedModule[] calldata _modules) external;

    function addAuthorizedModule(FlatcoinStructs.AuthorizedModule calldata _module) external;

    function removeAuthorizedModule(bytes32 _moduleKey) external;

    function deletePosition(uint256 _tokenId) external;

    function settleFundingFees() external returns (int256 fundingFees);

    function getCurrentFundingRate() external view returns (int256 fundingRate);

    function getPosition(uint256 _tokenId) external view returns (FlatcoinStructs.Position memory position);

    function checkSkewMax(uint256 sizeChange, int256 stableCollateralChange) external view;

    function checkCollateralCap(uint256 depositAmount) external view;

    function stableCollateralCap() external view returns (uint256 collateralCap);

    function getCurrentSkew() external view returns (int256 skew);
}

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.20;

import {IERC721Enumerable} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import {FlatcoinStructs} from "../libraries/FlatcoinStructs.sol";

interface ILeverageModule is IERC721Enumerable {
    function executeOpen(
        address account,
        address keeper,
        FlatcoinStructs.Order calldata order
    ) external returns (uint256 newTokenId);

    function executeAdjust(address account, address keeper, FlatcoinStructs.Order calldata order) external;

    function executeClose(
        address account,
        address keeper,
        FlatcoinStructs.Order calldata order
    ) external returns (int256 settledMargin);

    function burn(uint256 tokenId, bytes32 moduleKey) external;

    function lock(uint256 tokenId, bytes32 moduleKey) external;

    function unlock(uint256 tokenId, bytes32 moduleKey) external;

    function isLocked(uint256 tokenId) external view returns (bool lockStatus);

    function isLockedByModule(uint256 _tokenId, bytes32 _moduleKey) external view returns (bool _lockedByModuleStatus);

    function getPositionSummary(
        uint256 tokenId
    ) external view returns (FlatcoinStructs.PositionSummary memory positionSummary);

    function fundingAdjustedLongPnLTotal() external view returns (int256 _fundingAdjustedPnL);

    function fundingAdjustedLongPnLTotal(uint32 maxAge) external view returns (int256 _fundingAdjustedPnL);

    function tokenIdNext() external view returns (uint256 tokenId);

    function leverageTradingFee() external view returns (uint256 leverageTradingFee);

    function checkLeverageCriteria(uint256 margin, uint256 size) external view;

    function marginMin() external view returns (uint256 marginMin);

    function getTradeFee(uint256 size) external view returns (uint256 tradeFee);
}

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.20;

import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {FlatcoinStructs} from "../libraries/FlatcoinStructs.sol";

interface IStableModule is IERC20Metadata {
    function stableCollateralPerShare() external view returns (uint256 collateralPerShare);

    function executeDeposit(
        address account,
        uint64 executableAtTime,
        FlatcoinStructs.AnnouncedStableDeposit calldata announcedDeposit
    ) external returns (uint256 liquidityMinted);

    function executeWithdraw(
        address account,
        uint64 executableAtTime,
        FlatcoinStructs.AnnouncedStableWithdraw calldata announcedWithdraw
    ) external returns (uint256 amountOut, uint256 withdrawFee);

    function stableWithdrawFee() external view returns (uint256 stableWithdrawFee);

    function stableDepositQuote(uint256 depositAmount) external view returns (uint256 amountOut);

    function stableWithdrawQuote(uint256 withdrawAmount) external view returns (uint256 amountOut);

    function lock(address account, uint256 amount) external;

    function unlock(address account, uint256 amount) external;

    function getLockedAmount(address account) external view returns (uint256 amountLocked);
}

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.20;

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

interface IOracleModule {
    function onchainOracle() external view returns (IChainlinkAggregatorV3 oracleContract, uint32 maxAge);

    function getPrice() external view returns (uint256 price, uint256 timestamp);

    function getPrice(uint32 maxAge) external view returns (uint256 price, uint256 timestamp);

    function updatePythPrice(address sender, bytes[] calldata priceUpdateData) external payable;
}

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.20;

interface ILiquidationModule {
    function canLiquidate(uint256 tokenId) external view returns (bool liquidatable);

    function canLiquidate(uint256 tokenId, uint256 price) external view returns (bool liquidatable);

    function getLiquidationFee(uint256 tokenId) external view returns (uint256 liquidationFee);

    function getLiquidationMargin(uint256 additionalSize) external view returns (uint256 liquidationMargin);

    function getLiquidationMargin(
        uint256 additionalSize,
        uint256 price
    ) external view returns (uint256 liquidationMargin);

    function liquidate(uint256 tokenId) external;

    function liquidate(uint256 tokenID, bytes[] memory priceUpdateData) external payable;

    function liquidationBufferRatio() external view returns (uint128 liquidationBufferRatio);

    function liquidationFeeLowerBound() external view returns (uint256 feeLowerBound);

    function liquidationFeeRatio() external view returns (uint128 liquidationFeeRatio);

    function liquidationFeeUpperBound() external view returns (uint256 feeUpperBound);

    function liquidationPrice(uint256 tokenId) external view returns (uint256 liqPrice);

    function liquidationPrice(uint256 tokenId, uint256 price) external view returns (uint256 liqPrice);

    function setLiquidationBufferRatio(uint128 _newLiquidationBufferRatio) external;

    function setLiquidationFeeRatio(uint128 _newLiquidationFeeRatio) external;
}

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.20;

import {FlatcoinStructs} from "../libraries/FlatcoinStructs.sol";

interface ILimitOrder {
    function announceLimitOrder(uint256 tokenId, uint256 priceLowerThreshold, uint256 priceUpperThreshold) external;

    function cancelExistingLimitOrder(uint256 tokenId) external returns (bool cancelled);

    function cancelLimitOrder(uint256 tokenId) external;

    function executeLimitOrder(uint256 tokenId, bytes[] memory priceUpdateData) external payable;

    function getLimitOrder(uint256 tokenId) external view returns (FlatcoinStructs.Order memory order);

    function resetExecutionTime(uint256 tokenId) external;
}

File 10 of 20 : FlatcoinStructs.sol
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity 0.8.20;

import {IChainlinkAggregatorV3} from "../interfaces/IChainlinkAggregatorV3.sol";
import {IPyth} from "pyth-sdk-solidity/IPyth.sol";

library FlatcoinStructs {
    enum OrderType {
        None, // 0
        StableDeposit, // 1
        StableWithdraw, // 2
        LeverageOpen, // 3
        LeverageClose, // 4
        LeverageAdjust, // 5
        LimitClose // 6
    }

    enum LimitOrderExecutionType {
        None, // 0
        StopLoss, // 1
        ProfitTake // 2
    }

    /// @notice Global position data
    /// @dev This is the consolidated data of all leverage positions used to calculate funding fees and total profit and loss.
    /// @dev One can imagine this as being the data of a single big position on leverage side against the stable side.
    /// @param marginDepositedTotal Total collateral deposited for leverage trade positions.
    /// @param averagePrice The last time funding fees and profit and loss were settled.
    /// @param sizeOpenedTotal The total size of leverage across all trades on entry.
    struct GlobalPositions {
        int256 marginDepositedTotal;
        uint256 averagePrice;
        uint256 sizeOpenedTotal;
    }

    /// @notice Individual leverage position
    struct Position {
        uint256 averagePrice;
        uint256 marginDeposited;
        uint256 additionalSize;
        int256 entryCumulativeFunding;
    }

    struct MarketSummary {
        int256 profitLossTotalByLongs;
        int256 accruedFundingTotalByLongs;
        int256 currentFundingRate;
        int256 nextFundingEntry;
    }

    struct PositionSummary {
        int256 profitLoss;
        int256 accruedFunding;
        int256 marginAfterSettlement;
    }

    struct VaultSummary {
        int256 marketSkew;
        int256 cumulativeFundingRate;
        int256 lastRecomputedFundingRate;
        uint64 lastRecomputedFundingTimestamp;
        uint256 stableCollateralTotal;
        GlobalPositions globalPositions;
    }

    struct Order {
        OrderType orderType;
        uint256 keeperFee; // The deposit paid upon submitting that needs to be paid / refunded on tx confirmation
        uint64 executableAtTime; // The timestamp at which this order is executable at
        bytes orderData;
    }

    struct AnnouncedStableDeposit {
        uint256 depositAmount;
        uint256 minAmountOut; // The minimum amount of tokens expected to receive back
    }

    struct AnnouncedStableWithdraw {
        uint256 withdrawAmount;
        uint256 minAmountOut; // The minimum amount of underlying tokens expected to receive back
    }

    struct AnnouncedLeverageOpen {
        uint256 margin; // The margin amount to be used as leverage collateral
        uint256 additionalSize; // The additional size exposure (leverage)
        uint256 maxFillPrice; // The maximum price accepted by the user
        uint256 tradeFee;
    }

    struct AnnouncedLeverageAdjust {
        uint256 tokenId;
        int256 marginAdjustment;
        int256 additionalSizeAdjustment;
        uint256 fillPrice; // should be passed depending on the type of additionalSizeAdjustment
        uint256 tradeFee;
        uint256 totalFee;
    }

    // Note: the tradeFee is determined at time of execution
    struct LimitClose {
        // Note: the tradeFee is determined at time of execution
        uint256 tokenId;
        uint256 priceLowerThreshold;
        uint256 priceUpperThreshold;
    }

    struct AnnouncedLeverageClose {
        uint256 tokenId; // The NFT of the position
        uint256 minFillPrice; // The minimum price accepted by the user
        uint256 tradeFee;
    }

    struct OnchainOracle {
        IChainlinkAggregatorV3 oracleContract; // Chainlink oracle contract
        uint32 maxAge; // Oldest price that is acceptable to use
    }

    struct OffchainOracle {
        IPyth oracleContract; // Pyth network oracle contract
        bytes32 priceId; // Pyth network price Id
        uint32 maxAge; // Oldest price that is acceptable to use
        uint32 minConfidenceRatio; // the minimum Pyth oracle price / expo ratio. The higher, the more confident the accuracy of the price.
    }

    struct AuthorizedModule {
        bytes32 moduleKey;
        address moduleAddress;
    }

    struct LeveragePositionData {
        uint256 tokenId;
        uint256 averagePrice;
        uint256 marginDeposited;
        uint256 additionalSize;
        int256 entryCumulativeFunding;
        int256 profitLoss;
        int256 accruedFunding;
        int256 marginAfterSettlement;
        uint256 liquidationPrice;
        uint256 limitOrderPriceLowerThreshold;
        uint256 limitOrderPriceUpperThreshold;
    }

    struct MintRate {
        uint256 lastAccumulatedMint;
        uint256 maxAccumulatedMint;
        uint64 lastMintTimestamp;
        uint64 decayTime;
    }
}

File 11 of 20 : FlatcoinModuleKeys.sol
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity 0.8.20;

library FlatcoinModuleKeys {
    bytes32 internal constant _STABLE_MODULE_KEY = bytes32("stableModule");
    bytes32 internal constant _LEVERAGE_MODULE_KEY = bytes32("leverageModule");
    bytes32 internal constant _ORACLE_MODULE_KEY = bytes32("oracleModule");
    bytes32 internal constant _DELAYED_ORDER_KEY = bytes32("delayedOrder");
    bytes32 internal constant _LIMIT_ORDER_KEY = bytes32("limitOrder");
    bytes32 internal constant _LIQUIDATION_MODULE_KEY = bytes32("liquidationModule");
    bytes32 internal constant _KEEPER_FEE_MODULE_KEY = bytes32("keeperFee");
    bytes32 internal constant _POINTS_MODULE_KEY = bytes32("pointsModule");
}

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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.20;

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

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

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

pragma solidity ^0.8.20;

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

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

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

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

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.20;

interface IChainlinkAggregatorV3 {
    function decimals() external view returns (uint8 decimals);

    function latestRoundData()
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "./PythStructs.sol";
import "./IPythEvents.sol";

/// @title Consume prices from the Pyth Network (https://pyth.network/).
/// @dev Please refer to the guidance at https://docs.pyth.network/consumers/best-practices for how to consume prices safely.
/// @author Pyth Data Association
interface IPyth is IPythEvents {
    /// @notice Returns the period (in seconds) that a price feed is considered valid since its publish time
    function getValidTimePeriod() external view returns (uint validTimePeriod);

    /// @notice Returns the price and confidence interval.
    /// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds.
    /// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval.
    /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
    function getPrice(
        bytes32 id
    ) external view returns (PythStructs.Price memory price);

    /// @notice Returns the exponentially-weighted moving average price and confidence interval.
    /// @dev Reverts if the EMA price is not available.
    /// @param id The Pyth Price Feed ID of which to fetch the EMA price and confidence interval.
    /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
    function getEmaPrice(
        bytes32 id
    ) external view returns (PythStructs.Price memory price);

    /// @notice Returns the price of a price feed without any sanity checks.
    /// @dev This function returns the most recent price update in this contract without any recency checks.
    /// This function is unsafe as the returned price update may be arbitrarily far in the past.
    ///
    /// Users of this function should check the `publishTime` in the price to ensure that the returned price is
    /// sufficiently recent for their application. If you are considering using this function, it may be
    /// safer / easier to use either `getPrice` or `getPriceNoOlderThan`.
    /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
    function getPriceUnsafe(
        bytes32 id
    ) external view returns (PythStructs.Price memory price);

    /// @notice Returns the price that is no older than `age` seconds of the current time.
    /// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in
    /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
    /// recently.
    /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
    function getPriceNoOlderThan(
        bytes32 id,
        uint age
    ) external view returns (PythStructs.Price memory price);

    /// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks.
    /// @dev This function returns the same price as `getEmaPrice` in the case where the price is available.
    /// However, if the price is not recent this function returns the latest available price.
    ///
    /// The returned price can be from arbitrarily far in the past; this function makes no guarantees that
    /// the returned price is recent or useful for any particular application.
    ///
    /// Users of this function should check the `publishTime` in the price to ensure that the returned price is
    /// sufficiently recent for their application. If you are considering using this function, it may be
    /// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`.
    /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
    function getEmaPriceUnsafe(
        bytes32 id
    ) external view returns (PythStructs.Price memory price);

    /// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds
    /// of the current time.
    /// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in
    /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
    /// recently.
    /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
    function getEmaPriceNoOlderThan(
        bytes32 id,
        uint age
    ) external view returns (PythStructs.Price memory price);

    /// @notice Update price feeds with given update messages.
    /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
    /// `getUpdateFee` with the length of the `updateData` array.
    /// Prices will be updated if they are more recent than the current stored prices.
    /// The call will succeed even if the update is not the most recent.
    /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid.
    /// @param updateData Array of price update data.
    function updatePriceFeeds(bytes[] calldata updateData) external payable;

    /// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is
    /// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the
    /// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`.
    ///
    /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
    /// `getUpdateFee` with the length of the `updateData` array.
    ///
    /// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime
    /// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have
    /// a newer or equal publish time than the given publish time, it will reject the transaction to save gas.
    /// Otherwise, it calls updatePriceFeeds method to update the prices.
    ///
    /// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid.
    /// @param updateData Array of price update data.
    /// @param priceIds Array of price ids.
    /// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]`
    function updatePriceFeedsIfNecessary(
        bytes[] calldata updateData,
        bytes32[] calldata priceIds,
        uint64[] calldata publishTimes
    ) external payable;

    /// @notice Returns the required fee to update an array of price updates.
    /// @param updateData Array of price update data.
    /// @return feeAmount The required fee in Wei.
    function getUpdateFee(
        bytes[] calldata updateData
    ) external view returns (uint feeAmount);

    /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published
    /// within `minPublishTime` and `maxPublishTime`.
    ///
    /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;
    /// otherwise, please consider using `updatePriceFeeds`. This method does not store the price updates on-chain.
    ///
    /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
    /// `getUpdateFee` with the length of the `updateData` array.
    ///
    ///
    /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is
    /// no update for any of the given `priceIds` within the given time range.
    /// @param updateData Array of price update data.
    /// @param priceIds Array of price ids.
    /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.
    /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.
    /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).
    function parsePriceFeedUpdates(
        bytes[] calldata updateData,
        bytes32[] calldata priceIds,
        uint64 minPublishTime,
        uint64 maxPublishTime
    ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);
}

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

pragma solidity ^0.8.20;

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

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 18 of 20 : PythStructs.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

contract PythStructs {
    // A price with a degree of uncertainty, represented as a price +- a confidence interval.
    //
    // The confidence interval roughly corresponds to the standard error of a normal distribution.
    // Both the price and confidence are stored in a fixed-point numeric representation,
    // `x * (10^expo)`, where `expo` is the exponent.
    //
    // Please refer to the documentation at https://docs.pyth.network/consumers/best-practices for how
    // to how this price safely.
    struct Price {
        // Price
        int64 price;
        // Confidence interval around the price
        uint64 conf;
        // Price exponent
        int32 expo;
        // Unix timestamp describing when the price was published
        uint publishTime;
    }

    // PriceFeed represents a current aggregate price from pyth publisher feeds.
    struct PriceFeed {
        // The price ID.
        bytes32 id;
        // Latest available price
        Price price;
        // Latest available exponentially-weighted moving average price
        Price emaPrice;
    }
}

File 19 of 20 : IPythEvents.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @title IPythEvents contains the events that Pyth contract emits.
/// @dev This interface can be used for listening to the updates for off-chain and testing purposes.
interface IPythEvents {
    /// @dev Emitted when the price feed with `id` has received a fresh update.
    /// @param id The Pyth Price Feed ID.
    /// @param publishTime Publish time of the given price update.
    /// @param price Price of the given price update.
    /// @param conf Confidence interval of the given price update.
    event PriceFeedUpdate(
        bytes32 indexed id,
        uint64 publishTime,
        int64 price,
        uint64 conf
    );

    /// @dev Emitted when a batch price update is processed successfully.
    /// @param chainId ID of the source chain that the batch price update comes from.
    /// @param sequenceNumber Sequence number of the batch price update.
    event BatchPriceFeedUpdate(uint16 chainId, uint64 sequenceNumber);
}

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

pragma solidity ^0.8.20;

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

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/",
    "pyth-sdk-solidity/=lib/pyth-sdk-solidity/",
    "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/",
    "ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 500
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IFlatcoinVault","name":"_vault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAccountLeveragePositionData","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"averagePrice","type":"uint256"},{"internalType":"uint256","name":"marginDeposited","type":"uint256"},{"internalType":"uint256","name":"additionalSize","type":"uint256"},{"internalType":"int256","name":"entryCumulativeFunding","type":"int256"},{"internalType":"int256","name":"profitLoss","type":"int256"},{"internalType":"int256","name":"accruedFunding","type":"int256"},{"internalType":"int256","name":"marginAfterSettlement","type":"int256"},{"internalType":"uint256","name":"liquidationPrice","type":"uint256"},{"internalType":"uint256","name":"limitOrderPriceLowerThreshold","type":"uint256"},{"internalType":"uint256","name":"limitOrderPriceUpperThreshold","type":"uint256"}],"internalType":"struct FlatcoinStructs.LeveragePositionData[]","name":"positionData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFlatcoinPriceInUSD","outputs":[{"internalType":"uint256","name":"priceInUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFlatcoinTVL","outputs":[{"internalType":"uint256","name":"tvl","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMarketSkewPercentage","outputs":[{"internalType":"int256","name":"skewPercent","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getPositionData","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"averagePrice","type":"uint256"},{"internalType":"uint256","name":"marginDeposited","type":"uint256"},{"internalType":"uint256","name":"additionalSize","type":"uint256"},{"internalType":"int256","name":"entryCumulativeFunding","type":"int256"},{"internalType":"int256","name":"profitLoss","type":"int256"},{"internalType":"int256","name":"accruedFunding","type":"int256"},{"internalType":"int256","name":"marginAfterSettlement","type":"int256"},{"internalType":"uint256","name":"liquidationPrice","type":"uint256"},{"internalType":"uint256","name":"limitOrderPriceLowerThreshold","type":"uint256"},{"internalType":"uint256","name":"limitOrderPriceUpperThreshold","type":"uint256"}],"internalType":"struct FlatcoinStructs.LeveragePositionData","name":"positionData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenIdFrom","type":"uint256"},{"internalType":"uint256","name":"tokenIdTo","type":"uint256"}],"name":"getPositionData","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"averagePrice","type":"uint256"},{"internalType":"uint256","name":"marginDeposited","type":"uint256"},{"internalType":"uint256","name":"additionalSize","type":"uint256"},{"internalType":"int256","name":"entryCumulativeFunding","type":"int256"},{"internalType":"int256","name":"profitLoss","type":"int256"},{"internalType":"int256","name":"accruedFunding","type":"int256"},{"internalType":"int256","name":"marginAfterSettlement","type":"int256"},{"internalType":"uint256","name":"liquidationPrice","type":"uint256"},{"internalType":"uint256","name":"limitOrderPriceLowerThreshold","type":"uint256"},{"internalType":"uint256","name":"limitOrderPriceUpperThreshold","type":"uint256"}],"internalType":"struct FlatcoinStructs.LeveragePositionData[]","name":"positionData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IFlatcoinVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b5060405161170238038061170283398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b61166f806100936000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806373bc845c1161005b57806373bc845c146100e1578063d6ed5898146100e9578063fbfa77cf146100fc578063ff0774371461012757600080fd5b80630f415acb146100825780632f6d3457146100ab578063579bcf96146100cb575b600080fd5b610095610090366004610f06565b61012f565b6040516100a29190610f1f565b60405180910390f35b6100be6100b9366004610f9b565b61059c565b6040516100a29190610fbd565b6100d36106b1565b6040519081526020016100a2565b6100d36107c7565b6100be6100f7366004611091565b610a0e565b60005461010f906001600160a01b031681565b6040516001600160a01b0390911681526020016100a2565b6100d3610c6e565b61018c60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60008054604051630aa10e9f60e41b81526d6c657665726167654d6f64756c6560901b60048201526001600160a01b039091169063aa10e9f090602401602060405180830381865afa1580156101e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020a91906110b5565b60008054604051630aa10e9f60e41b81527f6c69717569646174696f6e4d6f64756c65000000000000000000000000000000600482015292935090916001600160a01b039091169063aa10e9f090602401602060405180830381865afa158015610278573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029c91906110b5565b60008054604051630aa10e9f60e41b8152693634b6b4ba27b93232b960b11b600482015292935090916001600160a01b039091169063aa10e9f090602401602060405180830381865afa1580156102f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031b91906110b5565b6000805460405163eb02c30160e01b81526004810189905292935090916001600160a01b039091169063eb02c30190602401608060405180830381865afa15801561036a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038e9190611188565b604051633de9a8bb60e11b8152600481018890529091506000906001600160a01b03861690637bd3517690602401606060405180830381865afa1580156103d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fd91906111ce565b90506000806000856001600160a01b031663530610268b6040518263ffffffff1660e01b815260040161043291815260200190565b600060405180830381865afa15801561044f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104779190810190611227565b905060068151600681111561048e5761048e611331565b036104bf57600081606001518060200190518101906104ad91906111ce565b90508060200151935080604001519250505b5060405163b7507cfd60e01b8152600481018a90526000906001600160a01b0388169063b7507cfd90602401602060405180830381865afa158015610508573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052c9190611347565b60408051610160810182529b8c5286516020808e0191909152878101518d830152878201516060808f01919091529097015160808d0152855160a08d01529585015160c08c0152939094015160e08a01526101008901929092526101208801526101408701525093949350505050565b606060006105aa8484611376565b6105b5906001611389565b90508067ffffffffffffffff8111156105d0576105d06110d2565b60405190808252806020026020018201604052801561065e57816020015b61064b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b8152602001906001900390816105ee5790505b50915060005b818110156106a9576106796100908683611389565b83828151811061068b5761068b61139c565b602002602001018190525080806106a1906113b2565b915050610664565b505092915050565b60008054604080516362af250760e11b8152905183926001600160a01b03169163c55e4a0e916004808301926101009291908290030181865afa1580156106fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072091906113cb565b905060008060009054906101000a90046001600160a01b03166001600160a01b03166319f741746040518163ffffffff1660e01b8152600401602060405180830381865afa158015610776573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079a9190611347565b608083015190915060008190036107b5576000935050505090565b6107bf8282610ede565b935050505090565b60008054604051630aa10e9f60e41b81526b737461626c654d6f64756c6560a01b600482015282916001600160a01b03169063aa10e9f090602401602060405180830381865afa15801561081f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084391906110b5565b90506000816001600160a01b03166367f77e546040518163ffffffff1660e01b8152600401602060405180830381865afa158015610885573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a99190611347565b60008054604051630aa10e9f60e41b81526b6f7261636c654d6f64756c6560a01b600482015292935090916001600160a01b039091169063aa10e9f090602401602060405180830381865afa158015610906573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092a91906110b5565b6001600160a01b03166398d5fdca6040518163ffffffff1660e01b81526004016040805180830381865afa158015610966573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098a9190611460565b509050826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ef9190611484565b6109fa90600a61158b565b610a04828461159a565b6107bf91906115c7565b60008054604051630aa10e9f60e41b81526d6c657665726167654d6f64756c6560901b6004820152606092916001600160a01b03169063aa10e9f090602401602060405180830381865afa158015610a6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8e91906110b5565b6040516370a0823160e01b81526001600160a01b0385811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610ada573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610afe9190611347565b90508067ffffffffffffffff811115610b1957610b196110d2565b604051908082528060200260200182016040528015610ba757816020015b610b9460405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610b375790505b50925060005b81811015610c6657604051632f745c5960e01b81526001600160a01b0386811660048301526024820183905260009190851690632f745c5990604401602060405180830381865afa158015610c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2a9190611347565b9050610c358161012f565b858381518110610c4757610c4761139c565b6020026020010181905250508080610c5e906113b2565b915050610bad565b505050919050565b60008054604051630aa10e9f60e41b81526b6f7261636c654d6f64756c6560a01b600482015282916001600160a01b03169063aa10e9f090602401602060405180830381865afa158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cea91906110b5565b60008054604051630aa10e9f60e41b81526b737461626c654d6f64756c6560a01b600482015292935090916001600160a01b039091169063aa10e9f090602401602060405180830381865afa158015610d47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6b91906110b5565b905060008060009054906101000a90046001600160a01b03166001600160a01b031663c55e4a0e6040518163ffffffff1660e01b815260040161010060405180830381865afa158015610dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de691906113cb565b90506000836001600160a01b03166398d5fdca6040518163ffffffff1660e01b81526004016040805180830381865afa158015610e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611460565b509050826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb09190611484565b610ebb90600a61158b565b818360800151610ecb919061159a565b610ed591906115c7565b94505050505090565b600081610ef3670de0b6b3a7640000856115db565b610efd919061160b565b90505b92915050565b600060208284031215610f1857600080fd5b5035919050565b6101608101610f008284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152506101208082015181840152506101408082015181840152505050565b60008060408385031215610fae57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b8181101561106d57611059838551805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152506101208082015181840152506101408082015181840152505050565b928401926101609290920191600101610fd9565b50909695505050505050565b6001600160a01b038116811461108e57600080fd5b50565b6000602082840312156110a357600080fd5b81356110ae81611079565b9392505050565b6000602082840312156110c757600080fd5b81516110ae81611079565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561110b5761110b6110d2565b60405290565b6040516060810167ffffffffffffffff8111828210171561110b5761110b6110d2565b60405160c0810167ffffffffffffffff8111828210171561110b5761110b6110d2565b604051601f8201601f1916810167ffffffffffffffff81118282101715611180576111806110d2565b604052919050565b60006080828403121561119a57600080fd5b6111a26110e8565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b6000606082840312156111e057600080fd5b6111e8611111565b8251815260208301516020820152604083015160408201528091505092915050565b805167ffffffffffffffff8116811461122257600080fd5b919050565b6000602080838503121561123a57600080fd5b825167ffffffffffffffff8082111561125257600080fd5b908401906080828703121561126657600080fd5b61126e6110e8565b82516007811061127d57600080fd5b815282840151848201526112936040840161120a565b60408201526060830151828111156112aa57600080fd5b80840193505086601f8401126112bf57600080fd5b8251828111156112d1576112d16110d2565b6112e3601f8201601f19168601611157565b925080835287858286010111156112f957600080fd5b60005b818110156113175784810186015184820187015285016112fc565b506000908301909401939093526060830152509392505050565b634e487b7160e01b600052602160045260246000fd5b60006020828403121561135957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f0057610f00611360565b80820180821115610f0057610f00611360565b634e487b7160e01b600052603260045260246000fd5b6000600182016113c4576113c4611360565b5060010190565b60008183036101008112156113df57600080fd5b6113e7611134565b83518152602084015160208201526040840151604082015261140b6060850161120a565b6060820152608084015160808201526060609f198301121561142c57600080fd5b611434611111565b60a085810151825260c0860151602083015260e090950151604082015293810193909352509092915050565b6000806040838503121561147357600080fd5b505080516020909101519092909150565b60006020828403121561149657600080fd5b815160ff811681146110ae57600080fd5b600181815b808511156114e25781600019048211156114c8576114c8611360565b808516156114d557918102915b93841c93908002906114ac565b509250929050565b6000826114f957506001610f00565b8161150657506000610f00565b816001811461151c576002811461152657611542565b6001915050610f00565b60ff84111561153757611537611360565b50506001821b610f00565b5060208310610133831016604e8410600b8410161715611565575081810a610f00565b61156f83836114a7565b806000190482111561158357611583611360565b029392505050565b6000610efd60ff8416836114ea565b8082028115828204841417610f0057610f00611360565b634e487b7160e01b600052601260045260246000fd5b6000826115d6576115d66115b1565b500490565b80820260008212600160ff1b841416156115f7576115f7611360565b8181058314821517610f0057610f00611360565b60008261161a5761161a6115b1565b600160ff1b82146000198414161561163457611634611360565b50059056fea2646970667358221220a5a89a192b0705b89c49dd992232f4dbdc2bcba870c3cd17f82523da3c8e9c8a64736f6c6343000814003300000000000000000000000095fa1ddc9a78273f795e67abe8f1cd2cd39831ff

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c806373bc845c1161005b57806373bc845c146100e1578063d6ed5898146100e9578063fbfa77cf146100fc578063ff0774371461012757600080fd5b80630f415acb146100825780632f6d3457146100ab578063579bcf96146100cb575b600080fd5b610095610090366004610f06565b61012f565b6040516100a29190610f1f565b60405180910390f35b6100be6100b9366004610f9b565b61059c565b6040516100a29190610fbd565b6100d36106b1565b6040519081526020016100a2565b6100d36107c7565b6100be6100f7366004611091565b610a0e565b60005461010f906001600160a01b031681565b6040516001600160a01b0390911681526020016100a2565b6100d3610c6e565b61018c60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60008054604051630aa10e9f60e41b81526d6c657665726167654d6f64756c6560901b60048201526001600160a01b039091169063aa10e9f090602401602060405180830381865afa1580156101e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020a91906110b5565b60008054604051630aa10e9f60e41b81527f6c69717569646174696f6e4d6f64756c65000000000000000000000000000000600482015292935090916001600160a01b039091169063aa10e9f090602401602060405180830381865afa158015610278573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029c91906110b5565b60008054604051630aa10e9f60e41b8152693634b6b4ba27b93232b960b11b600482015292935090916001600160a01b039091169063aa10e9f090602401602060405180830381865afa1580156102f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031b91906110b5565b6000805460405163eb02c30160e01b81526004810189905292935090916001600160a01b039091169063eb02c30190602401608060405180830381865afa15801561036a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038e9190611188565b604051633de9a8bb60e11b8152600481018890529091506000906001600160a01b03861690637bd3517690602401606060405180830381865afa1580156103d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fd91906111ce565b90506000806000856001600160a01b031663530610268b6040518263ffffffff1660e01b815260040161043291815260200190565b600060405180830381865afa15801561044f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104779190810190611227565b905060068151600681111561048e5761048e611331565b036104bf57600081606001518060200190518101906104ad91906111ce565b90508060200151935080604001519250505b5060405163b7507cfd60e01b8152600481018a90526000906001600160a01b0388169063b7507cfd90602401602060405180830381865afa158015610508573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052c9190611347565b60408051610160810182529b8c5286516020808e0191909152878101518d830152878201516060808f01919091529097015160808d0152855160a08d01529585015160c08c0152939094015160e08a01526101008901929092526101208801526101408701525093949350505050565b606060006105aa8484611376565b6105b5906001611389565b90508067ffffffffffffffff8111156105d0576105d06110d2565b60405190808252806020026020018201604052801561065e57816020015b61064b60405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b8152602001906001900390816105ee5790505b50915060005b818110156106a9576106796100908683611389565b83828151811061068b5761068b61139c565b602002602001018190525080806106a1906113b2565b915050610664565b505092915050565b60008054604080516362af250760e11b8152905183926001600160a01b03169163c55e4a0e916004808301926101009291908290030181865afa1580156106fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072091906113cb565b905060008060009054906101000a90046001600160a01b03166001600160a01b03166319f741746040518163ffffffff1660e01b8152600401602060405180830381865afa158015610776573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079a9190611347565b608083015190915060008190036107b5576000935050505090565b6107bf8282610ede565b935050505090565b60008054604051630aa10e9f60e41b81526b737461626c654d6f64756c6560a01b600482015282916001600160a01b03169063aa10e9f090602401602060405180830381865afa15801561081f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084391906110b5565b90506000816001600160a01b03166367f77e546040518163ffffffff1660e01b8152600401602060405180830381865afa158015610885573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a99190611347565b60008054604051630aa10e9f60e41b81526b6f7261636c654d6f64756c6560a01b600482015292935090916001600160a01b039091169063aa10e9f090602401602060405180830381865afa158015610906573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092a91906110b5565b6001600160a01b03166398d5fdca6040518163ffffffff1660e01b81526004016040805180830381865afa158015610966573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098a9190611460565b509050826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ef9190611484565b6109fa90600a61158b565b610a04828461159a565b6107bf91906115c7565b60008054604051630aa10e9f60e41b81526d6c657665726167654d6f64756c6560901b6004820152606092916001600160a01b03169063aa10e9f090602401602060405180830381865afa158015610a6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8e91906110b5565b6040516370a0823160e01b81526001600160a01b0385811660048301529192506000918316906370a0823190602401602060405180830381865afa158015610ada573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610afe9190611347565b90508067ffffffffffffffff811115610b1957610b196110d2565b604051908082528060200260200182016040528015610ba757816020015b610b9460405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081610b375790505b50925060005b81811015610c6657604051632f745c5960e01b81526001600160a01b0386811660048301526024820183905260009190851690632f745c5990604401602060405180830381865afa158015610c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2a9190611347565b9050610c358161012f565b858381518110610c4757610c4761139c565b6020026020010181905250508080610c5e906113b2565b915050610bad565b505050919050565b60008054604051630aa10e9f60e41b81526b6f7261636c654d6f64756c6560a01b600482015282916001600160a01b03169063aa10e9f090602401602060405180830381865afa158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cea91906110b5565b60008054604051630aa10e9f60e41b81526b737461626c654d6f64756c6560a01b600482015292935090916001600160a01b039091169063aa10e9f090602401602060405180830381865afa158015610d47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6b91906110b5565b905060008060009054906101000a90046001600160a01b03166001600160a01b031663c55e4a0e6040518163ffffffff1660e01b815260040161010060405180830381865afa158015610dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de691906113cb565b90506000836001600160a01b03166398d5fdca6040518163ffffffff1660e01b81526004016040805180830381865afa158015610e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611460565b509050826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb09190611484565b610ebb90600a61158b565b818360800151610ecb919061159a565b610ed591906115c7565b94505050505090565b600081610ef3670de0b6b3a7640000856115db565b610efd919061160b565b90505b92915050565b600060208284031215610f1857600080fd5b5035919050565b6101608101610f008284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152506101208082015181840152506101408082015181840152505050565b60008060408385031215610fae57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b8181101561106d57611059838551805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152506101208082015181840152506101408082015181840152505050565b928401926101609290920191600101610fd9565b50909695505050505050565b6001600160a01b038116811461108e57600080fd5b50565b6000602082840312156110a357600080fd5b81356110ae81611079565b9392505050565b6000602082840312156110c757600080fd5b81516110ae81611079565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561110b5761110b6110d2565b60405290565b6040516060810167ffffffffffffffff8111828210171561110b5761110b6110d2565b60405160c0810167ffffffffffffffff8111828210171561110b5761110b6110d2565b604051601f8201601f1916810167ffffffffffffffff81118282101715611180576111806110d2565b604052919050565b60006080828403121561119a57600080fd5b6111a26110e8565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b6000606082840312156111e057600080fd5b6111e8611111565b8251815260208301516020820152604083015160408201528091505092915050565b805167ffffffffffffffff8116811461122257600080fd5b919050565b6000602080838503121561123a57600080fd5b825167ffffffffffffffff8082111561125257600080fd5b908401906080828703121561126657600080fd5b61126e6110e8565b82516007811061127d57600080fd5b815282840151848201526112936040840161120a565b60408201526060830151828111156112aa57600080fd5b80840193505086601f8401126112bf57600080fd5b8251828111156112d1576112d16110d2565b6112e3601f8201601f19168601611157565b925080835287858286010111156112f957600080fd5b60005b818110156113175784810186015184820187015285016112fc565b506000908301909401939093526060830152509392505050565b634e487b7160e01b600052602160045260246000fd5b60006020828403121561135957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f0057610f00611360565b80820180821115610f0057610f00611360565b634e487b7160e01b600052603260045260246000fd5b6000600182016113c4576113c4611360565b5060010190565b60008183036101008112156113df57600080fd5b6113e7611134565b83518152602084015160208201526040840151604082015261140b6060850161120a565b6060820152608084015160808201526060609f198301121561142c57600080fd5b611434611111565b60a085810151825260c0860151602083015260e090950151604082015293810193909352509092915050565b6000806040838503121561147357600080fd5b505080516020909101519092909150565b60006020828403121561149657600080fd5b815160ff811681146110ae57600080fd5b600181815b808511156114e25781600019048211156114c8576114c8611360565b808516156114d557918102915b93841c93908002906114ac565b509250929050565b6000826114f957506001610f00565b8161150657506000610f00565b816001811461151c576002811461152657611542565b6001915050610f00565b60ff84111561153757611537611360565b50506001821b610f00565b5060208310610133831016604e8410600b8410161715611565575081810a610f00565b61156f83836114a7565b806000190482111561158357611583611360565b029392505050565b6000610efd60ff8416836114ea565b8082028115828204841417610f0057610f00611360565b634e487b7160e01b600052601260045260246000fd5b6000826115d6576115d66115b1565b500490565b80820260008212600160ff1b841416156115f7576115f7611360565b8181058314821517610f0057610f00611360565b60008261161a5761161a6115b1565b600160ff1b82146000198414161561163457611634611360565b50059056fea2646970667358221220a5a89a192b0705b89c49dd992232f4dbdc2bcba870c3cd17f82523da3c8e9c8a64736f6c63430008140033

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

00000000000000000000000095fa1ddc9a78273f795e67abe8f1cd2cd39831ff

-----Decoded View---------------
Arg [0] : _vault (address): 0x95Fa1ddc9a78273f795e67AbE8f1Cd2Cd39831fF

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000095fa1ddc9a78273f795e67abe8f1cd2cd39831ff


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

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.