Token Jarvis Synthetic Legacy French Franc

 

Overview ERC-20

Price
$0.00 @ 0.000000 MATIC
Fully Diluted Market Cap
Total Supply:
3,263.65726 jFRF

Holders:
19 addresses

Transfers:
-

Contract:
0x00FAE04063Ea815BF371FB95Af98c38BFA3063560x00FAE04063Ea815BF371FB95Af98c38BFA306356

Decimals:
18

Social Profiles:
Not Available, Update ?

 
Loading
[ Download CSV Export  ] 
Loading
[ Download CSV Export  ] 
Loading

Click here to update the token ICO / general information
# Exchange Pair Price  24H Volume % Volume
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FixedRateCurrency

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-10-18
*/

// File: @jarvis-network/synthereum-contracts/contracts/core/Constants.sol


pragma solidity ^0.8.4;

/**
 * @title Stores common interface names used throughout Synthereum.
 */
library SynthereumInterfaces {
  bytes32 public constant Deployer = 'Deployer';
  bytes32 public constant FactoryVersioning = 'FactoryVersioning';
  bytes32 public constant TokenFactory = 'TokenFactory';
  bytes32 public constant PoolRegistry = 'PoolRegistry';
  bytes32 public constant SelfMintingRegistry = 'SelfMintingRegistry';
  bytes32 public constant PriceFeed = 'PriceFeed';
  bytes32 public constant Manager = 'Manager';
  bytes32 public constant SelfMintingController = 'SelfMintingController';
}

library FactoryInterfaces {
  bytes32 public constant PoolFactory = 'PoolFactory';
  bytes32 public constant DerivativeFactory = 'DerivativeFactory';
  bytes32 public constant SelfMintingFactory = 'SelfMintingFactory';
}

// File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol



pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

// File: @jarvis-network/synthereum-contracts/contracts/base/interfaces/IRole.sol


pragma solidity ^0.8.4;

/**
 * @title Access role interface
 */
interface IRole {
  /**
   * @dev Returns `true` if `account` has been granted `role`.
   */
  function hasRole(bytes32 role, address account) external view returns (bool);

  /**
   * @dev Returns the number of accounts that have `role`. Can be used
   * together with {getRoleMember} to enumerate all bearers of a role.
   */
  function getRoleMemberCount(bytes32 role) external view returns (uint256);

  /**
   * @dev Returns one of the accounts that have `role`. `index` must be a
   * value between 0 and {getRoleMemberCount}, non-inclusive.
   *
   */
  function getRoleMember(bytes32 role, uint256 index)
    external
    view
    returns (address);

  /**
   * @dev Returns the admin role that controls `role`. See {grantRole} and
   * {revokeRole}.
   */
  function getRoleAdmin(bytes32 role) external view returns (bytes32);

  /**
   * @dev Grants `role` to `account`.
   *
   * - the caller must have ``role``'s admin role.
   */
  function grantRole(bytes32 role, address account) external;

  /**
   * @dev Revokes `role` from `account`.
   *
   * - the caller must have ``role``'s admin role.
   */
  function revokeRole(bytes32 role, address account) external;

  /**
   * @dev Revokes `role` from the calling account.
   *
   * Roles are often managed via {grantRole} and {revokeRole}: this function's
   * purpose is to provide a mechanism for accounts to lose their privileges
   * if they are compromised (such as when a trusted device is misplaced).
   *
   * - the caller must be `account`.
   */
  function renounceRole(bytes32 role, address account) external;
}

// File: @jarvis-network/synthereum-contracts/contracts/core/interfaces/IFinder.sol


pragma solidity ^0.8.4;

/**
 * @title Provides addresses of the contracts implementing certain interfaces.
 */
interface ISynthereumFinder {
  /**
   * @notice Updates the address of the contract that implements `interfaceName`.
   * @param interfaceName bytes32 encoding of the interface name that is either changed or registered.
   * @param implementationAddress address of the deployed contract that implements the interface.
   */
  function changeImplementationAddress(
    bytes32 interfaceName,
    address implementationAddress
  ) external;

  /**
   * @notice Gets the address of the contract that implements the given `interfaceName`.
   * @param interfaceName queried interface.
   * @return implementationAddress Address of the deployed contract that implements the interface.
   */
  function getImplementationAddress(bytes32 interfaceName)
    external
    view
    returns (address);
}

// File: @openzeppelin/contracts/utils/math/SignedSafeMath.sol



pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SignedSafeMath {
    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        return a / b;
    }

    /**
     * @dev Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        return a - b;
    }

    /**
     * @dev Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        return a + b;
    }
}

// File: @openzeppelin/contracts/utils/Context.sol



pragma solidity ^0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

// File: @openzeppelin/contracts/utils/Address.sol



pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

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

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol



pragma solidity ^0.8.0;

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

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

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

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

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

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

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

// File: @jarvis-network/synthereum-contracts/contracts/core/registries/interfaces/IRegistry.sol


pragma solidity ^0.8.4;


/**
 * @title Provides interface with functions of SynthereumRegistry
 */

interface ISynthereumRegistry {
  /**
   * @notice Allow the deployer to register an element
   * @param syntheticTokenSymbol Symbol of the syntheticToken
   * @param collateralToken Collateral ERC20 token of the element deployed
   * @param version Version of the element deployed
   * @param element Address of the element deployed
   */
  function register(
    string calldata syntheticTokenSymbol,
    IERC20 collateralToken,
    uint8 version,
    address element
  ) external;

  /**
   * @notice Returns if a particular element exists or not
   * @param syntheticTokenSymbol Synthetic token symbol of the element
   * @param collateralToken ERC20 contract of collateral currency
   * @param version Version of the element
   * @param element Contract of the element to check
   * @return isElementDeployed Returns true if a particular element exists, otherwise false
   */
  function isDeployed(
    string calldata syntheticTokenSymbol,
    IERC20 collateralToken,
    uint8 version,
    address element
  ) external view returns (bool isElementDeployed);

  /**
   * @notice Returns all the elements with partcular symbol, collateral and version
   * @param syntheticTokenSymbol Synthetic token symbol of the element
   * @param collateralToken ERC20 contract of collateral currency
   * @param version Version of the element
   * @return List of all elements
   */
  function getElements(
    string calldata syntheticTokenSymbol,
    IERC20 collateralToken,
    uint8 version
  ) external view returns (address[] memory);

  /**
   * @notice Returns all the synthetic token symbol used
   * @return List of all synthetic token symbol
   */
  function getSyntheticTokens() external view returns (string[] memory);

  /**
   * @notice Returns all the versions used
   * @return List of all versions
   */
  function getVersions() external view returns (uint8[] memory);

  /**
   * @notice Returns all the collaterals used
   * @return List of all collaterals
   */
  function getCollaterals() external view returns (address[] memory);
}

// File: @jarvis-network/synthereum-contracts/contracts/derivative/self-minting/common/interfaces/ISelfMintingDerivativeDeployment.sol


pragma solidity ^0.8.4;



/** @title Interface for interacting with SelfMintingDerivativeDeployment contract
 */
interface ISelfMintingDerivativeDeployment {
  /** @notice Returns the address of the SynthereumFinder contract
   */
  function synthereumFinder() external view returns (ISynthereumFinder finder);

  /** @notice Returns the address of the collateralCurrency contract
   */
  function collateralCurrency() external view returns (IERC20 collateral);

  /** @notice Returns the address of the synthetic token contract
   */
  function tokenCurrency() external view returns (IERC20 syntheticCurrency);

  /** @notice Returns the synthetic token symbol
   */
  function syntheticTokenSymbol() external view returns (string memory symbol);

  /** @notice Returns the version of the deployed self-minting derivative
   */
  function version() external view returns (uint8 selfMintingversion);
}

// File: @jarvis-network/synthereum-contracts/contracts/derivative/common/interfaces/IDerivativeDeployment.sol


pragma solidity ^0.8.4;


/**
 * @title Interface that a derivative MUST have in order to be included in the deployer
 */
interface IDerivativeDeployment {
  /**
   * @notice Gets the collateral currency of the derivative
   * @return collateral Collateral currency
   */
  function collateralCurrency() external view returns (IERC20 collateral);

  /**
   * @notice Get the token currency of the derivative
   * @return syntheticCurrency Synthetic token
   */
  function tokenCurrency() external view returns (IERC20 syntheticCurrency);

  /**
   * @notice Accessor method for the list of members with admin role
   * @return array of addresses with admin role
   */
  function getAdminMembers() external view returns (address[] memory);

  /**
   * @notice Accessor method for the list of members with pool role
   * @return array of addresses with pool role
   */
  function getPoolMembers() external view returns (address[] memory);
}

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol



pragma solidity ^0.8.0;


/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
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);
}

// File: @openzeppelin/contracts/token/ERC20/ERC20.sol



pragma solidity ^0.8.0;




/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The defaut value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        _approve(sender, _msgSender(), currentAllowance - amount);

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        _approve(_msgSender(), spender, currentAllowance - subtractedValue);

        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        _balances[sender] = senderBalance - amount;
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        _balances[account] = accountBalance - amount;
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

// File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol



pragma solidity ^0.8.0;



/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// File: @openzeppelin/contracts/utils/math/SafeMath.sol



pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

// File: @uma/core/contracts/common/implementation/FixedPoint.sol


pragma solidity ^0.8.0;



/**
 * @title Library for fixed point arithmetic on uints
 */
