creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n  function decimals() external view returns (uint8);\n\n  function description() external view returns (string memory);\n\n  function version() external view returns (uint256);\n\n  // getRoundData and latestRoundData should both raise \"No data present\"\n  // if they do not have data to report, instead of returning unset values\n  // which could be misinterpreted as actual reported values.\n  function getRoundData(uint80 _roundId)\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n\n  function latestRoundData()\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal initializer {\n        __Context_init_unchained();\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal initializer {\n        _setOwner(_msgSender());\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _setOwner(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _setOwner(newOwner);\n    }\n\n    function _setOwner(address newOwner) private {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     */\n    bool private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Modifier to protect an initializer function from being invoked twice.\n     */\n    modifier initializer() {\n        require(_initializing || !_initialized, \"Initializable: contract is already initialized\");\n\n        bool isTopLevelCall = !_initializing;\n        if (isTopLevelCall) {\n            _initializing = true;\n            _initialized = true;\n        }\n\n        _;\n\n        if (isTopLevelCall) {\n            _initializing = false;\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal initializer {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal initializer {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and make it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    function __ERC20_init(string memory name_, string memory symbol_) internal initializer {\n        __Context_init_unchained();\n        __ERC20_init_unchained(name_, symbol_);\n    }\n\n    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\n     * overridden;\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `recipient` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n        _transfer(_msgSender(), recipient, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        _approve(_msgSender(), spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * Requirements:\n     *\n     * - `sender` and `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``sender``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) public virtual override returns (bool) {\n        _transfer(sender, recipient, amount);\n\n        uint256 currentAllowance = _allowances[sender][_msgSender()];\n        require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n        unchecked {\n            _approve(sender, _msgSender(), currentAllowance - amount);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        uint256 currentAllowance = _allowances[_msgSender()][spender];\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `sender` to `recipient`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `sender` cannot be the zero address.\n     * - `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     */\n    function _transfer(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) internal virtual {\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(sender, recipient, amount);\n\n        uint256 senderBalance = _balances[sender];\n        require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[sender] = senderBalance - amount;\n        }\n        _balances[recipient] += amount;\n\n        emit Transfer(sender, recipient, amount);\n\n        _afterTokenTransfer(sender, recipient, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        _balances[account] += amount;\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n        }\n        _totalSupply -= amount;\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n    uint256[45] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal initializer {\n        __Context_init_unchained();\n    }\n\n    function __Context_init_unchained() internal initializer {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n    uint256[50] private __gap;\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
      },
      "contracts/interfaces/GammaInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.8.4;\n\nlibrary GammaTypes {\n    // vault is a struct of 6 arrays that describe a position a user has, a user can have multiple vaults.\n    struct Vault {\n        // addresses of oTokens a user has shorted (i.e. written) against this vault\n        address[] shortOtokens;\n        // addresses of oTokens a user has bought and deposited in this vault\n        // user can be long oTokens without opening a vault (e.g. by buying on a DEX)\n        // generally, long oTokens will be 'deposited' in vaults to act as collateral\n        // in order to write oTokens against (i.e. in spreads)\n        address[] longOtokens;\n        // addresses of other ERC-20s a user has deposited as collateral in this vault\n        address[] collateralAssets;\n        // quantity of oTokens minted/written for each oToken address in shortOtokens\n        uint256[] shortAmounts;\n        // quantity of oTokens owned and held in the vault for each oToken address in longOtokens\n        uint256[] longAmounts;\n        // quantity of ERC-20 deposited as collateral in the vault for each ERC-20 address in collateralAssets\n        uint256[] collateralAmounts;\n    }\n}\n\ninterface IOtoken {\n    function underlyingAsset() external view returns (address);\n\n    function strikeAsset() external view returns (address);\n\n    function collateralAsset() external view returns (address);\n\n    function strikePrice() external view returns (uint256);\n\n    function expiryTimestamp() external view returns (uint256);\n\n    function isPut() external view returns (bool);\n\n    function balanceOf(address) external view returns (uint256);\n\n    function totalSupply() external view returns (uint256);\n\n    function transfer(address, uint256) external;\n}\n\ninterface IOtokenFactory {\n    function getOtoken(\n        address _underlyingAsset,\n        address _strikeAsset,\n        address _collateralAsset,\n        uint256 _strikePrice,\n        uint256 _expiry,\n        bool _isPut\n    ) external view returns (address);\n\n    function createOtoken(\n        address _underlyingAsset,\n        address _strikeAsset,\n        address _collateralAsset,\n        uint256 _strikePrice,\n        uint256 _expiry,\n        bool _isPut\n    ) external returns (address);\n\n    function getTargetOtokenAddress(\n        address _underlyingAsset,\n        address _strikeAsset,\n        address _collateralAsset,\n        uint256 _strikePrice,\n        uint256 _expiry,\n        bool _isPut\n    ) external view returns (address);\n\n    event OtokenCreated(\n        address tokenAddress,\n        address creator,\n        address indexed underlying,\n        address indexed strike,\n        address indexed collateral,\n        uint256 strikePrice,\n        uint256 expiry,\n        bool isPut\n    );\n}\n\ninterface IController {\n    // possible actions that can be performed\n    enum ActionType {\n        OpenVault,\n        MintShortOption,\n        BurnShortOption,\n        DepositLongOption,\n        WithdrawLongOption,\n        DepositCollateral,\n        WithdrawCollateral,\n        SettleVault,\n        Redeem,\n        Call,\n        Liquidate\n    }\n\n    struct ActionArgs {\n        // type of action that is being performed on the system\n        ActionType actionType;\n        // address of the account owner\n        address owner;\n        // address which we move assets from or to (depending on the action type)\n        address secondAddress;\n        // asset that is to be transfered\n        address asset;\n        // index of the vault that is to be modified (if any)\n        uint256 vaultId;\n        // amount of asset that is to be transfered\n        uint256 amount;\n        // each vault can hold multiple short / long / collateral assets\n        // but we are restricting the scope to only 1 of each in this version\n        // in future versions this would be the index of the short / long / collateral asset that needs to be modified\n        uint256 index;\n        // any other data that needs to be passed in for arbitrary function calls\n        bytes data;\n    }\n\n    struct RedeemArgs {\n        // address to which we pay out the oToken proceeds\n        address receiver;\n        // oToken that is to be redeemed\n        address otoken;\n        // amount of oTokens that is to be redeemed\n        uint256 amount;\n    }\n\n    function getPayout(address _otoken, uint256 _amount)\n        external\n        view\n        returns (uint256);\n\n    function operate(ActionArgs[] calldata _actions) external;\n\n    function getAccountVaultCounter(address owner)\n        external\n        view\n        returns (uint256);\n\n    function oracle() external view returns (address);\n\n    function getVault(address _owner, uint256 _vaultId)\n        external\n        view\n        returns (GammaTypes.Vault memory);\n\n    function getProceed(address _owner, uint256 _vaultId)\n        external\n        view\n        returns (uint256);\n\n    function isSettlementAllowed(\n        address _underlying,\n        address _strike,\n        address _collateral,\n        uint256 _expiry\n    ) external view returns (bool);\n}\n\ninterface IOracle {\n    function setAssetPricer(address _asset, address _pricer) external;\n\n    function updateAssetPricer(address _asset, address _pricer) external;\n\n    function getPrice(address _asset) external view returns (uint256);\n\n    function getExpiryPrice(address _asset, uint256 _expiryTimestamp)\n        external\n        view\n        returns (uint256);\n}\n"
      },
      "contracts/interfaces/IERC20Detailed.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.8.4;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IERC20Detailed is IERC20 {\n    function decimals() external view returns (uint8);\n\n    function symbol() external view returns (string calldata);\n\n    function name() external view returns (string calldata);\n}\n"
      },
      "contracts/interfaces/ISwap.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.8.4;\n\ninterface ISwap {\n    struct Offer {\n        // 32 byte slot 1, partial fill\n        // Seller wallet address\n        address seller;\n        // 32 byte slot 2\n        // Addess of oToken\n        address oToken;\n        // Price per oToken denominated in biddingToken\n        uint96 minPrice;\n        // 32 byte slot 3\n        // ERC20 Token to bid for oToken\n        address biddingToken;\n        // Minimum oToken amount acceptable for a single bid\n        uint96 minBidSize;\n        // 32 byte slot 4\n        // Total available oToken amount\n        uint128 totalSize;\n        // Remaining available oToken amount\n        // This figure is updated after each successfull swap\n        uint128 availableSize;\n        // 32 byte slot 5\n        // Amount of biddingToken received\n        // This figure is updated after each successfull swap\n        uint256 totalSales;\n    }\n\n    struct Bid {\n        // ID assigned to offers\n        uint256 swapId;\n        // Number only used once for each wallet\n        uint256 nonce;\n        // Signer wallet address\n        address signerWallet;\n        // Buyer address\n        address buyer;\n        // Amount of biddingToken offered by signer\n        uint256 sellAmount;\n        // Amount of oToken requested by signer\n        uint256 buyAmount;\n        // Referrer wallet address\n        address referrer;\n        // Signature recovery id\n        uint8 v;\n        // r portion of the ECSDA signature\n        bytes32 r;\n        // s portion of the ECSDA signature\n        bytes32 s;\n    }\n\n    struct OfferDetails {\n        // Seller wallet address\n        address seller;\n        // Addess of oToken\n        address oToken;\n        // Price per oToken denominated in biddingToken\n        uint256 minPrice;\n        // ERC20 Token to bid for oToken\n        address biddingToken;\n        // Minimum oToken amount acceptable for a single bid\n        uint256 minBidSize;\n    }\n\n    event Swap(\n        uint256 indexed swapId,\n        uint256 nonce,\n        address indexed buyer,\n        uint256 signerAmount,\n        uint256 sellerAmount,\n        address referrer,\n        uint256 feeAmount\n    );\n\n    event NewOffer(\n        uint256 swapId,\n        address seller,\n        address oToken,\n        address biddingToken,\n        uint256 minPrice,\n        uint256 minBidSize,\n        uint256 totalSize\n    );\n\n    event SetFee(address referrer, uint256 fee);\n\n    event SetPriceFeed(address asset, address aggregator);\n\n    event SettleOffer(uint256 swapId);\n\n    event Cancel(uint256 indexed nonce, address indexed signerWallet);\n\n    event Authorize(address indexed signer, address indexed signerWallet);\n\n    event Revoke(address indexed signer, address indexed signerWallet);\n\n    function createOffer(\n        address oToken,\n        address biddingToken,\n        uint96 minPrice,\n        uint96 minBidSize,\n        uint128 totalSize\n    ) external returns (uint256 swapId);\n\n    function settleOffer(uint256 swapId, Bid[] calldata bids) external;\n\n    function cancelNonce(uint256[] calldata nonces) external;\n\n    function check(Bid calldata bid)\n        external\n        view\n        returns (uint256, bytes32[] memory);\n\n    function averagePriceForOffer(uint256 swapId)\n        external\n        view\n        returns (uint256);\n\n    function authorize(address sender) external;\n\n    function revoke() external;\n\n    function nonceUsed(address, uint256) external view returns (bool);\n}\n"
      },
      "contracts/storage/SwapStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.8.4;\nimport \"../interfaces/ISwap.sol\";\n\nabstract contract SwapStorageV1 {\n    // Keccak256 of domain name for signature verification\n    bytes32 public DOMAIN_NAME;\n    // Keccak256 of domain version for signature verification\n    bytes32 public DOMAIN_VERSION;\n    // Keccak256 of abi-encoded domain parameters for signature verification\n    bytes32 public DOMAIN_SEPARATOR;\n\n    // Counter to keep track number of offers\n    uint256 public offersCounter;\n    // Mapping of swap offer details for a given swapId\n    mapping(uint256 => ISwap.Offer) public swapOffers;\n    // Mapping of referral fees for a given address, 1000000 = 100%\n    mapping(address => uint256) public referralFees;\n    // Mapping of authorized delegate for a given address\n    mapping(address => address) public authorized;\n    /**\n     * @notice Double mapping of signers to nonce groups to nonce states\n     * @dev The nonce group is computed as nonce / 256, so each group of 256 sequential nonces uses the same key\n     * @dev The nonce states are encoded as 256 bits, for each nonce in the group 0 means available and 1 means used\n     */\n    mapping(address => mapping(uint256 => uint256)) internal _nonceGroups;\n}\n\nabstract contract SwapStorageV2 {\n    // Price feed for looking up value of asset\n    mapping(address => address) public priceFeeds;\n}\n\n// We are following Compound's method of upgrading new contract implementations\n// When we need to add new storage variables, we create a new version of SwapStorage\n// e.g. SwapStorage<versionNumber>, so finally it would look like\n// contract SwapStorage is SwapStorageV1, SwapStorageV2\nabstract contract SwapStorage is SwapStorageV1, SwapStorageV2 {\n\n}\n"
      },
      "contracts/utils/Swap.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Source: https://github.com/airswap/airswap-protocols/blob/main/source/swap/contracts/Swap.sol\n\npragma solidity =0.8.4;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"../interfaces/ISwap.sol\";\nimport \"../storage/SwapStorage.sol\";\nimport {\n    ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {\n    OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n    ERC20Upgradeable\n} from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport {IERC20Detailed} from \"../interfaces/IERC20Detailed.sol\";\nimport {IOtoken} from \"../interfaces/GammaInterface.sol\";\n\ncontract Swap is\n    ISwap,\n    ReentrancyGuardUpgradeable,\n    OwnableUpgradeable,\n    SwapStorage\n{\n    using SafeERC20 for IERC20;\n\n    uint256 public immutable DOMAIN_CHAIN_ID;\n\n    bytes32 public constant DOMAIN_TYPEHASH =\n        keccak256(\n            abi.encodePacked(\n                \"EIP712Domain(\",\n                \"string name,\",\n                \"string version,\",\n                \"uint256 chainId,\",\n                \"address verifyingContract\",\n                \")\"\n            )\n        );\n\n    bytes32 public constant BID_TYPEHASH =\n        keccak256(\n            abi.encodePacked(\n                \"Bid(\",\n                \"uint256 swapId,\",\n                \"uint256 nonce,\",\n                \"address signerWallet,\",\n                \"address buyer,\",\n                \"uint256 sellAmount,\",\n                \"uint256 buyAmount,\",\n                \"address referrer\",\n                \")\"\n            )\n        );\n\n    uint256 public constant MAX_PERCENTAGE = 1000000;\n    uint256 public constant MAX_FEE = 125000; // 12.5%\n    uint256 internal constant MAX_ERROR_COUNT = 10;\n    uint256 internal constant OTOKEN_DECIMALS = 8;\n\n    /************************************************\n     *  CONSTRUCTOR\n     ***********************************************/\n\n    constructor() {\n        uint256 currentChainId = getChainId();\n        DOMAIN_CHAIN_ID = currentChainId;\n    }\n\n    /************************************************\n     *  INITIALIZATION\n     ***********************************************/\n\n    function initialize(\n        string memory _domainName,\n        string memory _domainVersion,\n        address _owner\n    ) external initializer {\n        require(bytes(_domainName).length > 0, \"!_domainName\");\n        require(bytes(_domainVersion).length > 0, \"!_domainVersion\");\n        require(_owner != address(0), \"!_owner\");\n\n        __ReentrancyGuard_init();\n        __Ownable_init();\n        transferOwnership(_owner);\n\n        DOMAIN_NAME = keccak256(bytes(_domainName));\n        DOMAIN_VERSION = keccak256(bytes(_domainVersion));\n        DOMAIN_SEPARATOR = keccak256(\n            abi.encode(\n                DOMAIN_TYPEHASH,\n                DOMAIN_NAME,\n                DOMAIN_VERSION,\n                DOMAIN_CHAIN_ID,\n                this\n            )\n        );\n    }\n\n    /************************************************\n     *  SETTER\n     ***********************************************/\n\n    /**\n     * @notice Sets the referral fee for a specific referrer\n     * @param referrer is the address of the referrer\n     * @param fee is the fee in percent in 2 decimals\n     */\n    function setFee(address referrer, uint256 fee) external onlyOwner {\n        require(referrer != address(0), \"Referrer cannot be the zero address\");\n        require(fee < MAX_FEE, \"Fee exceeds maximum\");\n\n        referralFees[referrer] = fee;\n\n        emit SetFee(referrer, fee);\n    }\n\n    /************************************************\n     *  OFFER CREATION AND SETTLEMENT\n     ***********************************************/\n\n    /**\n     * @notice Create a new offer available for swap\n     * @param oToken token offered by seller\n     * @param biddingToken token asked by seller\n     * @param minPrice minimum price of oToken denominated in biddingToken\n     * @param minBidSize minimum amount of oToken requested in a single bid\n     * @param totalSize amount of oToken offered by seller\n     */\n    function createOffer(\n        address oToken,\n        address biddingToken,\n        uint96 minPrice,\n        uint96 minBidSize,\n        uint128 totalSize\n    ) external override returns (uint256 swapId) {\n        require(oToken != address(0), \"oToken cannot be the zero address\");\n        require(\n            biddingToken != address(0),\n            \"BiddingToken cannot be the zero address\"\n        );\n        require(minPrice > 0, \"MinPrice must be larger than zero\");\n        require(minBidSize > 0, \"MinBidSize must be larger than zero\");\n        require(minBidSize <= totalSize, \"MinBidSize exceeds total size\");\n\n        if (IOtoken(oToken).isPut()) {\n            require(\n                priceFeeds[IOtoken(oToken).underlyingAsset()] != address(0),\n                \"No price feed set\"\n            );\n        }\n\n        // Check seller allowance\n        uint256 sellerAllowance =\n            IERC20(oToken).allowance(msg.sender, address(this));\n        require(sellerAllowance >= totalSize, \"Seller allowance low\");\n\n        // Check seller balance\n        uint256 sellerBalance = IERC20(oToken).balanceOf(msg.sender);\n        require(sellerBalance >= totalSize, \"Seller balance low\");\n\n        offersCounter += 1;\n\n        swapId = offersCounter;\n\n        swapOffers[swapId].seller = msg.sender;\n        swapOffers[swapId].oToken = oToken;\n        swapOffers[swapId].biddingToken = biddingToken;\n        swapOffers[swapId].minBidSize = minBidSize;\n        swapOffers[swapId].minPrice = minPrice;\n        swapOffers[swapId].totalSize = totalSize;\n        swapOffers[swapId].availableSize = totalSize;\n        // We warm the storage slot with 1 wei so we avoid a cold SSTORE\n        swapOffers[swapId].totalSales = 1;\n\n        emit NewOffer(\n            swapId,\n            msg.sender,\n            oToken,\n            biddingToken,\n            minPrice,\n            minBidSize,\n            totalSize\n        );\n    }\n\n    /**\n     * @notice Settles the swap offering by iterating through the bids\n     * @param swapId unique identifier of the swap offer\n     * @param bids bids for swaps\n     */\n    function settleOffer(uint256 swapId, Bid[] calldata bids)\n        external\n        override\n        nonReentrant\n    {\n        Offer storage offer = swapOffers[swapId];\n\n        address seller = offer.seller;\n        require(\n            seller == msg.sender,\n            \"Only seller can settle or offer doesn't exist\"\n        );\n        require(offer.availableSize > 0, \"Offer fully settled\");\n\n        uint256 totalSales;\n        OfferDetails memory offerDetails;\n        offerDetails.seller = seller;\n        offerDetails.oToken = offer.oToken;\n        offerDetails.biddingToken = offer.biddingToken;\n        offerDetails.minPrice = offer.minPrice;\n        offerDetails.minBidSize = offer.minBidSize;\n\n        for (uint256 i = 0; i < bids.length; i++) {\n            require(\n                swapId == bids[i].swapId,\n                \"Offer and bid swapId mismatched\"\n            );\n\n            _swap(offerDetails, offer, bids[i]);\n            totalSales += bids[i].sellAmount;\n        }\n\n        bool fullySettled = offer.availableSize == 0;\n\n        // Deduct the initial 1 wei offset if offer is fully settled\n        offer.totalSales += totalSales - (fullySettled ? 1 : 0);\n\n        if (fullySettled) {\n            offer.seller = address(0);\n            offer.oToken = address(0);\n            offer.biddingToken = address(0);\n            offer.minBidSize = 0;\n            offer.minPrice = 0;\n\n            emit SettleOffer(swapId);\n        }\n    }\n\n    /**\n     * @notice Authorize a signer\n     * @param signer address Wallet of the signer to authorize\n     * @dev Emits an Authorize event\n     */\n    function authorize(address signer) external override {\n        require(signer != address(0), \"SIGNER_INVALID\");\n        authorized[msg.sender] = signer;\n        emit Authorize(signer, msg.sender);\n    }\n\n    /**\n     * @notice Revoke the signer\n     * @dev Emits a Revoke event\n     */\n    function revoke() external override {\n        address tmp = authorized[msg.sender];\n        delete authorized[msg.sender];\n        emit Revoke(tmp, msg.sender);\n    }\n\n    /**\n     * @notice Cancel one or more nonces\n     * @dev Cancelled nonces are marked as used\n     * @dev Emits a Cancel event\n     * @dev Out of gas may occur in arrays of length > 400\n     * @param nonces uint256[] List of nonces to cancel\n     */\n    function cancelNonce(uint256[] calldata nonces) external override {\n        for (uint256 i = 0; i < nonces.length; i++) {\n            uint256 nonce = nonces[i];\n            if (_markNonceAsUsed(msg.sender, nonce)) {\n                emit Cancel(nonce, msg.sender);\n            }\n        }\n    }\n\n    /************************************************\n     *  PUBLIC VIEW FUNCTIONS\n     ***********************************************/\n\n    /**\n     * @notice Validates Swap bid for any potential errors\n     * @param bid Bid struct containing bid details\n     * @return tuple of error count and bytes32[] memory array of error messages\n     */\n    function check(Bid calldata bid)\n        external\n        view\n        override\n        returns (uint256, bytes32[] memory)\n    {\n        Offer memory offer = swapOffers[bid.swapId];\n        require(offer.seller != address(0), \"Offer does not exist\");\n\n        bytes32[] memory errors = new bytes32[](MAX_ERROR_COUNT);\n\n        uint256 errCount;\n\n        // Check signature\n        address signatory = _getSignatory(bid);\n\n        if (signatory == address(0)) {\n            errors[errCount] = \"SIGNATURE_INVALID\";\n            errCount++;\n        }\n\n        if (\n            bid.buyer != signatory &&\n            authorized[bid.buyer] != signatory\n        ) {\n            errors[errCount] = \"UNAUTHORIZED\";\n            errCount++;\n        }\n\n        // Check nonce\n        if (nonceUsed(signatory, bid.nonce)) {\n            errors[errCount] = \"NONCE_ALREADY_USED\";\n            errCount++;\n        }\n\n        // Check bid size\n        if (bid.buyAmount < offer.minBidSize) {\n            errors[errCount] = \"BID_TOO_SMALL\";\n            errCount++;\n        }\n        if (bid.buyAmount > offer.availableSize) {\n            errors[errCount] = \"BID_EXCEED_AVAILABLE_SIZE\";\n            errCount++;\n        }\n\n        // Check bid price\n        uint256 bidPrice =\n            (bid.sellAmount * 10**OTOKEN_DECIMALS) / bid.buyAmount;\n        if (bidPrice < offer.minPrice) {\n            errors[errCount] = \"PRICE_TOO_LOW\";\n            errCount++;\n        }\n\n        // Check buyer allowance\n        uint256 buyerAllowance =\n            IERC20(offer.biddingToken).allowance(\n                bid.buyer,\n                address(this)\n            );\n        if (buyerAllowance < bid.sellAmount) {\n            errors[errCount] = \"BUYER_ALLOWANCE_LOW\";\n            errCount++;\n        }\n\n        // Check buyer balance\n        uint256 buyerBalance =\n            IERC20(offer.biddingToken).balanceOf(bid.buyer);\n        if (buyerBalance < bid.sellAmount) {\n            errors[errCount] = \"BUYER_BALANCE_LOW\";\n            errCount++;\n        }\n\n        return (errCount, errors);\n    }\n\n    /**\n     * @notice Returns the average settlement price for a swap offer\n     * @param swapId unique identifier of the swap offer\n     */\n    function averagePriceForOffer(uint256 swapId)\n        external\n        view\n        override\n        returns (uint256)\n    {\n        Offer storage offer = swapOffers[swapId];\n        require(offer.totalSize != 0, \"Offer does not exist\");\n\n        uint256 availableSize = offer.availableSize;\n\n        // Deduct the initial 1 wei offset if offer is not fully settled\n        uint256 adjustment = availableSize != 0 ? 1 : 0;\n\n        return\n            ((offer.totalSales - adjustment) * (10**8)) /\n            (offer.totalSize - availableSize);\n    }\n\n    /**\n     * @notice Returns true if the nonce has been used\n     * @param signer address Address of the signer\n     * @param nonce uint256 Nonce being checked\n     */\n    function nonceUsed(address signer, uint256 nonce)\n        public\n        view\n        override\n        returns (bool)\n    {\n        uint256 groupKey = nonce / 256;\n        uint256 indexInGroup = nonce % 256;\n        return (_nonceGroups[signer][groupKey] >> indexInGroup) & 1 == 1;\n    }\n\n    /************************************************\n     *  INTERNAL FUNCTIONS\n     ***********************************************/\n\n    /**\n     * @notice Swap Atomic ERC20 Swap\n     * @param details Details of offering\n     * @param offer Offer struct containing offer details\n     * @param bid Bid struct containing bid details\n     */\n    function _swap(\n        OfferDetails memory details,\n        Offer storage offer,\n        Bid calldata bid\n    ) internal {\n        require(DOMAIN_CHAIN_ID == getChainId(), \"CHAIN_ID_CHANGED\");\n\n        address signatory = _getSignatory(bid);\n\n        require(signatory != address(0), \"SIGNATURE_INVALID\");\n\n        if (bid.signerWallet != signatory) {\n            require(authorized[bid.signerWallet] == signatory, \"UNAUTHORIZED\");\n        }\n\n        require(_markNonceAsUsed(signatory, bid.nonce), \"NONCE_ALREADY_USED\");\n        require(\n            bid.buyAmount <= offer.availableSize,\n            \"BID_EXCEED_AVAILABLE_SIZE\"\n        );\n        require(bid.buyAmount >= details.minBidSize, \"BID_TOO_SMALL\");\n\n        // Ensure min. price is met\n        uint256 bidPrice =\n            (bid.sellAmount * 10**OTOKEN_DECIMALS) / bid.buyAmount;\n        require(bidPrice >= details.minPrice, \"PRICE_TOO_LOW\");\n\n        // don't have to do a uint128 check because we already check\n        // that bid.buyAmount <= offer.availableSize\n        offer.availableSize -= uint128(bid.buyAmount);\n\n        // Transfer token from sender to signer\n        IERC20(details.oToken).safeTransferFrom(\n            details.seller,\n            bid.buyer,\n            bid.buyAmount\n        );\n\n        // Transfer to referrer if any\n        uint256 feeAmount;\n        if (bid.referrer != address(0)) {\n            uint256 feePercent = referralFees[bid.referrer];\n\n            if (feePercent > 0) {\n                feeAmount = calculateReferralFee(\n                    details.oToken,\n                    feePercent,\n                    bid.buyAmount,\n                    bid.sellAmount\n                );\n\n                IERC20(details.biddingToken).safeTransferFrom(\n                    bid.buyer,\n                    bid.referrer,\n                    feeAmount\n                );\n            }\n        }\n\n        // Transfer token from signer to recipient\n        IERC20(details.biddingToken).safeTransferFrom(\n            bid.buyer,\n            details.seller,\n            bid.sellAmount - feeAmount\n        );\n\n        // Emit a Swap event\n        emit Swap(\n            bid.swapId,\n            bid.nonce,\n            bid.buyer,\n            bid.sellAmount,\n            bid.buyAmount,\n            bid.referrer,\n            feeAmount\n        );\n    }\n\n    /**\n     * @notice Marks a nonce as used for the given signer\n     * @param signer address Address of the signer for which to mark the nonce as used\n     * @param nonce uint256 Nonce to be marked as used\n     * @return bool True if the nonce was not marked as used already\n     */\n    function _markNonceAsUsed(address signer, uint256 nonce)\n        internal\n        returns (bool)\n    {\n        uint256 groupKey = nonce / 256;\n        uint256 indexInGroup = nonce % 256;\n        uint256 group = _nonceGroups[signer][groupKey];\n\n        // If it is already used, return false\n        if ((group >> indexInGroup) & 1 == 1) {\n            return false;\n        }\n\n        _nonceGroups[signer][groupKey] = group | (uint256(1) << indexInGroup);\n\n        return true;\n    }\n\n    /**\n     * @notice Recover the signatory from a signature\n     * @param bid Bid struct containing bid details\n     */\n    function _getSignatory(Bid calldata bid) internal view returns (address) {\n        return\n            ecrecover(\n                keccak256(\n                    abi.encodePacked(\n                        \"\\x19\\x01\",\n                        DOMAIN_SEPARATOR,\n                        keccak256(\n                            abi.encode(\n                                BID_TYPEHASH,\n                                bid.swapId,\n                                bid.nonce,\n                                bid.signerWallet,\n                                bid.buyer,\n                                bid.sellAmount,\n                                bid.buyAmount,\n                                bid.referrer\n                            )\n                        )\n                    )\n                ),\n                bid.v,\n                bid.r,\n                bid.s\n            );\n    }\n\n    /**\n     * This function assumes that all CALL premiums are denominated in the Offer.biddingToken\n     * This could easily change if we enabled Paradigm for Treasury - Calls are sold for USDC.\n     * It assumes that all PUT premiums are denominated in USDC.\n     */\n    function calculateReferralFee(\n        address otokenAddress,\n        uint256 feePercent,\n        uint256 numContracts,\n        uint256 premium\n    ) public view returns (uint256) {\n        IOtoken otoken = IOtoken(otokenAddress);\n        uint256 maxFee = (premium * MAX_FEE) / MAX_PERCENTAGE;\n        uint256 fee;\n\n        if (otoken.isPut()) {\n            uint256 marketPrice = getMarketPrice(otoken.underlyingAsset());\n            // both numContracts and marketPrice are 10**8\n            // then you scale it down to 10**6 because of USDC\n            uint256 notional = (numContracts * marketPrice) / 10**10;\n            fee = (notional * feePercent) / MAX_PERCENTAGE;\n        } else {\n            IERC20Detailed underlying =\n                IERC20Detailed(otoken.underlyingAsset());\n            uint256 underlyingDecimals = underlying.decimals();\n            uint256 numContractsInUnderlying;\n            if (underlyingDecimals < 8) {\n                numContractsInUnderlying =\n                    numContracts /\n                    10**(underlyingDecimals - 8);\n            } else {\n                numContractsInUnderlying =\n                    numContracts *\n                    10**(underlyingDecimals - 8);\n            }\n            fee = (numContractsInUnderlying * feePercent) / MAX_PERCENTAGE;\n        }\n\n        if (fee > maxFee) {\n            return maxFee;\n        }\n        return fee;\n    }\n\n    function getMarketPrice(address asset) public view returns (uint256) {\n        address feed = priceFeeds[asset];\n        require(feed != address(0), \"NO_PRICE_FEED_SET\");\n        (\n            ,\n            /*uint80 roundID*/\n            int256 price,\n            ,\n            ,\n\n        ) =\n            /*uint startedAt*/\n            /*uint timeStamp*/\n            /*uint80 answeredInRound*/\n            AggregatorV3Interface(feed).latestRoundData();\n\n        require(price > 0, \"INVALID_PRICE_FEED\");\n\n        return uint256(price);\n    }\n\n    function setPriceFeed(address asset, address aggregator)\n        external\n        onlyOwner\n    {\n        priceFeeds[asset] = aggregator;\n        emit SetPriceFeed(asset, aggregator);\n    }\n\n    /**\n     * @notice Returns the current chainId using the chainid opcode\n     * @return id uint256 The chain id\n     */\n    function getChainId() internal view returns (uint256 id) {\n        // no-inline-assembly\n        assembly {\n            id := chainid()\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}