library FixedPoint {
    using SafeMath for uint256;
    using SignedSafeMath for int256;

    // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5".
    // For unsigned values:
    //   This can represent a value up to (2^256 - 1)/10^18 = ~10^59. 10^59 will be stored internally as uint256 10^77.
    uint256 private constant FP_SCALING_FACTOR = 10**18;

    // --------------------------------------- UNSIGNED -----------------------------------------------------------------------------
    struct Unsigned {
        uint256 rawValue;
    }

    /**
     * @notice Constructs an `Unsigned` from an unscaled uint, e.g., `b=5` gets stored internally as `5*(10**18)`.
     * @param a uint to convert into a FixedPoint.
     * @return the converted FixedPoint.
     */
    function fromUnscaledUint(uint256 a) internal pure returns (Unsigned memory) {
        return Unsigned(a.mul(FP_SCALING_FACTOR));
    }

    /**
     * @notice Whether `a` is equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if equal, or False.
     */
    function isEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue == fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if equal, or False.
     */
    function isEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue == b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue > b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue > fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue > b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue >= b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue >= fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue >= b.rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a < b`, or False.
     */
    function isLessThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue < b.rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a < b`, or False.
     */
    function isLessThan(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue < fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a < b`, or False.
     */
    function isLessThan(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue < b.rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue <= b.rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue <= fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue <= b.rawValue;
    }

    /**
     * @notice The minimum of `a` and `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the minimum of `a` and `b`.
     */
    function min(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return a.rawValue < b.rawValue ? a : b;
    }

    /**
     * @notice The maximum of `a` and `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the maximum of `a` and `b`.
     */
    function max(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return a.rawValue > b.rawValue ? a : b;
    }

    /**
     * @notice Adds two `Unsigned`s, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the sum of `a` and `b`.
     */
    function add(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.add(b.rawValue));
    }

    /**
     * @notice Adds an `Unsigned` to an unscaled uint, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the sum of `a` and `b`.
     */
    function add(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return add(a, fromUnscaledUint(b));
    }

    /**
     * @notice Subtracts two `Unsigned`s, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the difference of `a` and `b`.
     */
    function sub(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.sub(b.rawValue));
    }

    /**
     * @notice Subtracts an unscaled uint256 from an `Unsigned`, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the difference of `a` and `b`.
     */
    function sub(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return sub(a, fromUnscaledUint(b));
    }

    /**
     * @notice Subtracts an `Unsigned` from an unscaled uint256, reverting on overflow.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return the difference of `a` and `b`.
     */
    function sub(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return sub(fromUnscaledUint(a), b);
    }

    /**
     * @notice Multiplies two `Unsigned`s, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mul(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        // There are two caveats with this computation:
        // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is
        // stored internally as a uint256 ~10^59.
        // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which
        // would round to 3, but this computation produces the result 2.
        // No need to use SafeMath because FP_SCALING_FACTOR != 0.
        return Unsigned(a.rawValue.mul(b.rawValue) / FP_SCALING_FACTOR);
    }

    /**
     * @notice Multiplies an `Unsigned` and an unscaled uint256, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the product of `a` and `b`.
     */
    function mul(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.mul(b));
    }

    /**
     * @notice Multiplies two `Unsigned`s and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mulCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        uint256 mulRaw = a.rawValue.mul(b.rawValue);
        uint256 mulFloor = mulRaw / FP_SCALING_FACTOR;
        uint256 mod = mulRaw.mod(FP_SCALING_FACTOR);
        if (mod != 0) {
            return Unsigned(mulFloor.add(1));
        } else {
            return Unsigned(mulFloor);
        }
    }

    /**
     * @notice Multiplies an `Unsigned` and an unscaled uint256 and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mulCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        // Since b is an int, there is no risk of truncation and we can just mul it normally
        return Unsigned(a.rawValue.mul(b));
    }

    /**
     * @notice Divides one `Unsigned` by an `Unsigned`, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a FixedPoint numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        // There are two caveats with this computation:
        // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.
        // 10^41 is stored internally as a uint256 10^59.
        // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which
        // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.
        return Unsigned(a.rawValue.mul(FP_SCALING_FACTOR).div(b.rawValue));
    }

    /**
     * @notice Divides one `Unsigned` by an unscaled uint256, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.div(b));
    }

    /**
     * @notice Divides one unscaled uint256 by an `Unsigned`, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a uint256 numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return div(fromUnscaledUint(a), b);
    }

    /**
     * @notice Divides one `Unsigned` by an `Unsigned` and "ceil's" the quotient, reverting on overflow or division by 0.
     * @param a a FixedPoint numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function divCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        uint256 aScaled = a.rawValue.mul(FP_SCALING_FACTOR);
        uint256 divFloor = aScaled.div(b.rawValue);
        uint256 mod = aScaled.mod(b.rawValue);
        if (mod != 0) {
            return Unsigned(divFloor.add(1));
        } else {
            return Unsigned(divFloor);
        }
    }

    /**
     * @notice Divides one `Unsigned` by an unscaled uint256 and "ceil's" the quotient, reverting on overflow or division by 0.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function divCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        // Because it is possible that a quotient gets truncated, we can't just call "Unsigned(a.rawValue.div(b))"
        // similarly to mulCeil with a uint256 as the second parameter. Therefore we need to convert b into an Unsigned.
        // This creates the possibility of overflow if b is very large.
        return divCeil(a, fromUnscaledUint(b));
    }

    /**
     * @notice Raises an `Unsigned` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.
     * @dev This will "floor" the result.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return output is `a` to the power of `b`.
     */
    function pow(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory output) {
        output = fromUnscaledUint(1);
        for (uint256 i = 0; i < b; i = i.add(1)) {
            output = mul(output, a);
        }
    }

    // ------------------------------------------------- SIGNED -------------------------------------------------------------
    // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5".
    // For signed values:
    //   This can represent a value up (or down) to +-(2^255 - 1)/10^18 = ~10^58. 10^58 will be stored internally as int256 10^76.
    int256 private constant SFP_SCALING_FACTOR = 10**18;

    struct Signed {
        int256 rawValue;
    }

    function fromSigned(Signed memory a) internal pure returns (Unsigned memory) {
        require(a.rawValue >= 0, "Negative value provided");
        return Unsigned(uint256(a.rawValue));
    }

    function fromUnsigned(Unsigned memory a) internal pure returns (Signed memory) {
        require(a.rawValue <= uint256(type(int256).max), "Unsigned too large");
        return Signed(int256(a.rawValue));
    }

    /**
     * @notice Constructs a `Signed` from an unscaled int, e.g., `b=5` gets stored internally as `5*(10**18)`.
     * @param a int to convert into a FixedPoint.Signed.
     * @return the converted FixedPoint.Signed.
     */
    function fromUnscaledInt(int256 a) internal pure returns (Signed memory) {
        return Signed(a.mul(SFP_SCALING_FACTOR));
    }

    /**
     * @notice Whether `a` is equal to `b`.
     * @param a a FixedPoint.Signed.
     * @param b a int256.
     * @return True if equal, or False.
     */
    function isEqual(Signed memory a, int256 b) internal pure returns (bool) {
        return a.rawValue == fromUnscaledInt(b).rawValue;
    }

    /**
     * @notice Whether `a` is equal to `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return True if equal, or False.
     */
    function isEqual(Signed memory a, Signed memory b) internal pure returns (bool) {
        return a.rawValue == b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(Signed memory a, Signed memory b) internal pure returns (bool) {
        return a.rawValue > b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a FixedPoint.Signed.
     * @param b an int256.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(Signed memory a, int256 b) internal pure returns (bool) {
        return a.rawValue > fromUnscaledInt(b).rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a an int256.
     * @param b a FixedPoint.Signed.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(int256 a, Signed memory b) internal pure returns (bool) {
        return fromUnscaledInt(a).rawValue > b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) {
        return a.rawValue >= b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.Signed.
     * @param b an int256.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {
        return a.rawValue >= fromUnscaledInt(b).rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a an int256.
     * @param b a FixedPoint.Signed.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) {
        return fromUnscaledInt(a).rawValue >= b.rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return True if `a < b`, or False.
     */
    function isLessThan(Signed memory a, Signed memory b) internal pure returns (bool) {
        return a.rawValue < b.rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a FixedPoint.Signed.
     * @param b an int256.
     * @return True if `a < b`, or False.
     */
    function isLessThan(Signed memory a, int256 b) internal pure returns (bool) {
        return a.rawValue < fromUnscaledInt(b).rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a an int256.
     * @param b a FixedPoint.Signed.
     * @return True if `a < b`, or False.
     */
    function isLessThan(int256 a, Signed memory b) internal pure returns (bool) {
        return fromUnscaledInt(a).rawValue < b.rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) {
        return a.rawValue <= b.rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.Signed.
     * @param b an int256.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {
        return a.rawValue <= fromUnscaledInt(b).rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a an int256.
     * @param b a FixedPoint.Signed.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) {
        return fromUnscaledInt(a).rawValue <= b.rawValue;
    }

    /**
     * @notice The minimum of `a` and `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the minimum of `a` and `b`.
     */
    function min(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        return a.rawValue < b.rawValue ? a : b;
    }

    /**
     * @notice The maximum of `a` and `b`.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the maximum of `a` and `b`.
     */
    function max(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        return a.rawValue > b.rawValue ? a : b;
    }

    /**
     * @notice Adds two `Signed`s, reverting on overflow.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the sum of `a` and `b`.
     */
    function add(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        return Signed(a.rawValue.add(b.rawValue));
    }

    /**
     * @notice Adds an `Signed` to an unscaled int, reverting on overflow.
     * @param a a FixedPoint.Signed.
     * @param b an int256.
     * @return the sum of `a` and `b`.
     */
    function add(Signed memory a, int256 b) internal pure returns (Signed memory) {
        return add(a, fromUnscaledInt(b));
    }

    /**
     * @notice Subtracts two `Signed`s, reverting on overflow.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the difference of `a` and `b`.
     */
    function sub(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        return Signed(a.rawValue.sub(b.rawValue));
    }

    /**
     * @notice Subtracts an unscaled int256 from an `Signed`, reverting on overflow.
     * @param a a FixedPoint.Signed.
     * @param b an int256.
     * @return the difference of `a` and `b`.
     */
    function sub(Signed memory a, int256 b) internal pure returns (Signed memory) {
        return sub(a, fromUnscaledInt(b));
    }

    /**
     * @notice Subtracts an `Signed` from an unscaled int256, reverting on overflow.
     * @param a an int256.
     * @param b a FixedPoint.Signed.
     * @return the difference of `a` and `b`.
     */
    function sub(int256 a, Signed memory b) internal pure returns (Signed memory) {
        return sub(fromUnscaledInt(a), b);
    }

    /**
     * @notice Multiplies two `Signed`s, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the product of `a` and `b`.
     */
    function mul(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        // There are two caveats with this computation:
        // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is
        // stored internally as an int256 ~10^59.
        // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which
        // would round to 3, but this computation produces the result 2.
        // No need to use SafeMath because SFP_SCALING_FACTOR != 0.
        return Signed(a.rawValue.mul(b.rawValue) / SFP_SCALING_FACTOR);
    }

    /**
     * @notice Multiplies an `Signed` and an unscaled int256, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.Signed.
     * @param b an int256.
     * @return the product of `a` and `b`.
     */
    function mul(Signed memory a, int256 b) internal pure returns (Signed memory) {
        return Signed(a.rawValue.mul(b));
    }

    /**
     * @notice Multiplies two `Signed`s and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the product of `a` and `b`.
     */
    function mulAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        int256 mulRaw = a.rawValue.mul(b.rawValue);
        int256 mulTowardsZero = mulRaw / SFP_SCALING_FACTOR;
        // Manual mod because SignedSafeMath doesn't support it.
        int256 mod = mulRaw % SFP_SCALING_FACTOR;
        if (mod != 0) {
            bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);
            int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);
            return Signed(mulTowardsZero.add(valueToAdd));
        } else {
            return Signed(mulTowardsZero);
        }
    }

    /**
     * @notice Multiplies an `Signed` and an unscaled int256 and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.Signed.
     * @param b a FixedPoint.Signed.
     * @return the product of `a` and `b`.
     */
    function mulAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) {
        // Since b is an int, there is no risk of truncation and we can just mul it normally
        return Signed(a.rawValue.mul(b));
    }

    /**
     * @notice Divides one `Signed` by an `Signed`, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a FixedPoint numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        // There are two caveats with this computation:
        // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.
        // 10^41 is stored internally as an int256 10^59.
        // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which
        // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.
        return Signed(a.rawValue.mul(SFP_SCALING_FACTOR).div(b.rawValue));
    }

    /**
     * @notice Divides one `Signed` by an unscaled int256, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a FixedPoint numerator.
     * @param b an int256 denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(Signed memory a, int256 b) internal pure returns (Signed memory) {
        return Signed(a.rawValue.div(b));
    }

    /**
     * @notice Divides one unscaled int256 by an `Signed`, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a an int256 numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(int256 a, Signed memory b) internal pure returns (Signed memory) {
        return div(fromUnscaledInt(a), b);
    }

    /**
     * @notice Divides one `Signed` by an `Signed` and "ceil's" the quotient, reverting on overflow or division by 0.
     * @param a a FixedPoint numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function divAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
        int256 aScaled = a.rawValue.mul(SFP_SCALING_FACTOR);
        int256 divTowardsZero = aScaled.div(b.rawValue);
        // Manual mod because SignedSafeMath doesn't support it.
        int256 mod = aScaled % b.rawValue;
        if (mod != 0) {
            bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);
            int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);
            return Signed(divTowardsZero.add(valueToAdd));
        } else {
            return Signed(divTowardsZero);
        }
    }

    /**
     * @notice Divides one `Signed` by an unscaled int256 and "ceil's" the quotient, reverting on overflow or division by 0.
     * @param a a FixedPoint numerator.
     * @param b an int256 denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function divAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) {
        // Because it is possible that a quotient gets truncated, we can't just call "Signed(a.rawValue.div(b))"
        // similarly to mulCeil with an int256 as the second parameter. Therefore we need to convert b into an Signed.
        // This creates the possibility of overflow if b is very large.
        return divAwayFromZero(a, fromUnscaledInt(b));
    }

    /**
     * @notice Raises an `Signed` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.
     * @dev This will "floor" the result.
     * @param a a FixedPoint.Signed.
     * @param b a uint256 (negative exponents are not allowed).
     * @return output is `a` to the power of `b`.
     */
    function pow(Signed memory a, uint256 b) internal pure returns (Signed memory output) {
        output = fromUnscaledInt(1);
        for (uint256 i = 0; i < b; i = i.add(1)) {
            output = mul(output, a);
        }
    }
}

// File: @jarvis-network/synthereum-contracts/contracts/derivative/common/interfaces/IDerivativeMain.sol


pragma solidity ^0.8.4;


/**
 * @title Interface for interacting with the Derivatives contracts
 */
interface IDerivativeMain {
  /** @notice Deposit funds to a certain derivative contract with specified sponsor
   * @param sponsor Address of the sponsor to which the funds will be deposited
   * @param collateralAmount Amount of funds to be deposited
   */
  function depositTo(
    address sponsor,
    FixedPoint.Unsigned memory collateralAmount
  ) external;

  /** @notice Deposit funds to the derivative contract where msg sender is the sponsor
   * @param collateralAmount Amount of funds to be deposited
   */
  function deposit(FixedPoint.Unsigned memory collateralAmount) external;

  /** @notice Fast withdraw excess collateral from a derivative contract
   * @param collateralAmount Amount of funds to be withdrawn
   */
  function withdraw(FixedPoint.Unsigned memory collateralAmount)
    external
    returns (FixedPoint.Unsigned memory amountWithdrawn);

  /** @notice Request of slow withdraw of collateral from derivative changing GCR
   * @param collateralAmount Amount of funds to be withdrawn
   */
  function requestWithdrawal(FixedPoint.Unsigned memory collateralAmount)
    external;

  /** @notice Execute withdraw if a slow withdraw request has passed
   */
  function withdrawPassedRequest()
    external
    returns (FixedPoint.Unsigned memory amountWithdrawn);

  /** @notice Cancel a slow withdraw request
   */
  function cancelWithdrawal() external;

  /** @notice Mint synthetic tokens
   * @param collateralAmount Amount of collateral to be locked
   * @param numTokens Amount of tokens to be minted based on collateralAmount
   */
  function create(
    FixedPoint.Unsigned memory collateralAmount,
    FixedPoint.Unsigned memory numTokens
  ) external;

  /** @notice Redeem collateral by burning synthetic tokens
   * @param numTokens Amount of synthetic tokens to be burned to unlock collateral
   */
  function redeem(FixedPoint.Unsigned memory numTokens)
    external
    returns (FixedPoint.Unsigned memory amountWithdrawn);

  /** @notice Burning an amount of synthetic tokens to increase GCR
   * @param numTokens Amount of synthetic tokens to be burned
   */
  function repay(FixedPoint.Unsigned memory numTokens) external;

  /** @notice Settles the withdraws from an emergency shutdown of a derivative
   */
  function settleEmergencyShutdown()
    external
    returns (FixedPoint.Unsigned memory amountWithdrawn);

  /** @notice Invokes an emergency shutdown of a derivative
   */
  function emergencyShutdown() external;

  /** @notice Remargin function
   */
  function remargin() external;

  /** @notice Allows withdrawing of excess ERC20 tokens
   * @param token The address of the ERC20 token
   */
  function trimExcess(IERC20 token)
    external
    returns (FixedPoint.Unsigned memory amount);

  /** @notice Gets the collateral locked by a certain sponsor
   * @param sponsor The address of the sponsor for which to return amount of collateral locked
   */
  function getCollateral(address sponsor)
    external
    view
    returns (FixedPoint.Unsigned memory collateralAmount);

  /** @notice Gets the address of the SynthereumFinder contract
   */
  function synthereumFinder() external view returns (ISynthereumFinder finder);

  /** @notice Gets the synthetic token symbol associated with the derivative
   */
  function syntheticTokenSymbol() external view returns (string memory symbol);

  /** @notice Gets the price identifier associated with the derivative
   */
  function priceIdentifier() external view returns (bytes32 identifier);

  /** @notice Gets the total collateral locked in a derivative
   */
  function totalPositionCollateral()
    external
    view
    returns (FixedPoint.Unsigned memory totalCollateral);

  /** @notice Gets the total synthetic tokens minted through a derivative
   */
  function totalTokensOutstanding()
    external
    view
    returns (FixedPoint.Unsigned memory totalTokens);

  /** @notice Gets the price at which the emergency shutdown was performed
   */
  function emergencyShutdownPrice()
    external
    view
    returns (FixedPoint.Unsigned memory emergencyPrice);
}

// File: @jarvis-network/synthereum-contracts/contracts/derivative/common/interfaces/IDerivative.sol


pragma solidity ^0.8.4;



/**
 * @title Interface that a derivative MUST have in order to be used in the pools
 */
interface IDerivative is IDerivativeDeployment, IDerivativeMain {

}

// File: @jarvis-network/synthereum-contracts/contracts/synthereum-pool/v4/interfaces/IPoolInteraction.sol


pragma solidity ^0.8.4;

interface ISynthereumPoolInteraction {
  /**
   * @notice Called by a source Pool's `exchange` function to mint destination tokens
   * @notice This functon can be called only by a pool registred in the PoolRegister contract
   * @param srcDerivative Derivative used by the source pool
   * @param derivative The derivative of the destination pool to use for mint
   * @param collateralAmount The amount of collateral to use from the source Pool
   * @param numTokens The number of new tokens to mint
   */
  function exchangeMint(
    IDerivative srcDerivative,
    IDerivative derivative,
    uint256 collateralAmount,
    uint256 numTokens
  ) external;

  /**
   * @notice Returns price identifier of the pool
   * @return identifier Price identifier
   */
  function getPriceFeedIdentifier() external view returns (bytes32 identifier);
}

// File: @jarvis-network/synthereum-contracts/contracts/synthereum-pool/common/interfaces/IPoolDeployment.sol


pragma solidity ^0.8.4;


/**
 * @title Interface that a pool MUST have in order to be included in the deployer
 */
interface ISynthereumPoolDeployment {
  /**
   * @notice Get Synthereum finder of the pool
   * @return finder Returns finder contract
   */
  function synthereumFinder() external view returns (ISynthereumFinder finder);

  /**
   * @notice Get Synthereum version
   * @return poolVersion Returns the version of this Synthereum pool
   */
  function version() external view returns (uint8 poolVersion);

  /**
   * @notice Get the collateral token
   * @return collateralCurrency The ERC20 collateral token
   */
  function collateralToken() external view returns (IERC20 collateralCurrency);

  /**
   * @notice Get the synthetic token associated to this pool
   * @return syntheticCurrency The ERC20 synthetic token
   */
  function syntheticToken() external view returns (IERC20 syntheticCurrency);

  /**
   * @notice Get the synthetic token symbol associated to this pool
   * @return symbol The ERC20 synthetic token symbol
   */
  function syntheticTokenSymbol() external view returns (string memory symbol);
}

// File: @jarvis-network/synthereum-contracts/contracts/synthereum-pool/common/interfaces/IPoolWithDerivativeDeployment.sol


pragma solidity ^0.8.4;


/**
 * @title Interface that an autonomous pool MUST have in order to be included in the deployer
 */
interface ISynthereumPoolWithDerivativeDeployment is ISynthereumPoolDeployment {
  /**
   * @notice Check that a derivative is admitted in the pool
   * @param derivative Address of the derivative to be checked
   * @return isAdmitted true if derivative is admitted otherwise false
   */
  function isDerivativeAdmitted(address derivative)
    external
    view
    returns (bool isAdmitted);
}

// File: @jarvis-network/synthereum-contracts/contracts/synthereum-pool/v4/interfaces/IPoolGeneral.sol


pragma solidity ^0.8.4;


interface ISynthereumPoolGeneral is
  ISynthereumPoolWithDerivativeDeployment,
  ISynthereumPoolInteraction
{}

// File: @jarvis-network/synthereum-contracts/contracts/core/interfaces/IDeployer.sol


pragma solidity ^0.8.4;


/**
 * @title Provides interface with functions of Synthereum deployer
 */
interface ISynthereumDeployer {
  /**
   * @notice Deploys derivative and pool linking the contracts together
   * @param derivativeVersion Version of derivative contract
   * @param poolVersion Version of the pool contract
   * @param derivativeParamsData Input params of derivative constructor
   * @param poolParamsData Input params of pool constructor
   * @return derivative Derivative contract deployed
   * @return pool Pool contract deployed
   */
  function deployPoolAndDerivative(
    uint8 derivativeVersion,
    uint8 poolVersion,
    bytes calldata derivativeParamsData,
    bytes calldata poolParamsData
  )
    external
    returns (
      IDerivativeDeployment derivative,
      ISynthereumPoolWithDerivativeDeployment pool
    );

  /**
   * @notice Deploys a pool and links it with an already existing derivative
   * @param poolVersion Version of the pool contract
   * @param poolParamsData Input params of pool constructor
   * @param derivative Existing derivative contract to link with the new pool
   * @return pool Pool contract deployed
   */
  function deployOnlyPool(
    uint8 poolVersion,
    bytes calldata poolParamsData,
    IDerivativeDeployment derivative
  ) external returns (ISynthereumPoolWithDerivativeDeployment pool);

  /**
   * @notice Deploys a derivative and option to links it with an already existing pool
   * @param derivativeVersion Version of the derivative contract
   * @param derivativeParamsData Input params of derivative constructor
   * @param pool Existing pool contract to link with the new derivative
   * @return derivative Derivative contract deployed
   */
  function deployOnlyDerivative(
    uint8 derivativeVersion,
    bytes calldata derivativeParamsData,
    ISynthereumPoolWithDerivativeDeployment pool
  ) external returns (IDerivativeDeployment derivative);

  function deployOnlySelfMintingDerivative(
    uint8 selfMintingDerVersion,
    bytes calldata selfMintingDerParamsData
  ) external returns (ISelfMintingDerivativeDeployment selfMintingDerivative);
}

// File: @jarvis-network/synthereum-contracts/contracts/synthereum-pool/v4/interfaces/IPoolOnChainPriceFeed.sol


pragma solidity ^0.8.4;


/**
 * @title Token Issuer Contract Interface
 */
interface ISynthereumPoolOnChainPriceFeed is ISynthereumPoolGeneral {
  // Describe fee structure
  struct Fee {
    // Fees charged when a user mints, redeem and exchanges tokens
    FixedPoint.Unsigned feePercentage;
    address[] feeRecipients;
    uint32[] feeProportions;
  }

  // Describe role structure
  struct Roles {
    address admin;
    address maintainer;
    address liquidityProvider;
  }

  struct MintParams {
    // Derivative to use
    IDerivative derivative;
    // Minimum amount of synthetic tokens that a user wants to mint using collateral (anti-slippage)
    uint256 minNumTokens;
    // Amount of collateral that a user wants to spend for minting
    uint256 collateralAmount;
    // Maximum amount of fees in percentage that user is willing to pay
    uint256 feePercentage;
    // Expiration time of the transaction
    uint256 expiration;
    // Address to which send synthetic tokens minted
    address recipient;
  }

  struct RedeemParams {
    // Derivative to use
    IDerivative derivative;
    // Amount of synthetic tokens that user wants to use for redeeming
    uint256 numTokens;
    // Minimium amount of collateral that user wants to redeem (anti-slippage)
    uint256 minCollateral;
    // Maximum amount of fees in percentage that user is willing to pay
    uint256 feePercentage;
    // Expiration time of the transaction
    uint256 expiration;
    // Address to which send collateral tokens redeemed
    address recipient;
  }

  struct ExchangeParams {
    // Derivative of source pool
    IDerivative derivative;
    // Destination pool
    ISynthereumPoolGeneral destPool;
    // Derivative of destination pool
    IDerivative destDerivative;
    // Amount of source synthetic tokens that user wants to use for exchanging
    uint256 numTokens;
    // Minimum Amount of destination synthetic tokens that user wants to receive (anti-slippage)
    uint256 minDestNumTokens;
    // Maximum amount of fees in percentage that user is willing to pay
    uint256 feePercentage;
    // Expiration time of the transaction
    uint256 expiration;
    // Address to which send synthetic tokens exchanged
    address recipient;
  }

  /**
   * @notice Add a derivate to be controlled by this pool
   * @param derivative A perpetual derivative
   */
  function addDerivative(IDerivative derivative) external;

  /**
   * @notice Remove a derivative controlled by this pool
   * @param derivative A perpetual derivative
   */
  function removeDerivative(IDerivative derivative) external;

  /**
   * @notice Mint synthetic tokens using fixed amount of collateral
   * @notice This calculate the price using on chain price feed
   * @notice User must approve collateral transfer for the mint request to succeed
   * @param mintParams Input parameters for minting (see MintParams struct)
   * @return syntheticTokensMinted Amount of synthetic tokens minted by a user
   * @return feePaid Amount of collateral paid by the minter as fee
   */
  function mint(MintParams memory mintParams)
    external
    returns (uint256 syntheticTokensMinted, uint256 feePaid);

  /**
   * @notice Redeem amount of collateral using fixed number of synthetic token
   * @notice This calculate the price using on chain price feed
   * @notice User must approve synthetic token transfer for the redeem request to succeed
   * @param redeemParams Input parameters for redeeming (see RedeemParams struct)
   * @return collateralRedeemed Amount of collateral redeeem by user
   * @return feePaid Amount of collateral paid by user as fee
   */
  function redeem(RedeemParams memory redeemParams)
    external
    returns (uint256 collateralRedeemed, uint256 feePaid);

  /**
   * @notice Exchange a fixed amount of synthetic token of this pool, with an amount of synthetic tokens of an another pool
   * @notice This calculate the price using on chain price feed
   * @notice User must approve synthetic token transfer for the redeem request to succeed
   * @param exchangeParams Input parameters for exchanging (see ExchangeParams struct)
   * @return destNumTokensMinted Amount of collateral redeeem by user
   * @return feePaid Amount of collateral paid by user as fee
   */
  function exchange(ExchangeParams memory exchangeParams)
    external
    returns (uint256 destNumTokensMinted, uint256 feePaid);

  /**
   * @notice Liquidity provider withdraw margin from the pool
   * @param collateralAmount The amount of margin to withdraw
   */
  function withdrawFromPool(uint256 collateralAmount) external;

  /**
   * @notice Move collateral from Pool to its derivative in order to increase GCR
   * @param derivative Derivative on which to deposit collateral
   * @param collateralAmount The amount of collateral to move into derivative
   */
  function depositIntoDerivative(
    IDerivative derivative,
    uint256 collateralAmount
  ) external;

  /**
   * @notice Start a slow withdrawal request
   * @notice Collateral can be withdrawn once the liveness period has elapsed
   * @param derivative Derivative from which collateral withdrawal is requested
   * @param collateralAmount The amount of excess collateral to withdraw
   */
  function slowWithdrawRequest(IDerivative derivative, uint256 collateralAmount)
    external;

  /**
   * @notice Withdraw collateral after a withdraw request has passed it's liveness period
   * @param derivative Derivative from which collateral withdrawal is requested
   * @return amountWithdrawn Amount of collateral withdrawn by slow withdrawal
   */
  function slowWithdrawPassedRequest(IDerivative derivative)
    external
    returns (uint256 amountWithdrawn);

  /**
   * @notice Withdraw collateral immediately if the remaining collateral is above GCR
   * @param derivative Derivative from which fast withdrawal is requested
   * @param collateralAmount The amount of excess collateral to withdraw
   * @return amountWithdrawn Amount of collateral withdrawn by fast withdrawal
   */
  function fastWithdraw(IDerivative derivative, uint256 collateralAmount)
    external
    returns (uint256 amountWithdrawn);

  /**
   * @notice Redeem tokens after contract emergency shutdown
   * @param derivative Derivative for which settlement is requested
   * @return amountSettled Amount of collateral withdrawn after emergency shutdown
   */
  function settleEmergencyShutdown(IDerivative derivative)
    external
    returns (uint256 amountSettled);

  /**
   * @notice Update the fee percentage, recipients and recipient proportions
   * @param _fee Fee struct containing percentage, recipients and proportions
   */
  function setFee(Fee memory _fee) external;

  /**
   * @notice Update the fee percentage
   * @param _feePercentage The new fee percentage
   */
  function setFeePercentage(uint256 _feePercentage) external;

  /**
   * @notice Update the addresses of recipients for generated fees and proportions of fees each address will receive
   * @param _feeRecipients An array of the addresses of recipients that will receive generated fees
   * @param _feeProportions An array of the proportions of fees generated each recipient will receive
   */
  function setFeeRecipients(
    address[] memory _feeRecipients,
    uint32[] memory _feeProportions
  ) external;

  /**
   * @notice Reset the starting collateral ratio - for example when you add a new derivative without collateral
   * @param startingCollateralRatio Initial ratio between collateral amount and synth tokens
   */
  function setStartingCollateralization(uint256 startingCollateralRatio)
    external;

  /**
   * @notice Get all the derivatives associated to this pool
   * @return Return list of all derivatives
   */
  function getAllDerivatives() external view returns (IDerivative[] memory);

  /**
   * @notice Get the starting collateral ratio of the pool
   * @return startingCollateralRatio Initial ratio between collateral amount and synth tokens
   */
  function getStartingCollateralization()
    external
    view
    returns (uint256 startingCollateralRatio);

  /**
   * @notice Returns infos about fee set
   * @return fee Percentage and recipients of fee
   */
  function getFeeInfo() external view returns (Fee memory fee);

  /**
   * @notice Calculate the fees a user will have to pay to mint tokens with their collateral
   * @param collateralAmount Amount of collateral on which fees are calculated
   * @return fee Amount of fee that must be paid by the user
   */
  function calculateFee(uint256 collateralAmount)
    external
    view
    returns (uint256 fee);
}

// File: @jarvis-network/atomic-swap/contracts/interfaces/IAtomicSwap.sol

pragma solidity ^0.8.4;


interface IAtomicSwap {
  function swapExactTokensAndMint(
    uint256 tokenAmountIn,
    uint256 collateralAmountOut,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed synthereumPool,
    ISynthereumPoolOnChainPriceFeed.MintParams memory mintParams
  )
    external
    returns (
      uint256 collateralOut,
      IERC20 synthToken,
      uint256 syntheticTokensMinted
    );

  function swapTokensForExactAndMint(
    uint256 tokenAmountIn,
    uint256 collateralAmountOut,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed synthereumPool,
    ISynthereumPoolOnChainPriceFeed.MintParams memory mintParams
  )
    external
    returns (
      uint256 collateralOut,
      IERC20 synthToken,
      uint256 syntheticTokensMinted
    );

  function redeemAndSwapExactTokens(
    uint256 amountTokenOut,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed synthereumPool,
    ISynthereumPoolOnChainPriceFeed.RedeemParams memory redeemParams,
    address recipient
  )
    external
    returns (
      uint256 collateralRedeemed,
      IERC20 outputToken,
      uint256 outputTokenAmount
    );

  function redeemAndSwapTokensForExact(
    uint256 amountTokenOut,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed synthereumPool,
    ISynthereumPoolOnChainPriceFeed.RedeemParams memory redeemParams,
    address recipient
  )
    external
    returns (
      uint256 collateralRedeemed,
      IERC20 outputToken,
      uint256 outputTokenAmount
    );

  function swapExactETHAndMint(
    uint256 collateralAmountOut,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed synthereumPool,
    ISynthereumPoolOnChainPriceFeed.MintParams memory mintParams
  )
    external
    payable
    returns (
      uint256 collateralOut,
      IERC20 synthToken,
      uint256 syntheticTokensMinted
    );

  function swapETHForExactAndMint(
    uint256 collateralAmountOut,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed synthereumPool,
    ISynthereumPoolOnChainPriceFeed.MintParams memory mintParams
  )
    external
    payable
    returns (
      uint256 collateralOut,
      IERC20 synthToken,
      uint256 syntheticTokensMinted
    );

  function redeemAndSwapExactTokensForETH(
    uint256 amountTokenOut,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed synthereumPool,
    ISynthereumPoolOnChainPriceFeed.RedeemParams memory redeemParams,
    address recipient
  )
    external
    returns (
      uint256 collateralRedeemed,
      IERC20 outputToken,
      uint256 outputTokenAmount
    );

  function redeemAndSwapTokensForExactETH(
    uint256 amountTokenOut,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed synthereumPool,
    ISynthereumPoolOnChainPriceFeed.RedeemParams memory redeemParams,
    address recipient
  )
    external
    returns (
      uint256 collateralRedeemed,
      IERC20 outputToken,
      uint256 outputTokenAmount
    );
}

// File: libs/legacy-currency-contracts/contracts/fixed-rate-currency/FixedRateWrapper.sol



pragma solidity ^0.8.4;





contract FixedRateWrapper is ERC20 {
  using SafeMath for uint256;
  using SafeERC20 for IERC20;

  // Precision for math operations
  uint256 public constant PRECISION = 1e18;

  // The synthetic token to which the legacy currency is pegged
  IERC20 public immutable synth;

  // The rate at which the conversion happens
  uint256 public rate;

  // A variable to track total deposited amount of synthetic tokens
  uint256 public total_deposited;

  /** @notice Constructs the ERC20 contract and sets the immutable variables
   * @param _token - The synthetic token to which the legacy currency is pegged
   * @param _rate - The rate at which the conversion happens
   * @param _name - The name of the synthetic legacy currency token
   * @param _symbol - The symbol of the synthetic legacy currency token
   */
  constructor(
    IERC20 _token,
    uint256 _rate,
    string memory _name,
    string memory _symbol
  ) public ERC20(_name, _symbol) {
    synth = _token;
    rate = _rate;
  }

  /** @notice - An internal function which mints new fixedRate tokens according to the rate with it's peg synth
   * @param _amount - The amount of synthetic tokens the user wants to exchange
   */
  function wrap(uint256 _amount, address recipient)
    internal
    returns (uint256 amountTokens)
  {
    amountTokens = _amount.mul(rate).div(PRECISION);
    total_deposited = total_deposited.add(_amount);
    _mint(recipient, amountTokens);
  }

  /** @notice - A internal function which burns fixedRate tokens releasing peg synthetic tokens to a recipient
   * @param _amount - The amount of legacy synthetic tokens the user wants to deposit and burn
   */
  function unwrap(uint256 _amount, address recipient)
    internal
    returns (uint256 amountTokens)
  {
    require(balanceOf(msg.sender) >= _amount, 'Not enought tokens to unwrap');
    amountTokens = total_deposited.mul(_amount).div(totalSupply());
    _burn(msg.sender, _amount);
    total_deposited = total_deposited.sub(amountTokens);
    synth.safeTransfer(recipient, amountTokens);
  }
}

// File: libs/legacy-currency-contracts/contracts/fixed-rate-currency/FixedRateCurrency.sol



pragma solidity ^0.8.4;
pragma experimental ABIEncoderV2;


contract FixedRateCurrency is FixedRateWrapper {
  using SafeMath for uint256;
  using SafeERC20 for IERC20;

  bool public paused; // Prevents minting when true

  ISynthereumFinder public synthereumFinder;
  ISynthereumPoolOnChainPriceFeed public synthereumPool; // pegSynth-USDC pool
  IERC20 public collateralInstance; // synthereum pool collateral (USDC)
  IAtomicSwap public atomicSwap;

  address public admin;
  //----------------------------------------
  // Events
  //----------------------------------------
  event Mint(
    address indexed account,
    address indexed tokenCollateral,
    address indexed tokenAddress,
    uint256 numTokens
  );

  event Redeem(
    address indexed account,
    address indexed tokenBurned,
    address indexed tokenRedeemed,
    uint256 numTokensRedeemed
  );

  event SwapWithSynth(
    address indexed account,
    address indexed synth,
    address indexed tokenAddress,
    uint256 numTokens,
    string side
  );

  event SwapWithERC20(
    address indexed account,
    address indexed ERC20Address,
    address indexed synthToken,
    string side,
    uint256 numTokensIn,
    uint256 numTokensOut
  );

  event SwapWithETH(
    address indexed account,
    string side,
    uint256 numTokensIn,
    uint256 numTokensOut
  );

  event ContractPaused();
  event ContractResumed();

  event RateChange(uint256 oldRate, uint256 newRate);
  //----------------------------------------
  // Modifiers
  //----------------------------------------

  modifier isActive() {
    require(!paused, 'Contract has been paused');
    _;
  }

  modifier onlyAdmin() {
    require(msg.sender == admin, 'Only contract admin can call this function');
    _;
  }

  constructor(
    IERC20 _pegToken,
    IERC20 _collateralToken,
    ISynthereumPoolOnChainPriceFeed _synthereumPoolAddress,
    ISynthereumFinder _synthereumFinder,
    IAtomicSwap _atomicSwapAddr,
    address _admin,
    uint256 _rate,
    string memory _name,
    string memory _symbol
  ) public FixedRateWrapper(_pegToken, _rate, _name, _symbol) {
    paused = false;
    synthereumFinder = _synthereumFinder;
    synthereumPool = _synthereumPoolAddress;
    collateralInstance = _collateralToken;
    admin = _admin;
    atomicSwap = _atomicSwapAddr;

    address synthAddress;
    address collateralAddress;
    // check the appropriate pool is passed
    (collateralAddress, synthAddress) = checkPoolRegistration();

    require(
      address(_pegToken) == synthAddress &&
        address(_collateralToken) == collateralAddress,
      'Pool mismatch with collateral and synth'
    );
  }

  /** @notice - Mints fixed rate synths against the deposited peg synth (jEUR)
   */
  function mintFromPegSynth(uint256 _pegTokenAmount, address recipient)
    public
    isActive()
    returns (uint256 numTokensMinted)
  {
    synth.safeTransferFrom(msg.sender, address(this), _pegTokenAmount);
    numTokensMinted = super.wrap(_pegTokenAmount, recipient);

    emit Mint(msg.sender, address(synth), address(this), numTokensMinted);
  }

  /** @notice - Burns fixed rate synths and unlocks the deposited peg synth (jEUR)
   */
  function redeemToPegSynth(uint256 _fixedSynthAmount, address recipient)
    public
    returns (uint256 tokensRedeemed)
  {
    tokensRedeemed = super.unwrap(_fixedSynthAmount, recipient);
    emit Redeem(msg.sender, address(this), address(synth), tokensRedeemed);
  }

  /** @notice - Mints fixed rate synths from USDC.
        Mints _pegToken from USDC using the appropriate synthereum pool.
     */
  function mintFromUSDC(
    ISynthereumPoolOnChainPriceFeed.MintParams memory _mintParams
  ) public isActive() {
    // pull USDC from user's wallet
    collateralInstance.safeTransferFrom(
      msg.sender,
      address(this),
      _mintParams.collateralAmount
    );

    // approves the pool to transfer collateral from this contract
    collateralInstance.safeIncreaseAllowance(
      address(synthereumPool),
      _mintParams.collateralAmount
    );

    // mint jEUR (peg token) with USDC and deposit directly into this contract
    _mintParams.recipient = address(this);
    (uint256 pegTokensMinted, ) = synthereumPool.mint(_mintParams);

    // mint fixedRate to user wallet
    uint256 numTokensMinted = super.wrap(pegTokensMinted, msg.sender);

    emit Mint(msg.sender, address(synth), address(this), numTokensMinted);
  }

  /** @notice - Redeem USDC by burning peg synth (from synthereum pool)
        Unlocked by burning fixed rate synths (unwrap).
    */
  function redeemUSDC(
    ISynthereumPoolOnChainPriceFeed.RedeemParams memory _redeemParams
  ) public {
    // burn _synthAmount to get peg tokens jEur into this wallet
    uint256 pegTokensUnlocked =
      super.unwrap(_redeemParams.numTokens, address(this));

    // approves the synthereum pool to pull peg tokens tokens from this contract
    synth.safeIncreaseAllowance(address(synthereumPool), pegTokensUnlocked);

    // redeem USDC by burning jEur in broker contract and send them recipient in redeemParams
    _redeemParams.numTokens = pegTokensUnlocked;
    (uint256 collateralRedeemed, ) = synthereumPool.redeem(_redeemParams);

    emit Redeem(
      msg.sender,
      address(synth),
      address(collateralInstance),
      collateralRedeemed
    );
  }

  /**
    @notice Mints fixed rate currency from a synthereum synthetic asset 
   */
  function mintFromSynth(
    IERC20 inputSynthAddress,
    ISynthereumPoolOnChainPriceFeed inputSynthPool,
    ISynthereumPoolOnChainPriceFeed.ExchangeParams memory _exchangeParams
  ) public isActive {
    // pull synth to be exchanged from user wallet into this contract wallet
    inputSynthAddress.safeTransferFrom(
      msg.sender,
      address(this),
      _exchangeParams.numTokens
    );

    // allow the synthereum pool to transfer input synth
    inputSynthAddress.safeIncreaseAllowance(
      address(inputSynthPool),
      _exchangeParams.numTokens
    );

    // synth -> peg Token into this wallet
    _exchangeParams.recipient = address(this);
    (uint256 pegTokenAmount, ) = inputSynthPool.exchange(_exchangeParams);

    // mint fixedRate token according to rate into user wallet
    uint256 numTokensMinted = super.wrap(pegTokenAmount, msg.sender);

    emit SwapWithSynth(
      msg.sender,
      address(inputSynthAddress),
      address(this),
      numTokensMinted,
      'buy'
    );
  }

  /**
    @notice Burns fixed rate currency and swap the peg synth with any other synthereum asset 
   */
  function swapForSynth(
    uint256 _fixedSynthAmount,
    ISynthereumPoolOnChainPriceFeed.ExchangeParams memory _exchangeParams
  ) public {
    // burn _synthAmount to get peg tokens jEur into this wallet
    uint256 pegTokensUnlocked = super.unwrap(_fixedSynthAmount, address(this));

    // allow the synthereum pool to transfer jEur
    synth.safeIncreaseAllowance(address(synthereumPool), pegTokensUnlocked);

    // exchange function in broker to get final asset into user wallet
    _exchangeParams.numTokens = pegTokensUnlocked;
    (uint256 numTokensMinted, ) = synthereumPool.exchange(_exchangeParams);
    emit SwapWithSynth(
      msg.sender,
      address(_exchangeParams.destPool.syntheticToken()),
      address(this),
      numTokensMinted,
      'sell'
    );
  }

  /**
    @notice Leverages the OCLR to do ERC20 -> USDC -> jEUR -> fixedSynth 
   */
  function mintFromERC20(
    uint256 amountTokensIn,
    uint256 collateralAmountOutMin,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed.MintParams memory mintParams
  ) public isActive {
    // deposit erc20 into this contract
    IERC20(tokenSwapPath[0]).safeTransferFrom(
      msg.sender,
      address(this),
      amountTokensIn
    );

    // allowance
    IERC20(tokenSwapPath[0]).safeIncreaseAllowance(
      address(atomicSwap),
      amountTokensIn
    );

    //erc20 -> USDC -> jEur to this wallet
    mintParams.recipient = address(this);
    (, , uint256 synthMinted) =
      atomicSwap.swapExactTokensAndMint(
        amountTokensIn,
        collateralAmountOutMin,
        tokenSwapPath,
        synthereumPool,
        mintParams
      );

    // mint FixedRate to user wallet
    uint256 numTokensMinted = super.wrap(synthMinted, msg.sender);

    emit SwapWithERC20(
      msg.sender,
      tokenSwapPath[0],
      address(synth),
      'buy',
      amountTokensIn,
      numTokensMinted
    );
  }

  /**
    @notice Leverages the OCLR to do ETH -> USDC -> jEUR -> fixedSynth 
   */
  function mintFromETH(
    uint256 collateralAmountOutMin,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed.MintParams memory mintParams
  ) public payable isActive {
    // ETH -> USDC -> jEUR into this wallet
    mintParams.recipient = address(this);
    (, , uint256 pegSynthMinted) =
      atomicSwap.swapExactETHAndMint{value: msg.value}(
        collateralAmountOutMin,
        tokenSwapPath,
        synthereumPool,
        mintParams
      );

    // mint fixedRate into this wallet
    uint256 numTokensMinted = super.wrap(pegSynthMinted, msg.sender);

    emit SwapWithETH(msg.sender, 'buy', msg.value, numTokensMinted);
  }

  /**
    @notice Leverages the OCLR to do fixedSynth -> jEur (peg) -> USDC -> ERC20 
   */
  function swapToERC20(
    uint256 fixedSynthAmountIn,
    uint256 amountTokenOutMin,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed.RedeemParams memory redeemParams
  ) public {
    // jBGN -> jEUR into this waallet
    uint256 pegSynthRedeemed = super.unwrap(fixedSynthAmountIn, address(this));

    // allow AtomicSwap to pull jEUR
    synth.safeIncreaseAllowance(address(atomicSwap), pegSynthRedeemed);

    // jEUr -> USDC -> ERC20 through AtomicSwap contract
    redeemParams.numTokens = pegSynthRedeemed;
    (, , uint256 outputAmount) =
      atomicSwap.redeemAndSwapExactTokens(
        amountTokenOutMin,
        tokenSwapPath,
        synthereumPool,
        redeemParams,
        msg.sender
      );

    emit SwapWithERC20(
      msg.sender,
      address(tokenSwapPath[1]),
      address(synth),
      'sell',
      fixedSynthAmountIn,
      outputAmount
    );
  }

  /**
    @notice Leverages the OCLR to do fixedSynth -> jEur (peg) -> USDC -> ETH 
   */
  function swapToETH(
    uint256 fixedSynthAmountIn,
    uint256 amountTokenOutMin,
    address[] calldata tokenSwapPath,
    ISynthereumPoolOnChainPriceFeed.RedeemParams memory redeemParams
  ) public {
    // jBGN -> jEUR into this wallet
    uint256 pegSynthRedeemed = super.unwrap(fixedSynthAmountIn, address(this));

    // allow AtomicSwap to pull jEUR
    synth.safeIncreaseAllowance(address(atomicSwap), pegSynthRedeemed);

    // jEUr -> USDC -> ERC20 through AtomicSwap contract
    redeemParams.numTokens = pegSynthRedeemed;
    (, , uint256 outputAmount) =
      atomicSwap.redeemAndSwapExactTokensForETH(
        amountTokenOutMin,
        tokenSwapPath,
        synthereumPool,
        redeemParams,
        msg.sender
      );

    emit SwapWithETH(msg.sender, 'sell', fixedSynthAmountIn, outputAmount);
  }

  // only synthereum manager can pause new mintings
  function pauseContract() public onlyAdmin {
    paused = true;
    emit ContractPaused();
  }

  function resumeContract() public onlyAdmin {
    paused = false;
    emit ContractResumed();
  }

  function changeRate(uint256 newRate) public onlyAdmin {
    emit RateChange(rate, newRate);
    rate = newRate;
  }

  function getRate() public view returns (uint256) {
    return rate;
  }

  function checkPoolRegistration()
    internal
    view
    returns (address collateralAddress, address synthAddress)
  {
    ISynthereumRegistry poolRegistry =
      ISynthereumRegistry(
        synthereumFinder.getImplementationAddress(
          SynthereumInterfaces.PoolRegistry
        )
      );

    string memory synthTokenSymbol = synthereumPool.syntheticTokenSymbol();
    collateralAddress = address(synthereumPool.collateralToken());
    uint8 version = synthereumPool.version();
    require(
      poolRegistry.isDeployed(
        synthTokenSymbol,
        IERC20(collateralAddress),
        version,
        address(synthereumPool)
      ),
      'Pool not registred'
    );

    synthAddress = address(synthereumPool.syntheticToken());
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IERC20","name":"_pegToken","type":"address"},{"internalType":"contract IERC20","name":"_collateralToken","type":"address"},{"internalType":"contract ISynthereumPoolOnChainPriceFeed","name":"_synthereumPoolAddress","type":"address"},{"internalType":"contract ISynthereumFinder","name":"_synthereumFinder","type":"address"},{"internalType":"contract IAtomicSwap","name":"_atomicSwapAddr","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"uint256","name":"_rate","type":"uint256"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"ContractPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"ContractResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"tokenCollateral","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"RateChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"tokenBurned","type":"address"},{"indexed":true,"internalType":"address","name":"tokenRedeemed","type":"address"},{"indexed":false,"internalType":"uint256","name":"numTokensRedeemed","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"ERC20Address","type":"address"},{"indexed":true,"internalType":"address","name":"synthToken","type":"address"},{"indexed":false,"internalType":"string","name":"side","type":"string"},{"indexed":false,"internalType":"uint256","name":"numTokensIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numTokensOut","type":"uint256"}],"name":"SwapWithERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"string","name":"side","type":"string"},{"indexed":false,"internalType":"uint256","name":"numTokensIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numTokensOut","type":"uint256"}],"name":"SwapWithETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"synth","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"numTokens","type":"uint256"},{"indexed":false,"internalType":"string","name":"side","type":"string"}],"name":"SwapWithSynth","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"atomicSwap","outputs":[{"internalType":"contract IAtomicSwap","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"changeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralInstance","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountTokensIn","type":"uint256"},{"internalType":"uint256","name":"collateralAmountOutMin","type":"uint256"},{"internalType":"address[]","name":"tokenSwapPath","type":"address[]"},{"components":[{"internalType":"contract IDerivative","name":"derivative","type":"address"},{"internalType":"uint256","name":"minNumTokens","type":"uint256"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"feePercentage","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISynthereumPoolOnChainPriceFeed.MintParams","name":"mintParams","type":"tuple"}],"name":"mintFromERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateralAmountOutMin","type":"uint256"},{"internalType":"address[]","name":"tokenSwapPath","type":"address[]"},{"components":[{"internalType":"contract IDerivative","name":"derivative","type":"address"},{"internalType":"uint256","name":"minNumTokens","type":"uint256"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"feePercentage","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISynthereumPoolOnChainPriceFeed.MintParams","name":"mintParams","type":"tuple"}],"name":"mintFromETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pegTokenAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"mintFromPegSynth","outputs":[{"internalType":"uint256","name":"numTokensMinted","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"inputSynthAddress","type":"address"},{"internalType":"contract ISynthereumPoolOnChainPriceFeed","name":"inputSynthPool","type":"address"},{"components":[{"internalType":"contract IDerivative","name":"derivative","type":"address"},{"internalType":"contract ISynthereumPoolGeneral","name":"destPool","type":"address"},{"internalType":"contract IDerivative","name":"destDerivative","type":"address"},{"internalType":"uint256","name":"numTokens","type":"uint256"},{"internalType":"uint256","name":"minDestNumTokens","type":"uint256"},{"internalType":"uint256","name":"feePercentage","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISynthereumPoolOnChainPriceFeed.ExchangeParams","name":"_exchangeParams","type":"tuple"}],"name":"mintFromSynth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IDerivative","name":"derivative","type":"address"},{"internalType":"uint256","name":"minNumTokens","type":"uint256"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"feePercentage","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISynthereumPoolOnChainPriceFeed.MintParams","name":"_mintParams","type":"tuple"}],"name":"mintFromUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fixedSynthAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"redeemToPegSynth","outputs":[{"internalType":"uint256","name":"tokensRedeemed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IDerivative","name":"derivative","type":"address"},{"internalType":"uint256","name":"numTokens","type":"uint256"},{"internalType":"uint256","name":"minCollateral","type":"uint256"},{"internalType":"uint256","name":"feePercentage","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISynthereumPoolOnChainPriceFeed.RedeemParams","name":"_redeemParams","type":"tuple"}],"name":"redeemUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resumeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fixedSynthAmount","type":"uint256"},{"components":[{"internalType":"contract IDerivative","name":"derivative","type":"address"},{"internalType":"contract ISynthereumPoolGeneral","name":"destPool","type":"address"},{"internalType":"contract IDerivative","name":"destDerivative","type":"address"},{"internalType":"uint256","name":"numTokens","type":"uint256"},{"internalType":"uint256","name":"minDestNumTokens","type":"uint256"},{"internalType":"uint256","name":"feePercentage","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISynthereumPoolOnChainPriceFeed.ExchangeParams","name":"_exchangeParams","type":"tuple"}],"name":"swapForSynth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fixedSynthAmountIn","type":"uint256"},{"internalType":"uint256","name":"amountTokenOutMin","type":"uint256"},{"internalType":"address[]","name":"tokenSwapPath","type":"address[]"},{"components":[{"internalType":"contract IDerivative","name":"derivative","type":"address"},{"internalType":"uint256","name":"numTokens","type":"uint256"},{"internalType":"uint256","name":"minCollateral","type":"uint256"},{"internalType":"uint256","name":"feePercentage","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISynthereumPoolOnChainPriceFeed.RedeemParams","name":"redeemParams","type":"tuple"}],"name":"swapToERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fixedSynthAmountIn","type":"uint256"},{"internalType":"uint256","name":"amountTokenOutMin","type":"uint256"},{"internalType":"address[]","name":"tokenSwapPath","type":"address[]"},{"components":[{"internalType":"contract IDerivative","name":"derivative","type":"address"},{"internalType":"uint256","name":"numTokens","type":"uint256"},{"internalType":"uint256","name":"minCollateral","type":"uint256"},{"internalType":"uint256","name":"feePercentage","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISynthereumPoolOnChainPriceFeed.RedeemParams","name":"redeemParams","type":"tuple"}],"name":"swapToETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"synth","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"synthereumFinder","outputs":[{"internalType":"contract ISynthereumFinder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"synthereumPool","outputs":[{"internalType":"contract ISynthereumPoolOnChainPriceFeed","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"total_deposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b50604051620033b4380380620033b48339810160408190526200003491620006d2565b88838383818181600390805190602001906200005292919062000543565b5080516200006890600490602084019062000543565b505050505060609190911b6001600160601b031916608052600555600780546001600160a81b0319166101006001600160a01b038981169190910291909117909155600880546001600160a01b03199081168a8416179091556009805482168b8416179055600b80548216878416179055600a8054909116918716919091179055600080620000f66200019a565b925090506001600160a01b038b8116908316148015620001275750806001600160a01b03168a6001600160a01b0316145b620001895760405162461bcd60e51b815260206004820152602760248201527f506f6f6c206d69736d61746368207769746820636f6c6c61746572616c20616e6044820152660c840e6f2dce8d60cb1b60648201526084015b60405180910390fd5b50505050505050505050506200090d565b6007546040516302abf57960e61b81526b506f6f6c526567697374727960a01b60048201526000918291829161010090046001600160a01b03169063aafd5e409060240160206040518083038186803b158015620001f757600080fd5b505afa1580156200020c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200023291906200068a565b90506000600860009054906101000a90046001600160a01b03166001600160a01b03166336815bb76040518163ffffffff1660e01b815260040160006040518083038186803b1580156200028557600080fd5b505afa1580156200029a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620002c49190810190620007b9565b9050600860009054906101000a90046001600160a01b03166001600160a01b031663b2016bd46040518163ffffffff1660e01b815260040160206040518083038186803b1580156200031557600080fd5b505afa1580156200032a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035091906200068a565b93506000600860009054906101000a90046001600160a01b03166001600160a01b03166354fd4d506040518163ffffffff1660e01b815260040160206040518083038186803b158015620003a357600080fd5b505afa158015620003b8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003de9190620007f7565b6008546040516310ffc46560e11b81529192506001600160a01b03808616926321ff88ca92620004199287928b92889216906004016200081a565b60206040518083038186803b1580156200043257600080fd5b505afa15801562000447573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200046d9190620006b0565b620004b05760405162461bcd60e51b8152602060048201526012602482015271141bdbdb081b9bdd081c9959da5cdd1c995960721b604482015260640162000180565b600860009054906101000a90046001600160a01b03166001600160a01b0316638230ecd66040518163ffffffff1660e01b815260040160206040518083038186803b158015620004ff57600080fd5b505afa15801562000514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200053a91906200068a565b93505050509091565b8280546200055190620008a1565b90600052602060002090601f016020900481019282620005755760008555620005c0565b82601f106200059057805160ff1916838001178555620005c0565b82800160010185558215620005c0579182015b82811115620005c0578251825591602001919060010190620005a3565b50620005ce929150620005d2565b5090565b5b80821115620005ce5760008155600101620005d3565b8051620005f681620008f4565b919050565b600082601f8301126200060c578081fd5b81516001600160401b0380821115620006295762000629620008de565b604051601f8301601f19908116603f01168101908282118183101715620006545762000654620008de565b816040528381528660208588010111156200066d578485fd5b620006808460208301602089016200086e565b9695505050505050565b6000602082840312156200069c578081fd5b8151620006a981620008f4565b9392505050565b600060208284031215620006c2578081fd5b81518015158114620006a9578182fd5b60008060008060008060008060006101208a8c031215620006f1578485fd5b8951620006fe81620008f4565b60208b01519099506200071181620008f4565b97506200072160408b01620005e9565b96506200073160608b01620005e9565b95506200074160808b01620005e9565b94506200075160a08b01620005e9565b60c08b015160e08c015191955093506001600160401b038082111562000775578384fd5b620007838d838e01620005fb565b93506101008c01519150808211156200079a578283fd5b50620007a98c828d01620005fb565b9150509295985092959850929598565b600060208284031215620007cb578081fd5b81516001600160401b03811115620007e1578182fd5b620007ef84828501620005fb565b949350505050565b60006020828403121562000809578081fd5b815160ff81168114620006a9578182fd5b60808152600085518060808401526200083b8160a0850160208a016200086e565b6001600160a01b03958616602084015260ff9490941660408301525092166060830152601f01601f19160160a001919050565b60005b838110156200088b57818101518382015260200162000871565b838111156200089b576000848401525b50505050565b600181811c90821680620008b657607f821691505b60208210811415620008d857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146200090a57600080fd5b50565b60805160601c612a3462000980600039600081816102aa015281816109ff01528181610acc01528181610b5701528181610b9601528181610e4f01528181610f1901528181610fec0152818161126a015281816112df015281816115d4015281816116950152611bfa0152612a346000f3fe6080604052600436106102045760003560e01c806370a0823111610118578063c4bc5da5116100a0578063de560cca1161006f578063de560cca146105f8578063e6f3356b1461060e578063f6bf3ef61461062e578063f851a44014610653578063fba67d1e1461067357600080fd5b8063c4bc5da51461055d578063cbd4b9e814610572578063d44e19a614610592578063dd62ed3e146105b257600080fd5b8063a9059cbb116100e7578063a9059cbb146104ce578063aaf5eb68146104ee578063af997b361461050a578063b52f71bd1461051d578063baab7de91461053d57600080fd5b806370a082311461044357806374e7493b1461047957806395d89b4114610499578063a457c2d7146104ae57600080fd5b8063313ce5671161019b578063488117991161016a57806348811799146103b4578063495ebdc6146103d457806350fcbec0146103f45780635c975abb14610414578063679aefce1461042e57600080fd5b8063313ce56714610343578063395093511461035f578063439766ce1461037f578063439a12f01461039457600080fd5b806318160ddd116101d757806318160ddd146102cc57806323b872dd146102eb5780632bf325071461030b5780632c4e722e1461032d57600080fd5b80630289b70e1461020957806306fdde0314610246578063095ea7b314610268578063115f4fee14610298575b600080fd5b34801561021557600080fd5b50600a54610229906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561025257600080fd5b5061025b610693565b60405161023d9190612653565b34801561027457600080fd5b50610288610283366004612340565b610725565b604051901515815260200161023d565b3480156102a457600080fd5b506102297f000000000000000000000000000000000000000000000000000000000000000081565b3480156102d857600080fd5b506002545b60405190815260200161023d565b3480156102f757600080fd5b50610288610306366004612300565b61073c565b34801561031757600080fd5b5061032b6103263660046123a7565b6107f4565b005b34801561033957600080fd5b506102dd60055481565b34801561034f57600080fd5b506040516012815260200161023d565b34801561036b57600080fd5b5061028861037a366004612340565b610942565b34801561038b57600080fd5b5061032b610979565b3480156103a057600080fd5b50600854610229906001600160a01b031681565b3480156103c057600080fd5b5061032b6103cf3660046123ef565b6109db565b3480156103e057600080fd5b50600954610229906001600160a01b031681565b34801561040057600080fd5b506102dd61040f36600461243a565b610b24565b34801561042057600080fd5b506007546102889060ff1681565b34801561043a57600080fd5b506005546102dd565b34801561044f57600080fd5b506102dd61045e3660046122ac565b6001600160a01b031660009081526020819052604090205490565b34801561048557600080fd5b5061032b61049436600461240a565b610bf5565b3480156104a557600080fd5b5061025b610c60565b3480156104ba57600080fd5b506102886104c9366004612340565b610c6f565b3480156104da57600080fd5b506102886104e9366004612340565b610d0a565b3480156104fa57600080fd5b506102dd670de0b6b3a764000081565b61032b61051836600461245e565b610d17565b34801561052957600080fd5b5061032b610538366004612544565b610e2f565b34801561054957600080fd5b5061032b610558366004612544565b610fcc565b34801561056957600080fd5b5061032b611100565b34801561057e57600080fd5b5061032b61058d3660046123ef565b61115f565b34801561059e57600080fd5b5061032b6105ad3660046124f4565b6112bf565b3480156105be57600080fd5b506102dd6105cd3660046122c8565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b34801561060457600080fd5b506102dd60065481565b34801561061a57600080fd5b5061032b610629366004612544565b611463565b34801561063a57600080fd5b506007546102299061010090046001600160a01b031681565b34801561065f57600080fd5b50600b54610229906001600160a01b031681565b34801561067f57600080fd5b506102dd61068e36600461243a565b611676565b6060600380546106a290612995565b80601f01602080910402602001604051908101604052809291908181526020018280546106ce90612995565b801561071b5780601f106106f05761010080835404028352916020019161071b565b820191906000526020600020905b8154815290600101906020018083116106fe57829003601f168201915b5050505050905090565b60006107323384846116e4565b5060015b92915050565b6000610749848484611809565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156107d35760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b6107e785336107e28685612952565b6116e4565b60019150505b9392505050565b60075460ff16156108175760405162461bcd60e51b81526004016107ca90612686565b6060810151610834906001600160a01b03851690339030906119e1565b606081015161084f906001600160a01b038516908490611a52565b3060e082015260405163c0034cfb60e01b81526000906001600160a01b0384169063c0034cfb9061088490859060040161275e565b6040805180830381600087803b15801561089d57600080fd5b505af11580156108b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d59190612521565b50905060006108e48233611b13565b9050306001600160a01b0316856001600160a01b0316336001600160a01b03167f79a14def166d96da8b8cd7aa8344af4741fd6825c081d40096225b405e60baa4846040516109339190612867565b60405180910390a45050505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916107329185906107e29086906128fb565b600b546001600160a01b031633146109a35760405162461bcd60e51b81526004016107ca906126f0565b6007805460ff191660011790556040517fab35696f06e428ebc5ceba8cd17f8fed287baf43440206d1943af1ee53e6d26790600090a1565b60006109eb826020015130611b59565b600854909150610a28906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683611a52565b602082018190526008546040516373618c4d60e11b81526000916001600160a01b03169063e6c3189a90610a609086906004016127c2565b6040805180830381600087803b158015610a7957600080fd5b505af1158015610a8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab19190612521565b506009546040518281529192506001600160a01b03908116917f00000000000000000000000000000000000000000000000000000000000000009091169033907fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef0906020015b60405180910390a4505050565b60075460009060ff1615610b4a5760405162461bcd60e51b81526004016107ca90612686565b610b7f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330866119e1565b610b898383611b13565b60405181815290915030907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169033907f6b460f6f5497bb72eeec65f6df538e6388b2e74b8fc03e7d318653a663e73782906020015b60405180910390a492915050565b600b546001600160a01b03163314610c1f5760405162461bcd60e51b81526004016107ca906126f0565b60055460408051918252602082018390527f5fe72661ec4e10c57ee25f11a7e9125b4ff994b73b2e48e8575d6ffc8dbf2bf0910160405180910390a1600555565b6060600480546106a290612995565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610cf15760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016107ca565b610d0033856107e28685612952565b5060019392505050565b6000610732338484611809565b60075460ff1615610d3a5760405162461bcd60e51b81526004016107ca90612686565b3060a0820152600a5460085460405163397ec39160e11b81526000926001600160a01b03908116926372fd8722923492610d80928b928b928b9216908a906004016127d0565b6060604051808303818588803b158015610d9957600080fd5b505af1158015610dad573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610dd291906124bc565b925050506000610de28233611b13565b9050336001600160a01b03167f72d5c97d9890dbe24d69a3704e0e89586e02a7d5db392f629211d31c25bfbce13483604051610e1f9291906126bd565b60405180910390a2505050505050565b6000610e3b8630611b59565b600a54909150610e78906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683611a52565b60208201819052600a5460085460405163c3348f5160e01b81526000926001600160a01b039081169263c3348f5192610ec1928b928b928b92909116908a903390600401612815565b606060405180830381600087803b158015610edb57600080fd5b505af1158015610eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1391906124bc565b925050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031685856001818110610f6257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610f7791906122ac565b6001600160a01b0316336001600160a01b03167f7000ed2537cc33deca0eb8a6552be35f81bfaf280b500b5c9fdc84bf015652408a85604051610fbb92919061273a565b60405180910390a450505050505050565b6000610fd88630611b59565b600a54909150611015906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683611a52565b60208201819052600a54600854604051632f4d230960e21b81526000926001600160a01b039081169263bd348c249261105e928b928b928b92909116908a903390600401612815565b606060405180830381600087803b15801561107857600080fd5b505af115801561108c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b091906124bc565b92505050336001600160a01b03167f72d5c97d9890dbe24d69a3704e0e89586e02a7d5db392f629211d31c25bfbce188836040516110ef92919061273a565b60405180910390a250505050505050565b600b546001600160a01b0316331461112a5760405162461bcd60e51b81526004016107ca906126f0565b6007805460ff191690556040517fab5f6dacf93a267a93a533de8a56370de8341bbd8102017307e7be375c3dda6a90600090a1565b60075460ff16156111825760405162461bcd60e51b81526004016107ca90612686565b60408101516009546111a3916001600160a01b0390911690339030906119e1565b60085460408201516009546111c6926001600160a01b0391821692911690611a52565b3060a0820152600854604051633bf8c17360e01b81526000916001600160a01b031690633bf8c173906111fd9085906004016127c2565b6040805180830381600087803b15801561121657600080fd5b505af115801561122a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124e9190612521565b509050600061125d8233611b13565b60405181815290915030907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169033907f6b460f6f5497bb72eeec65f6df538e6388b2e74b8fc03e7d318653a663e7378290602001610b17565b60006112cb8330611b59565b600854909150611308906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683611a52565b6060820181905260085460405163c0034cfb60e01b81526000916001600160a01b03169063c0034cfb9061134090869060040161275e565b6040805180830381600087803b15801561135957600080fd5b505af115801561136d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113919190612521565b509050306001600160a01b031683602001516001600160a01b0316638230ecd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156113db57600080fd5b505afa1580156113ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611413919061238b565b6001600160a01b0316336001600160a01b03167f79a14def166d96da8b8cd7aa8344af4741fd6825c081d40096225b405e60baa4846040516114559190612890565b60405180910390a450505050565b60075460ff16156114865760405162461bcd60e51b81526004016107ca90612686565b6114d3333087868660008181106114ad57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906114c291906122ac565b6001600160a01b03169291906119e1565b600a54611528906001600160a01b031686858560008161150357634e487b7160e01b600052603260045260246000fd5b905060200201602081019061151891906122ac565b6001600160a01b03169190611a52565b3060a0820152600a5460085460405163b193811b60e01b81526000926001600160a01b039081169263b193811b9261156e928b928b928b928b9216908a906004016128ba565b606060405180830381600087803b15801561158857600080fd5b505af115801561159c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c091906124bc565b9250505060006115d08233611b13565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168585600081811061161d57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061163291906122ac565b6001600160a01b0316336001600160a01b03167f7000ed2537cc33deca0eb8a6552be35f81bfaf280b500b5c9fdc84bf015652408a85604051610fbb9291906126bd565b60006116828383611b59565b6040518181529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690309033907fee02732fab40ece8284c756220846dff4b8d32058b86b35b4f0459bf172fcef090602001610be7565b6001600160a01b0383166117465760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016107ca565b6001600160a01b0382166117a75760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016107ca565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03831661186d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016107ca565b6001600160a01b0382166118cf5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016107ca565b6001600160a01b038316600090815260208190526040902054818110156119475760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016107ca565b6119518282612952565b6001600160a01b0380861660009081526020819052604080822093909355908516815290812080548492906119879084906128fb565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516119d391815260200190565b60405180910390a350505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611a4c9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c26565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015611a9e57600080fd5b505afa158015611ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad69190612422565b611ae091906128fb565b6040516001600160a01b038516602482015260448101829052909150611a4c90859063095ea7b360e01b90606401611a15565b6000611b3c670de0b6b3a7640000611b3660055486611cf890919063ffffffff16565b90611d04565b600654909150611b4c9084611d10565b6006556107368282611d1c565b33600090815260208190526040812054831115611bb85760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f7567687420746f6b656e7320746f20756e777261700000000060448201526064016107ca565b611bd1611bc460025490565b600654611b369086611cf8565b9050611bdd3384611dfb565b600654611bea9082611f4a565b6006556107366001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383611f56565b505050565b6000611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611f869092919063ffffffff16565b805190915015611c215780806020019051810190611c99919061236b565b611c215760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016107ca565b60006107ed8284612933565b60006107ed8284612913565b60006107ed82846128fb565b6001600160a01b038216611d725760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016107ca565b8060026000828254611d8491906128fb565b90915550506001600160a01b03821660009081526020819052604081208054839290611db19084906128fb565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216611e5b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016107ca565b6001600160a01b03821660009081526020819052604090205481811015611ecf5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016107ca565b611ed98282612952565b6001600160a01b03841660009081526020819052604081209190915560028054849290611f07908490612952565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016117fc565b60006107ed8284612952565b6040516001600160a01b038316602482015260448101829052611c2190849063a9059cbb60e01b90606401611a15565b6060611f958484600085611f9d565b949350505050565b606082471015611ffe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016107ca565b843b61204c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107ca565b600080866001600160a01b031685876040516120689190612637565b60006040518083038185875af1925050503d80600081146120a5576040519150601f19603f3d011682016040523d82523d6000602084013e6120aa565b606091505b50915091506120ba8282866120c5565b979650505050505050565b606083156120d45750816107ed565b8251156120e45782518084602001fd5b8160405162461bcd60e51b81526004016107ca9190612653565b8035612109816129e6565b919050565b60008083601f84011261211f578182fd5b50813567ffffffffffffffff811115612136578182fd5b6020830191508360208260051b850101111561215157600080fd5b9250929050565b600061010080838503121561216b578182fd5b6040519081019067ffffffffffffffff8211818310171561219a57634e487b7160e01b83526041600452602483fd5b81604052809250833591506121ae826129e6565b8181526121bd602085016120fe565b60208201526121ce604085016120fe565b6040820152606084013560608201526080840135608082015260a084013560a082015260c084013560c082015261220760e085016120fe565b60e0820152505092915050565b600060c08284031215612225578081fd5b60405160c0810181811067ffffffffffffffff8211171561225457634e487b7160e01b83526041600452602483fd5b6040529050808235612265816129e6565b808252506020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013561229f816129e6565b60a0919091015292915050565b6000602082840312156122bd578081fd5b81356107ed816129e6565b600080604083850312156122da578081fd5b82356122e5816129e6565b915060208301356122f5816129e6565b809150509250929050565b600080600060608486031215612314578081fd5b833561231f816129e6565b9250602084013561232f816129e6565b929592945050506040919091013590565b60008060408385031215612352578182fd5b823561235d816129e6565b946020939093013593505050565b60006020828403121561237c578081fd5b815180151581146107ed578182fd5b60006020828403121561239c578081fd5b81516107ed816129e6565b600080600061014084860312156123bc578283fd5b83356123c7816129e6565b925060208401356123d7816129e6565b91506123e68560408601612158565b90509250925092565b600060c08284031215612400578081fd5b6107ed8383612214565b60006020828403121561241b578081fd5b5035919050565b600060208284031215612433578081fd5b5051919050565b6000806040838503121561244c578182fd5b8235915060208301356122f5816129e6565b6000806000806101008587031215612474578182fd5b84359350602085013567ffffffffffffffff811115612491578283fd5b61249d8782880161210e565b90945092506124b190508660408701612214565b905092959194509250565b6000806000606084860312156124d0578081fd5b8351925060208401516124e2816129e6565b80925050604084015190509250925092565b6000806101208385031215612507578182fd5b823591506125188460208501612158565b90509250929050565b60008060408385031215612533578182fd5b505080516020909101519092909150565b6000806000806000610120868803121561255c578283fd5b8535945060208601359350604086013567ffffffffffffffff811115612580578384fd5b61258c8882890161210e565b90945092506125a090508760608801612214565b90509295509295909350565b81835260006020808501945082825b858110156125e95781356125ce816129e6565b6001600160a01b0316875295820195908201906001016125bb565b509495945050505050565b80516001600160a01b0390811683526020808301519084015260408083015190840152606080830151908401526080808301519084015260a09182015116910152565b60008251612649818460208701612969565b9190910192915050565b6020815260008251806020840152612672816040850160208701612969565b601f01601f19169190910160400192915050565b60208082526018908201527f436f6e747261637420686173206265656e207061757365640000000000000000604082015260600190565b6060815260006126e060608301600381526262757960e81b602082015260400190565b6020830194909452506040015290565b6020808252602a908201527f4f6e6c7920636f6e74726163742061646d696e2063616e2063616c6c207468696040820152693990333ab731ba34b7b760b11b606082015260800190565b6060815260006126e06060830160048152631cd95b1b60e21b602082015260400190565b81516001600160a01b039081168252602080840151821690830152604080840151821690830152606080840151908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b60c0810161073682846125f4565b60006101208783528060208401526127eb81840187896125ac565b6001600160a01b0386166040850152915061280b905060608301846125f4565b9695505050505050565b6000610140888352806020840152612830818401888a6125ac565b6001600160a01b038781166040860152909250905061285260608401866125f4565b80841661012084015250979650505050505050565b8181526040602082015260006107ed60408301600381526262757960e81b602082015260400190565b8181526040602082015260006107ed6040830160048152631cd95b1b60e21b602082015260400190565b60006101408883528760208401528060408401526128db81840187896125ac565b6001600160a01b038616606085015291506120ba905060808301846125f4565b6000821982111561290e5761290e6129d0565b500190565b60008261292e57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561294d5761294d6129d0565b500290565b600082821015612964576129646129d0565b500390565b60005b8381101561298457818101518382015260200161296c565b83811115611a4c5750506000910152565b600181811c908216806129a957607f821691505b602082108114156129ca57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146129fb57600080fd5b5056fea26469706673582212202ed485e1d84beb25f2a55ef8c37642ab245b8850c683b83c4d4f66f65adfa3b164736f6c634300080400330000000000000000000000004e3decbb3645551b8a19f0ea1678079fcb33fb4c0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000cbba8c0645ffb8aa6ec868f6f5858f2b0eae34da00000000000000000000000043a98e5c4a7f3b7f11080fc9d58b0b8a80ca954e000000000000000000000000b711f3a71c00d92ef862a4af2f584635dfe318b80000000000000000000000008a73fda882601c4b84b0c52d7d85e4ba46357ca10000000000000000000000000000000000000000000000005b084629314f20000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000244a61727669732053796e746865746963204c6567616379204672656e6368204672616e630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046a46524600000000000000000000000000000000000000000000000000000000

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

0000000000000000000000004e3decbb3645551b8a19f0ea1678079fcb33fb4c0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000cbba8c0645ffb8aa6ec868f6f5858f2b0eae34da00000000000000000000000043a98e5c4a7f3b7f11080fc9d58b0b8a80ca954e000000000000000000000000b711f3a71c00d92ef862a4af2f584635dfe318b80000000000000000000000008a73fda882601c4b84b0c52d7d85e4ba46357ca10000000000000000000000000000000000000000000000005b084629314f20000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000244a61727669732053796e746865746963204c6567616379204672656e6368204672616e630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046a46524600000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _pegToken (address): 0x4e3decbb3645551b8a19f0ea1678079fcb33fb4c
Arg [1] : _collateralToken (address): 0x2791bca1f2de4661ed88a30c99a7a9449aa84174
Arg [2] : _synthereumPoolAddress (address): 0xcbba8c0645ffb8aa6ec868f6f5858f2b0eae34da
Arg [3] : _synthereumFinder (address): 0x43a98e5c4a7f3b7f11080fc9d58b0b8a80ca954e
Arg [4] : _atomicSwapAddr (address): 0xb711f3a71c00d92ef862a4af2f584635dfe318b8
Arg [5] : _admin (address): 0x8a73fda882601c4b84b0c52d7d85e4ba46357ca1
Arg [6] : _rate (uint256): 6559570000000000000
Arg [7] : _name (string): Jarvis Synthetic Legacy French Franc
Arg [8] : _symbol (string): jFRF

-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 0000000000000000000000004e3decbb3645551b8a19f0ea1678079fcb33fb4c
Arg [1] : 0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174
Arg [2] : 000000000000000000000000cbba8c0645ffb8aa6ec868f6f5858f2b0eae34da
Arg [3] : 00000000000000000000000043a98e5c4a7f3b7f11080fc9d58b0b8a80ca954e
Arg [4] : 000000000000000000000000b711f3a71c00d92ef862a4af2f584635dfe318b8
Arg [5] : 0000000000000000000000008a73fda882601c4b84b0c52d7d85e4ba46357ca1
Arg [6] : 0000000000000000000000000000000000000000000000005b084629314f2000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [10] : 4a61727669732053796e746865746963204c6567616379204672656e63682046
Arg [11] : 72616e6300000000000000000000000000000000000000000000000000000000
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [13] : 6a46524600000000000000000000000000000000000000000000000000000000


Deployed ByteCode Sourcemap

108224:12688:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108595:29;;;;;;;;;;-1:-1:-1;108595:29:0;;;;-1:-1:-1;;;;;108595:29:0;;;;;;-1:-1:-1;;;;;11337:32:1;;;11319:51;;11307:2;11292:18;108595:29:0;;;;;;;;34236:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;36403:169::-;;;;;;;;;;-1:-1:-1;36403:169:0;;;;;:::i;:::-;;:::i;:::-;;;12514:14:1;;12507:22;12489:41;;12477:2;12462:18;36403:169:0;12444:92:1;106201:29:0;;;;;;;;;;;;;;;35356:108;;;;;;;;;;-1:-1:-1;35444:12:0;;35356:108;;;22452:25:1;;;22440:2;22425:18;35356:108:0;22407:76:1;37054:422:0;;;;;;;;;;-1:-1:-1;37054:422:0;;;;;:::i;:::-;;:::i;113771:1045::-;;;;;;;;;;-1:-1:-1;113771:1045:0;;;;;:::i;:::-;;:::i;:::-;;106284:19;;;;;;;;;;;;;;;;35198:93;;;;;;;;;;-1:-1:-1;35198:93:0;;35281:2;25783:36:1;;25771:2;25756:18;35198:93:0;25738:87:1;37885:215:0;;;;;;;;;;-1:-1:-1;37885:215:0;;;;;:::i;:::-;;:::i;119720:96::-;;;;;;;;;;;;;:::i;108441:53::-;;;;;;;;;;-1:-1:-1;108441:53:0;;;;-1:-1:-1;;;;;108441:53:0;;;112890:787;;;;;;;;;;-1:-1:-1;112890:787:0;;;;;:::i;:::-;;:::i;108521:32::-;;;;;;;;;;-1:-1:-1;108521:32:0;;;;-1:-1:-1;;;;;108521:32:0;;;111013:360;;;;;;;;;;-1:-1:-1;111013:360:0;;;;;:::i;:::-;;:::i;108340:18::-;;;;;;;;;;-1:-1:-1;108340:18:0;;;;;;;;120051:73;;;;;;;;;;-1:-1:-1;120114:4:0;;120051:73;;35527:127;;;;;;;;;;-1:-1:-1;35527:127:0;;;;;:::i;:::-;-1:-1:-1;;;;;35628:18:0;35601:7;35628:18;;;;;;;;;;;;35527:127;119927:118;;;;;;;;;;-1:-1:-1;119927:118:0;;;;;:::i;:::-;;:::i;34455:104::-;;;;;;;;;;;;;:::i;38603:377::-;;;;;;;;;;-1:-1:-1;38603:377:0;;;;;:::i;:::-;;:::i;35867:175::-;;;;;;;;;;-1:-1:-1;35867:175:0;;;;;:::i;:::-;;:::i;106089:40::-;;;;;;;;;;;;106125:4;106089:40;;117003:677;;;;;;:::i;:::-;;:::i;117781:936::-;;;;;;;;;;-1:-1:-1;117781:936:0;;;;;:::i;:::-;;:::i;118816:845::-;;;;;;;;;;-1:-1:-1;118816:845:0;;;;;:::i;:::-;;:::i;119822:99::-;;;;;;;;;;;;;:::i;111885:861::-;;;;;;;;;;-1:-1:-1;111885:861:0;;;;;:::i;:::-;;:::i;114931:800::-;;;;;;;;;;-1:-1:-1;114931:800:0;;;;;:::i;:::-;;:::i;36105:151::-;;;;;;;;;;-1:-1:-1;36105:151:0;;;;;:::i;:::-;-1:-1:-1;;;;;36221:18:0;;;36194:7;36221:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;36105:151;106379:30;;;;;;;;;;;;;;;;115826:1084;;;;;;;;;;-1:-1:-1;115826:1084:0;;;;;:::i;:::-;;:::i;108395:41::-;;;;;;;;;;-1:-1:-1;108395:41:0;;;;;;;-1:-1:-1;;;;;108395:41:0;;;108631:20;;;;;;;;;;-1:-1:-1;108631:20:0;;;;-1:-1:-1;;;;;108631:20:0;;;111470:274;;;;;;;;;;-1:-1:-1;111470:274:0;;;;;:::i;:::-;;:::i;34236:100::-;34290:13;34323:5;34316:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34236:100;:::o;36403:169::-;36486:4;36503:39;15937:10;36526:7;36535:6;36503:8;:39::i;:::-;-1:-1:-1;36560:4:0;36403:169;;;;;:::o;37054:422::-;37160:4;37177:36;37187:6;37195:9;37206:6;37177:9;:36::i;:::-;-1:-1:-1;;;;;37253:19:0;;37226:24;37253:19;;;:11;:19;;;;;;;;15937:10;37253:33;;;;;;;;37305:26;;;;37297:79;;;;-1:-1:-1;;;37297:79:0;;17275:2:1;37297:79:0;;;17257:21:1;17314:2;17294:18;;;17287:30;17353:34;17333:18;;;17326:62;-1:-1:-1;;;17404:18:1;;;17397:38;17452:19;;37297:79:0;;;;;;;;;37387:57;37396:6;15937:10;37418:25;37437:6;37418:16;:25;:::i;:::-;37387:8;:57::i;:::-;37464:4;37457:11;;;37054:422;;;;;;:::o;113771:1045::-;109820:6;;;;109819:7;109811:44;;;;-1:-1:-1;;;109811:44:0;;;;;;;:::i;:::-;114144:25:::1;::::0;::::1;::::0;114060:116:::1;::::0;-1:-1:-1;;;;;114060:34:0;::::1;::::0;114103:10:::1;::::0;114130:4:::1;::::0;114060:34:::1;:116::i;:::-;114323:25;::::0;::::1;::::0;114243:112:::1;::::0;-1:-1:-1;;;;;114243:39:0;::::1;::::0;114299:14;;114243:39:::1;:112::i;:::-;114444:4;114408:25;::::0;::::1;:41:::0;114485:40:::1;::::0;-1:-1:-1;;;114485:40:0;;114457:22:::1;::::0;-1:-1:-1;;;;;114485:23:0;::::1;::::0;::::1;::::0;:40:::1;::::0;114408:15;;114485:40:::1;;;:::i;:::-;;::::0;::::1;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114456:69;;;114598:23;114624:38;114635:14;114651:10;114624;:38::i;:::-;114598:64;;114760:4;-1:-1:-1::0;;;;;114676:134:0::1;114725:17;-1:-1:-1::0;;;;;114676:134:0::1;114698:10;-1:-1:-1::0;;;;;114676:134:0::1;;114774:15;114676:134;;;;;;:::i;:::-;;;;;;;;109862:1;;113771:1045:::0;;;:::o;37885:215::-;15937:10;37973:4;38022:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;38022:34:0;;;;;;;;;;37973:4;;37990:80;;38013:7;;38022:47;;38059:10;;38022:47;:::i;119720:96::-;109925:5;;-1:-1:-1;;;;;109925:5:0;109911:10;:19;109903:74;;;;-1:-1:-1;;;109903:74:0;;;;;;;:::i;:::-;119769:6:::1;:13:::0;;-1:-1:-1;;119769:13:0::1;119778:4;119769:13;::::0;;119794:16:::1;::::0;::::1;::::0;119769:6:::1;::::0;119794:16:::1;119720:96::o:0;112890:787::-;113067:25;113102:52;113115:13;:23;;;113148:4;113102:12;:52::i;:::-;113281:14;;113067:87;;-1:-1:-1;113245:71:0;;-1:-1:-1;;;;;113245:5:0;:27;;;113281:14;113067:87;113245:27;:71::i;:::-;113420:23;;;:43;;;113503:14;;:36;;-1:-1:-1;;;113503:36:0;;113471:26;;-1:-1:-1;;;;;113503:14:0;;:21;;:36;;113420:13;;113503:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;113618:18:0;;113553:118;;22452:25:1;;;113470:69:0;;-1:-1:-1;;;;;;113618:18:0;;;;113595:5;113553:118;;;;113568:10;;113553:118;;22440:2:1;22425:18;113553:118:0;;;;;;;;112890:787;;;:::o;111013:360::-;109820:6;;111125:23;;109820:6;;109819:7;109811:44;;;;-1:-1:-1;;;109811:44:0;;;;;;;:::i;:::-;111160:66:::1;-1:-1:-1::0;;;;;111160:5:0::1;:22;111183:10;111203:4;111210:15:::0;111160:22:::1;:66::i;:::-;111251:38;111262:15;111279:9;111251:10;:38::i;:::-;111303:64;::::0;22452:25:1;;;111233:56:0;;-1:-1:-1;111344:4:0::1;::::0;111328:5:::1;-1:-1:-1::0;;;;;111303:64:0::1;::::0;111308:10:::1;::::0;111303:64:::1;::::0;22440:2:1;22425:18;111303:64:0::1;;;;;;;;111013:360:::0;;;;:::o;119927:118::-;109925:5;;-1:-1:-1;;;;;109925:5:0;109911:10;:19;109903:74;;;;-1:-1:-1;;;109903:74:0;;;;;;;:::i;:::-;120004:4:::1;::::0;119993:25:::1;::::0;;24818::1;;;24874:2;24859:18;;24852:34;;;119993:25:0::1;::::0;24791:18:1;119993:25:0::1;;;;;;;120025:4;:14:::0;119927:118::o;34455:104::-;34511:13;34544:7;34537:14;;;;;:::i;38603:377::-;15937:10;38696:4;38740:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;38740:34:0;;;;;;;;;;38793:35;;;;38785:85;;;;-1:-1:-1;;;38785:85:0;;20447:2:1;38785:85:0;;;20429:21:1;20486:2;20466:18;;;20459:30;20525:34;20505:18;;;20498:62;-1:-1:-1;;;20576:18:1;;;20569:35;20621:19;;38785:85:0;20419:227:1;38785:85:0;38881:67;15937:10;38904:7;38913:34;38932:15;38913:16;:34;:::i;38881:67::-;-1:-1:-1;38968:4:0;;38603:377;-1:-1:-1;;;38603:377:0:o;35867:175::-;35953:4;35970:42;15937:10;35994:9;36005:6;35970:9;:42::i;117003:677::-;109820:6;;;;109819:7;109811:44;;;;-1:-1:-1;;;109811:44:0;;;;;;;:::i;:::-;117279:4:::1;117248:20;::::0;::::1;:36:::0;117329:10:::1;::::0;117445:14:::1;::::0;117329:160:::1;::::0;-1:-1:-1;;;117329:160:0;;117296:22:::1;::::0;-1:-1:-1;;;;;117329:10:0;;::::1;::::0;:30:::1;::::0;117367:9:::1;::::0;117329:160:::1;::::0;117388:22;;117421:13;;;;117445:14:::1;::::0;117248:10;;117329:160:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117291:198;;;;117538:23;117564:38;117575:14;117591:10;117564;:38::i;:::-;117538:64;;117628:10;-1:-1:-1::0;;;;;117616:58:0::1;;117647:9;117658:15;117616:58;;;;;;;:::i;:::-;;;;;;;;109862:1;;117003:677:::0;;;;:::o;117781:936::-;118035:24;118062:47;118075:18;118103:4;118062:12;:47::i;:::-;118192:10;;118035:74;;-1:-1:-1;118156:66:0;;-1:-1:-1;;;;;118156:5:0;:27;;;118192:10;118035:74;118156:27;:66::i;:::-;118289:22;;;:41;;;118373:10;;118471:14;;118373:165;;-1:-1:-1;;;118373:165:0;;118342:20;;-1:-1:-1;;;;;118373:10:0;;;;:35;;:165;;118419:17;;118447:13;;;;118471:14;;;;118289:22;;118519:10;;118373:165;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118337:201;;;;118635:5;-1:-1:-1;;;;;118552:159:0;118601:13;;118615:1;118601:16;;;;;-1:-1:-1;;;118601:16:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;118552:159:0;118574:10;-1:-1:-1;;;;;118552:159:0;;118665:18;118692:12;118552:159;;;;;;;:::i;:::-;;;;;;;;117781:936;;;;;;;:::o;118816:845::-;119067:24;119094:47;119107:18;119135:4;119094:12;:47::i;:::-;119224:10;;119067:74;;-1:-1:-1;119188:66:0;;-1:-1:-1;;;;;119188:5:0;:27;;;119224:10;119067:74;119188:27;:66::i;:::-;119321:22;;;:41;;;119405:10;;119509:14;;119405:171;;-1:-1:-1;;;119405:171:0;;119374:20;;-1:-1:-1;;;;;119405:10:0;;;;:41;;:171;;119457:17;;119485:13;;;;119509:14;;;;119321:22;;119557:10;;119405:171;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;119369:207;;;;119602:10;-1:-1:-1;;;;;119590:65:0;;119622:18;119642:12;119590:65;;;;;;;:::i;:::-;;;;;;;;118816:845;;;;;;;:::o;119822:99::-;109925:5;;-1:-1:-1;;;;;109925:5:0;109911:10;:19;109903:74;;;;-1:-1:-1;;;109903:74:0;;;;;;;:::i;:::-;119872:6:::1;:14:::0;;-1:-1:-1;;119872:14:0::1;::::0;;119898:17:::1;::::0;::::1;::::0;119881:5:::1;::::0;119898:17:::1;119822:99::o:0;111885:861::-;109820:6;;;;109819:7;109811:44;;;;-1:-1:-1;;;109811:44:0;;;;;;;:::i;:::-;112127:28:::1;::::0;::::1;::::0;112042:18:::1;::::0;:120:::1;::::0;-1:-1:-1;;;;;112042:18:0;;::::1;::::0;112086:10:::1;::::0;112113:4:::1;::::0;112042:35:::1;:120::i;:::-;112296:14;::::0;112320:28:::1;::::0;::::1;::::0;112239:18:::1;::::0;:116:::1;::::0;-1:-1:-1;;;;;112239:18:0;;::::1;::::0;112296:14;::::1;::::0;112239:40:::1;:116::i;:::-;112476:4;112444:21;::::0;::::1;:37:::0;112518:14:::1;::::0;:32:::1;::::0;-1:-1:-1;;;112518:32:0;;112489:23:::1;::::0;-1:-1:-1;;;;;112518:14:0::1;::::0;:19:::1;::::0;:32:::1;::::0;112444:11;;112518:32:::1;;;:::i;:::-;;::::0;::::1;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;112488:62;;;112597:23;112623:39;112634:15;112651:10;112623;:39::i;:::-;112676:64;::::0;22452:25:1;;;112597:65:0;;-1:-1:-1;112717:4:0::1;::::0;112701:5:::1;-1:-1:-1::0;;;;;112676:64:0::1;::::0;112681:10:::1;::::0;112676:64:::1;::::0;22440:2:1;22425:18;112676:64:0::1;22407:76:1::0;114931:800:0;115146:25;115174:46;115187:17;115214:4;115174:12;:46::i;:::-;115316:14;;115146:74;;-1:-1:-1;115280:71:0;;-1:-1:-1;;;;;115280:5:0;:27;;;115316:14;115146:74;115280:27;:71::i;:::-;115432:25;;;:45;;;115514:14;;:40;;-1:-1:-1;;;115514:40:0;;115485:23;;-1:-1:-1;;;;;115514:14:0;;:23;;:40;;115432:15;;115514:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115484:70;;;115674:4;-1:-1:-1;;;;;115566:159:0;115615:15;:24;;;-1:-1:-1;;;;;115615:39:0;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;115566:159:0;115588:10;-1:-1:-1;;;;;115566:159:0;;115688:15;115566:159;;;;;;:::i;:::-;;;;;;;;114931:800;;;;:::o;115826:1084::-;109820:6;;;;109819:7;109811:44;;;;-1:-1:-1;;;109811:44:0;;;;;;;:::i;:::-;116090:112:::1;116140:10;116167:4;116181:14;116097:13;;116111:1;116097:16;;;;;-1:-1:-1::0;;;116097:16:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;116090:41:0::1;::::0;:112;;:41:::1;:112::i;:::-;116292:10;::::0;116229:104:::1;::::0;-1:-1:-1;;;;;116292:10:0::1;116312:14:::0;116236:13;;116292:10:::1;116236:16:::0;::::1;;-1:-1:-1::0;;;116236:16:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;116229:46:0::1;::::0;:104;:46:::1;:104::i;:::-;116417:4;116386:20;::::0;::::1;:36:::0;116464:10:::1;::::0;116590:14:::1;::::0;116464:170:::1;::::0;-1:-1:-1;;;116464:170:0;;116434:19:::1;::::0;-1:-1:-1;;;;;116464:10:0;;::::1;::::0;:33:::1;::::0;:170:::1;::::0;116508:14;;116533:22;;116566:13;;;;116590:14:::1;::::0;116386:10;;116464:170:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116429:205;;;;116681:23;116707:35;116718:11;116731:10;116707;:35::i;:::-;116681:61;;116830:5;-1:-1:-1::0;;;;;116756:148:0::1;116797:13;;116811:1;116797:16;;;;;-1:-1:-1::0;;;116797:16:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;116756:148:0::1;116778:10;-1:-1:-1::0;;;;;116756:148:0::1;;116859:14;116882:15;116756:148;;;;;;;:::i;111470:274::-:0;111568:22;111619:42;111632:17;111651:9;111619:12;:42::i;:::-;111673:65;;22452:25:1;;;111602:59:0;;-1:-1:-1;;;;;;111715:5:0;111673:65;;111700:4;;111680:10;;111673:65;;22440:2:1;22425:18;111673:65:0;22407:76:1;41959:346:0;-1:-1:-1;;;;;42061:19:0;;42053:68;;;;-1:-1:-1;;;42053:68:0;;18492:2:1;42053:68:0;;;18474:21:1;18531:2;18511:18;;;18504:30;18570:34;18550:18;;;18543:62;-1:-1:-1;;;18621:18:1;;;18614:34;18665:19;;42053:68:0;18464:226:1;42053:68:0;-1:-1:-1;;;;;42140:21:0;;42132:68;;;;-1:-1:-1;;;42132:68:0;;14870:2:1;42132:68:0;;;14852:21:1;14909:2;14889:18;;;14882:30;14948:34;14928:18;;;14921:62;-1:-1:-1;;;14999:18:1;;;14992:32;15041:19;;42132:68:0;14842:224:1;42132:68:0;-1:-1:-1;;;;;42213:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;42265:32;;22452:25:1;;;42265:32:0;;22425:18:1;42265:32:0;;;;;;;;41959:346;;;:::o;39470:604::-;-1:-1:-1;;;;;39576:20:0;;39568:70;;;;-1:-1:-1;;;39568:70:0;;18086:2:1;39568:70:0;;;18068:21:1;18125:2;18105:18;;;18098:30;18164:34;18144:18;;;18137:62;-1:-1:-1;;;18215:18:1;;;18208:35;18260:19;;39568:70:0;18058:227:1;39568:70:0;-1:-1:-1;;;;;39657:23:0;;39649:71;;;;-1:-1:-1;;;39649:71:0;;14063:2:1;39649:71:0;;;14045:21:1;14102:2;14082:18;;;14075:30;14141:34;14121:18;;;14114:62;-1:-1:-1;;;14192:18:1;;;14185:33;14235:19;;39649:71:0;14035:225:1;39649:71:0;-1:-1:-1;;;;;39817:17:0;;39793:21;39817:17;;;;;;;;;;;39853:23;;;;39845:74;;;;-1:-1:-1;;;39845:74:0;;15273:2:1;39845:74:0;;;15255:21:1;15312:2;15292:18;;;15285:30;15351:34;15331:18;;;15324:62;-1:-1:-1;;;15402:18:1;;;15395:36;15448:19;;39845:74:0;15245:228:1;39845:74:0;39950:22;39966:6;39950:13;:22;:::i;:::-;-1:-1:-1;;;;;39930:17:0;;;:9;:17;;;;;;;;;;;:42;;;;39983:20;;;;;;;;:30;;40007:6;;39930:9;39983:30;;40007:6;;39983:30;:::i;:::-;;;;;;;;40048:9;-1:-1:-1;;;;;40031:35:0;40040:6;-1:-1:-1;;;;;40031:35:0;;40059:6;40031:35;;;;22452:25:1;;22440:2;22425:18;;22407:76;40031:35:0;;;;;;;;39470:604;;;;:::o;43821:205::-;43949:68;;-1:-1:-1;;;;;11948:15:1;;;43949:68:0;;;11930:34:1;12000:15;;11980:18;;;11973:43;12032:18;;;12025:34;;;43922:96:0;;43942:5;;-1:-1:-1;;;43972:27:0;11865:18:1;;43949:68:0;;;;-1:-1:-1;;43949:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;43949:68:0;-1:-1:-1;;;;;;43949:68:0;;;;;;;;;;43922:19;:96::i;:::-;43821:205;;;;:::o;44925:283::-;45045:39;;-1:-1:-1;;;45045:39:0;;45069:4;45045:39;;;11593:34:1;-1:-1:-1;;;;;11663:15:1;;;11643:18;;;11636:43;45022:20:0;;45087:5;;45045:15;;;;;11528:18:1;;45045:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;:::-;45130:69;;-1:-1:-1;;;;;12262:32:1;;45130:69:0;;;12244:51:1;12311:18;;;12304:34;;;45022:70:0;;-1:-1:-1;45103:97:0;;45123:5;;-1:-1:-1;;;45153:22:0;12217:18:1;;45130:69:0;12199:145:1;107179:253:0;107257:20;107304:32;106125:4;107304:17;107316:4;;107304:7;:11;;:17;;;;:::i;:::-;:21;;:32::i;:::-;107361:15;;107289:47;;-1:-1:-1;107361:28:0;;107381:7;107361:19;:28::i;:::-;107343:15;:46;107396:30;107402:9;107413:12;107396:5;:30::i;107653:401::-;107783:10;107733:20;35628:18;;;;;;;;;;;107798:7;-1:-1:-1;107773:32:0;107765:73;;;;-1:-1:-1;;;107765:73:0;;19255:2:1;107765:73:0;;;19237:21:1;19294:2;19274:18;;;19267:30;19333;19313:18;;;19306:58;19381:18;;107765:73:0;19227:178:1;107765:73:0;107860:47;107893:13;35444:12;;;35356:108;107893:13;107860:15;;:28;;107880:7;107860:19;:28::i;:47::-;107845:62;;107914:26;107920:10;107932:7;107914:5;:26::i;:::-;107965:15;;:33;;107985:12;107965:19;:33::i;:::-;107947:15;:51;108005:43;-1:-1:-1;;;;;108005:5:0;:18;108024:9;108035:12;108005:18;:43::i;42908:92::-;;;;:::o;46070:761::-;46494:23;46520:69;46548:4;46520:69;;;;;;;;;;;;;;;;;46528:5;-1:-1:-1;;;;;46520:27:0;;;:69;;;;;:::i;:::-;46604:17;;46494:95;;-1:-1:-1;46604:21:0;46600:224;;46746:10;46735:30;;;;;;;;;;;;:::i;:::-;46727:85;;;;-1:-1:-1;;;46727:85:0;;19612:2:1;46727:85:0;;;19594:21:1;19651:2;19631:18;;;19624:30;19690:34;19670:18;;;19663:62;-1:-1:-1;;;19741:18:1;;;19734:40;19791:19;;46727:85:0;19584:232:1;50368:98:0;50426:7;50453:5;50457:1;50453;:5;:::i;50767:98::-;50825:7;50852:5;50856:1;50852;:5;:::i;49630:98::-;49688:7;49715:5;49719:1;49715;:5;:::i;40356:338::-;-1:-1:-1;;;;;40440:21:0;;40432:65;;;;-1:-1:-1;;;40432:65:0;;20853:2:1;40432:65:0;;;20835:21:1;20892:2;20872:18;;;20865:30;20931:33;20911:18;;;20904:61;20982:18;;40432:65:0;20825:181:1;40432:65:0;40588:6;40572:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;40605:18:0;;:9;:18;;;;;;;;;;:28;;40627:6;;40605:9;:28;;40627:6;;40605:28;:::i;:::-;;;;-1:-1:-1;;40649:37:0;;22452:25:1;;;-1:-1:-1;;;;;40649:37:0;;;40666:1;;40649:37;;22440:2:1;22425:18;40649:37:0;;;;;;;40356:338;;:::o;41027:494::-;-1:-1:-1;;;;;41111:21:0;;41103:67;;;;-1:-1:-1;;;41103:67:0;;17684:2:1;41103:67:0;;;17666:21:1;17723:2;17703:18;;;17696:30;17762:34;17742:18;;;17735:62;-1:-1:-1;;;17813:18:1;;;17806:31;17854:19;;41103:67:0;17656:223:1;41103:67:0;-1:-1:-1;;;;;41270:18:0;;41245:22;41270:18;;;;;;;;;;;41307:24;;;;41299:71;;;;-1:-1:-1;;;41299:71:0;;14467:2:1;41299:71:0;;;14449:21:1;14506:2;14486:18;;;14479:30;14545:34;14525:18;;;14518:62;-1:-1:-1;;;14596:18:1;;;14589:32;14638:19;;41299:71:0;14439:224:1;41299:71:0;41402:23;41419:6;41402:14;:23;:::i;:::-;-1:-1:-1;;;;;41381:18:0;;:9;:18;;;;;;;;;;:44;;;;41436:12;:22;;41452:6;;41381:9;41436:22;;41452:6;;41436:22;:::i;:::-;;;;-1:-1:-1;;41476:37:0;;22452:25:1;;;41502:1:0;;-1:-1:-1;;;;;41476:37:0;;;;;22440:2:1;22425:18;41476:37:0;22407:76:1;50011:98:0;50069:7;50096:5;50100:1;50096;:5;:::i;43636:177::-;43746:58;;-1:-1:-1;;;;;12262:32:1;;43746:58:0;;;12244:51:1;12311:18;;;12304:34;;;43719:86:0;;43739:5;;-1:-1:-1;;;43769:23:0;12217:18:1;;43746:58:0;12199:145:1;19889:195:0;19992:12;20024:52;20046:6;20054:4;20060:1;20063:12;20024:21;:52::i;:::-;20017:59;19889:195;-1:-1:-1;;;;19889:195:0:o;20941:530::-;21068:12;21126:5;21101:21;:30;;21093:81;;;;-1:-1:-1;;;21093:81:0;;15680:2:1;21093:81:0;;;15662:21:1;15719:2;15699:18;;;15692:30;15758:34;15738:18;;;15731:62;-1:-1:-1;;;15809:18:1;;;15802:36;15855:19;;21093:81:0;15652:228:1;21093:81:0;17338:20;;21185:60;;;;-1:-1:-1;;;21185:60:0;;18897:2:1;21185:60:0;;;18879:21:1;18936:2;18916:18;;;18909:30;18975:31;18955:18;;;18948:59;19024:18;;21185:60:0;18869:179:1;21185:60:0;21319:12;21333:23;21360:6;-1:-1:-1;;;;;21360:11:0;21380:5;21388:4;21360:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21318:75;;;;21411:52;21429:7;21438:10;21450:12;21411:17;:52::i;:::-;21404:59;20941:530;-1:-1:-1;;;;;;;20941:530:0:o;23481:742::-;23596:12;23625:7;23621:595;;;-1:-1:-1;23656:10:0;23649:17;;23621:595;23770:17;;:21;23766:439;;24033:10;24027:17;24094:15;24081:10;24077:2;24073:19;24066:44;23981:148;24176:12;24169:20;;-1:-1:-1;;;24169:20:0;;;;;;;;:::i;14:134:1:-;82:20;;111:31;82:20;111:31;:::i;:::-;63:85;;;:::o;153:395::-;216:8;226:6;280:3;273:4;265:6;261:17;257:27;247:2;;305:8;295;288:26;247:2;-1:-1:-1;335:20:1;;378:18;367:30;;364:2;;;417:8;407;400:26;364:2;461:4;453:6;449:17;437:29;;521:3;514:4;504:6;501:1;497:14;489:6;485:27;481:38;478:47;475:2;;;538:1;535;528:12;475:2;237:311;;;;;:::o;553:1108::-;614:5;644:6;687:2;675:9;670:3;666:19;662:28;659:2;;;707:5;700;693:20;659:2;744;738:9;774:15;;;;819:18;804:34;;840:22;;;801:62;798:2;;;-1:-1:-1;;;886:35:1;;944:4;941:1;934:15;976:4;893:5;962:19;798:2;1011:10;1007:2;1000:22;1040:6;1031:15;;1083:9;1070:23;1055:38;;1102:33;1127:7;1102:33;:::i;:::-;1159:7;1151:6;1144:23;1200:38;1234:2;1223:9;1219:18;1200:38;:::i;:::-;1195:2;1187:6;1183:15;1176:63;1272:38;1306:2;1295:9;1291:18;1272:38;:::i;:::-;1267:2;1259:6;1255:15;1248:63;1372:2;1361:9;1357:18;1344:32;1339:2;1331:6;1327:15;1320:57;1439:3;1428:9;1424:19;1411:33;1405:3;1397:6;1393:16;1386:59;1507:3;1496:9;1492:19;1479:33;1473:3;1465:6;1461:16;1454:59;1575:3;1564:9;1560:19;1547:33;1541:3;1533:6;1529:16;1522:59;1615:39;1649:3;1638:9;1634:19;1615:39;:::i;:::-;1609:3;1601:6;1597:16;1590:65;;;624:1037;;;;:::o;1666:1002::-;1723:5;1771:4;1759:9;1754:3;1750:19;1746:30;1743:2;;;1793:5;1786;1779:20;1743:2;1830;1824:9;1872:4;1864:6;1860:17;1943:6;1931:10;1928:22;1907:18;1895:10;1892:34;1889:62;1886:2;;;-1:-1:-1;;;1974:35:1;;2032:4;2029:1;2022:15;2064:4;1981:5;2050:19;1886:2;2095;2088:22;2128:6;-1:-1:-1;2128:6:1;2158:23;;2190:33;2158:23;2190:33;:::i;:::-;2247:7;2239:6;2232:23;;2316:2;2305:9;2301:18;2288:32;2283:2;2275:6;2271:15;2264:57;2382:2;2371:9;2367:18;2354:32;2349:2;2341:6;2337:15;2330:57;2448:2;2437:9;2433:18;2420:32;2415:2;2407:6;2403:15;2396:57;2515:3;2504:9;2500:19;2487:33;2481:3;2473:6;2469:16;2462:59;2573:3;2562:9;2558:19;2545:33;2587;2612:7;2587:33;:::i;:::-;2648:3;2636:16;;;;2629:33;1733:935;;-1:-1:-1;;1733:935:1:o;2673:257::-;2732:6;2785:2;2773:9;2764:7;2760:23;2756:32;2753:2;;;2806:6;2798;2791:22;2753:2;2850:9;2837:23;2869:31;2894:5;2869:31;:::i;2935:398::-;3003:6;3011;3064:2;3052:9;3043:7;3039:23;3035:32;3032:2;;;3085:6;3077;3070:22;3032:2;3129:9;3116:23;3148:31;3173:5;3148:31;:::i;:::-;3198:5;-1:-1:-1;3255:2:1;3240:18;;3227:32;3268:33;3227:32;3268:33;:::i;:::-;3320:7;3310:17;;;3022:311;;;;;:::o;3338:466::-;3415:6;3423;3431;3484:2;3472:9;3463:7;3459:23;3455:32;3452:2;;;3505:6;3497;3490:22;3452:2;3549:9;3536:23;3568:31;3593:5;3568:31;:::i;:::-;3618:5;-1:-1:-1;3675:2:1;3660:18;;3647:32;3688:33;3647:32;3688:33;:::i;:::-;3442:362;;3740:7;;-1:-1:-1;;;3794:2:1;3779:18;;;;3766:32;;3442:362::o;3809:325::-;3877:6;3885;3938:2;3926:9;3917:7;3913:23;3909:32;3906:2;;;3959:6;3951;3944:22;3906:2;4003:9;3990:23;4022:31;4047:5;4022:31;:::i;:::-;4072:5;4124:2;4109:18;;;;4096:32;;-1:-1:-1;;;3896:238:1:o;4139:297::-;4206:6;4259:2;4247:9;4238:7;4234:23;4230:32;4227:2;;;4280:6;4272;4265:22;4227:2;4317:9;4311:16;4370:5;4363:13;4356:21;4349:5;4346:32;4336:2;;4397:6;4389;4382:22;4441:276;4526:6;4579:2;4567:9;4558:7;4554:23;4550:32;4547:2;;;4600:6;4592;4585:22;4547:2;4637:9;4631:16;4656:31;4681:5;4656:31;:::i;4722:583::-;4886:6;4894;4902;4955:3;4943:9;4934:7;4930:23;4926:33;4923:2;;;4977:6;4969;4962:22;4923:2;5021:9;5008:23;5040:31;5065:5;5040:31;:::i;:::-;5090:5;-1:-1:-1;5147:2:1;5132:18;;5119:32;5160:33;5119:32;5160:33;:::i;:::-;5212:7;-1:-1:-1;5238:61:1;5291:7;5286:2;5271:18;;5238:61;:::i;:::-;5228:71;;4913:392;;;;;:::o;5310:244::-;5397:6;5450:3;5438:9;5429:7;5425:23;5421:33;5418:2;;;5472:6;5464;5457:22;5418:2;5500:48;5540:7;5529:9;5500:48;:::i;5810:190::-;5869:6;5922:2;5910:9;5901:7;5897:23;5893:32;5890:2;;;5943:6;5935;5928:22;5890:2;-1:-1:-1;5971:23:1;;5880:120;-1:-1:-1;5880:120:1:o;6005:194::-;6075:6;6128:2;6116:9;6107:7;6103:23;6099:32;6096:2;;;6149:6;6141;6134:22;6096:2;-1:-1:-1;6177:16:1;;6086:113;-1:-1:-1;6086:113:1:o;6204:325::-;6272:6;6280;6333:2;6321:9;6312:7;6308:23;6304:32;6301:2;;;6354:6;6346;6339:22;6301:2;6395:9;6382:23;6372:33;;6455:2;6444:9;6440:18;6427:32;6468:31;6493:5;6468:31;:::i;6534:647::-;6666:6;6674;6682;6690;6743:3;6731:9;6722:7;6718:23;6714:33;6711:2;;;6765:6;6757;6750:22;6711:2;6806:9;6793:23;6783:33;;6867:2;6856:9;6852:18;6839:32;6894:18;6886:6;6883:30;6880:2;;;6931:6;6923;6916:22;6880:2;6975:70;7037:7;7028:6;7017:9;7013:22;6975:70;:::i;:::-;7064:8;;-1:-1:-1;6949:96:1;-1:-1:-1;7118:57:1;;-1:-1:-1;7167:7:1;7162:2;7147:18;;7118:57;:::i;:::-;7108:67;;6701:480;;;;;;;:::o;7186:398::-;7289:6;7297;7305;7358:2;7346:9;7337:7;7333:23;7329:32;7326:2;;;7379:6;7371;7364:22;7326:2;7413:9;7407:16;7397:26;;7466:2;7455:9;7451:18;7445:25;7479:31;7504:5;7479:31;:::i;:::-;7529:5;7519:15;;;7574:2;7563:9;7559:18;7553:25;7543:35;;7316:268;;;;;:::o;7589:320::-;7689:6;7697;7750:3;7738:9;7729:7;7725:23;7721:33;7718:2;;;7772:6;7764;7757:22;7718:2;7813:9;7800:23;7790:33;;7842:61;7895:7;7890:2;7879:9;7875:18;7842:61;:::i;:::-;7832:71;;7708:201;;;;;:::o;7914:255::-;7993:6;8001;8054:2;8042:9;8033:7;8029:23;8025:32;8022:2;;;8075:6;8067;8060:22;8022:2;-1:-1:-1;;8103:16:1;;8159:2;8144:18;;;8138:25;8103:16;;8138:25;;-1:-1:-1;8012:157:1:o;8174:715::-;8315:6;8323;8331;8339;8347;8400:3;8388:9;8379:7;8375:23;8371:33;8368:2;;;8422:6;8414;8407:22;8368:2;8463:9;8450:23;8440:33;;8520:2;8509:9;8505:18;8492:32;8482:42;;8575:2;8564:9;8560:18;8547:32;8602:18;8594:6;8591:30;8588:2;;;8639:6;8631;8624:22;8588:2;8683:70;8745:7;8736:6;8725:9;8721:22;8683:70;:::i;:::-;8772:8;;-1:-1:-1;8657:96:1;-1:-1:-1;8826:57:1;;-1:-1:-1;8875:7:1;8870:2;8855:18;;8826:57;:::i;:::-;8816:67;;8358:531;;;;;;;;:::o;9616:524::-;9716:6;9711:3;9704:19;9686:3;9742:4;9771:2;9766:3;9762:12;9755:19;;9797:5;9820:3;9832:283;9846:6;9843:1;9840:13;9832:283;;;9923:6;9910:20;9943:33;9968:7;9943:33;:::i;:::-;-1:-1:-1;;;;;10001:33:1;9989:46;;10055:12;;;;10090:15;;;;10031:1;9861:9;9832:283;;;-1:-1:-1;10131:3:1;;9694:446;-1:-1:-1;;;;;9694:446:1:o;10458:431::-;10576:12;;-1:-1:-1;;;;;10572:21:1;;;10560:34;;10643:4;10632:16;;;10626:23;10610:14;;;10603:47;10699:4;10688:16;;;10682:23;10666:14;;;10659:47;10755:4;10744:16;;;10738:23;10722:14;;;10715:47;10811:4;10800:16;;;10794:23;10778:14;;;10771:47;10540:3;10860:16;;;10854:23;10850:32;10834:14;;10827:56;10512:377::o;10894:274::-;11023:3;11061:6;11055:13;11077:53;11123:6;11118:3;11111:4;11103:6;11099:17;11077:53;:::i;:::-;11146:16;;;;;11031:137;-1:-1:-1;;11031:137:1:o;13473:383::-;13622:2;13611:9;13604:21;13585:4;13654:6;13648:13;13697:6;13692:2;13681:9;13677:18;13670:34;13713:66;13772:6;13767:2;13756:9;13752:18;13747:2;13739:6;13735:15;13713:66;:::i;:::-;13840:2;13819:15;-1:-1:-1;;13815:29:1;13800:45;;;;13847:2;13796:54;;13594:262;-1:-1:-1;;13594:262:1:o;15885:348::-;16087:2;16069:21;;;16126:2;16106:18;;;16099:30;16165:26;16160:2;16145:18;;16138:54;16224:2;16209:18;;16059:174::o;16238:419::-;16496:2;16485:9;16478:21;16459:4;16516:49;16561:2;16550:9;16546:18;10222:1;10210:14;;-1:-1:-1;;;10249:4:1;10240:14;;10233:29;10287:2;10278:12;;10200:96;16516:49;16596:2;16581:18;;16574:34;;;;-1:-1:-1;16639:2:1;16624:18;16617:34;16508:57;16468:189::o;16662:406::-;16864:2;16846:21;;;16903:2;16883:18;;;16876:30;16942:34;16937:2;16922:18;;16915:62;-1:-1:-1;;;17008:2:1;16993:18;;16986:40;17058:3;17043:19;;16836:232::o;19821:419::-;20079:2;20068:9;20061:21;20042:4;20099:49;20144:2;20133:9;20129:18;10378:1;10366:14;;-1:-1:-1;;;10405:4:1;10396:14;;10389:30;10444:2;10435:12;;10356:97;21011:764;21282:13;;-1:-1:-1;;;;;21278:22:1;;;21260:41;;21361:4;21349:17;;;21343:24;21339:33;;21317:20;;;21310:63;21433:4;21421:17;;;21415:24;21411:33;;21389:20;;;21382:63;21501:4;21489:17;;;21483:24;21461:20;;;21454:54;21564:4;21552:17;;;21546:24;21524:20;;;21517:54;21240:3;21615:17;;;21609:24;21587:20;;;21580:54;21690:4;21678:17;;;21672:24;21650:20;;;21643:54;21757:4;21745:17;;;21739:24;21735:33;21713:20;;;21706:63;;;;21209:3;21194:19;;21176:599::o;21780:256::-;21970:3;21955:19;;21983:47;21959:9;22012:6;21983:47;:::i;22488:667::-;22820:4;22849:3;22879:6;22868:9;22861:25;22922:2;22917;22906:9;22902:18;22895:30;22942:73;23011:2;23000:9;22996:18;22988:6;22980;22942:73;:::i;:::-;-1:-1:-1;;;;;23051:32:1;;23046:2;23031:18;;23024:60;22934:81;-1:-1:-1;23093:56:1;;-1:-1:-1;23145:2:1;23130:18;;23122:6;23093:56;:::i;:::-;22829:326;;;;;;;;:::o;23160:773::-;23524:4;23553:3;23583:6;23572:9;23565:25;23626:2;23621;23610:9;23606:18;23599:30;23646:73;23715:2;23704:9;23700:18;23692:6;23684;23646:73;:::i;:::-;-1:-1:-1;;;;;23793:15:1;;;23788:2;23773:18;;23766:43;23638:81;;-1:-1:-1;23738:19:1;-1:-1:-1;23818:56:1;23870:2;23855:18;;23847:6;23818:56;:::i;:::-;23923:2;23915:6;23911:15;23905:3;23894:9;23890:19;23883:44;;23533:400;;;;;;;;;:::o;23938:348::-;24168:6;24157:9;24150:25;24211:2;24206;24195:9;24191:18;24184:30;24131:4;24231:49;24276:2;24265:9;24261:18;10222:1;10210:14;;-1:-1:-1;;;10249:4:1;10240:14;;10233:29;10287:2;10278:12;;10200:96;24291:348;24521:6;24510:9;24503:25;24564:2;24559;24548:9;24544:18;24537:30;24484:4;24584:49;24629:2;24618:9;24614:18;10378:1;10366:14;;-1:-1:-1;;;10405:4:1;10396:14;;10389:30;10444:2;10435:12;;10356:97;24897:739;25257:4;25286:3;25316:6;25305:9;25298:25;25359:6;25354:2;25343:9;25339:18;25332:34;25402:2;25397;25386:9;25382:18;25375:30;25422:73;25491:2;25480:9;25476:18;25468:6;25460;25422:73;:::i;:::-;-1:-1:-1;;;;;25531:32:1;;25526:2;25511:18;;25504:60;25414:81;-1:-1:-1;25573:57:1;;-1:-1:-1;25625:3:1;25610:19;;25602:6;25573:57;:::i;25830:128::-;25870:3;25901:1;25897:6;25894:1;25891:13;25888:2;;;25907:18;;:::i;:::-;-1:-1:-1;25943:9:1;;25878:80::o;25963:217::-;26003:1;26029;26019:2;;-1:-1:-1;;;26054:31:1;;26108:4;26105:1;26098:15;26136:4;26061:1;26126:15;26019:2;-1:-1:-1;26165:9:1;;26009:171::o;26185:168::-;26225:7;26291:1;26287;26283:6;26279:14;26276:1;26273:21;26268:1;26261:9;26254:17;26250:45;26247:2;;;26298:18;;:::i;:::-;-1:-1:-1;26338:9:1;;26237:116::o;26358:125::-;26398:4;26426:1;26423;26420:8;26417:2;;;26431:18;;:::i;:::-;-1:-1:-1;26468:9:1;;26407:76::o;26488:258::-;26560:1;26570:113;26584:6;26581:1;26578:13;26570:113;;;26660:11;;;26654:18;26641:11;;;26634:39;26606:2;26599:10;26570:113;;;26701:6;26698:1;26695:13;26692:2;;;-1:-1:-1;;26736:1:1;26718:16;;26711:27;26541:205::o;26751:380::-;26830:1;26826:12;;;;26873;;;26894:2;;26948:4;26940:6;26936:17;26926:27;;26894:2;27001;26993:6;26990:14;26970:18;26967:38;26964:2;;;27047:10;27042:3;27038:20;27035:1;27028:31;27082:4;27079:1;27072:15;27110:4;27107:1;27100:15;26964:2;;26806:325;;;:::o;27136:127::-;27197:10;27192:3;27188:20;27185:1;27178:31;27228:4;27225:1;27218:15;27252:4;27249:1;27242:15;27268:131;-1:-1:-1;;;;;27343:31:1;;27333:42;;27323:2;;27389:1;27386;27379:12;27323:2;27313:86;:::o

Swarm Source

ipfs://2ed485e1d84beb25f2a55ef8c37642ab245b8850c683b83c4d4f66f65adfa3b1
Loading