{
  "address": "0xfC20BccA96BDE758E9C69151d99cEcfEAE3AB37E",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "Token6",
          "name": "usdc_",
          "type": "address"
        },
        {
          "internalType": "Token18",
          "name": "dsu_",
          "type": "address"
        },
        {
          "internalType": "contract IBatcher",
          "name": "batcher_",
          "type": "address"
        },
        {
          "internalType": "contract ICollateral",
          "name": "collateral_",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [],
      "name": "ForwarderNotContractAddressError",
      "type": "error"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "contract IProduct",
          "name": "product",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "UFixed18",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "WrapAndDeposit",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "DSU",
      "outputs": [
        {
          "internalType": "Token18",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "USDC",
      "outputs": [
        {
          "internalType": "Token6",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "batcher",
      "outputs": [
        {
          "internalType": "contract IBatcher",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "collateral",
      "outputs": [
        {
          "internalType": "contract ICollateral",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "contract IProduct",
          "name": "product",
          "type": "address"
        },
        {
          "internalType": "UFixed18",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "wrapAndDeposit",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0x4f810be2b2604db84b6762daad998e7b71210cf6ad79b3a843a0399b109fb523",
  "receipt": {
    "to": null,
    "from": "0x66a7fDB96C583c59597de16d8b2B989231415339",
    "contractAddress": "0xfC20BccA96BDE758E9C69151d99cEcfEAE3AB37E",
    "transactionIndex": 96,
    "gasUsed": "803183",
    "logsBloom": "0x00000000002000000000001000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000008000000800400000000000000000000000000000000010000000000000040000000010000000000000000000000000000000020000000400020000000000000000000000000000000000000010000000000000000000000020000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000020000000000000",
    "blockHash": "0x3d14e8ab1411cc12e52e3ad839497df01652a7c33802aaf4ffeda61da83e21da",
    "transactionHash": "0x4f810be2b2604db84b6762daad998e7b71210cf6ad79b3a843a0399b109fb523",
    "logs": [
      {
        "transactionIndex": 96,
        "blockNumber": 15792797,
        "transactionHash": "0x4f810be2b2604db84b6762daad998e7b71210cf6ad79b3a843a0399b109fb523",
        "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "topics": [
          "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
          "0x000000000000000000000000fc20bcca96bde758e9c69151d99cecfeae3ab37e",
          "0x0000000000000000000000000b663ceacef01f2f88eb7451c70aa069f19db997"
        ],
        "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
        "logIndex": 253,
        "blockHash": "0x3d14e8ab1411cc12e52e3ad839497df01652a7c33802aaf4ffeda61da83e21da"
      },
      {
        "transactionIndex": 96,
        "blockNumber": 15792797,
        "transactionHash": "0x4f810be2b2604db84b6762daad998e7b71210cf6ad79b3a843a0399b109fb523",
        "address": "0x605D26FBd5be761089281d5cec2Ce86eeA667109",
        "topics": [
          "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
          "0x000000000000000000000000fc20bcca96bde758e9c69151d99cecfeae3ab37e",
          "0x0000000000000000000000002d264ebdb6632a06a1726193d4d37fef1e5dbdcd"
        ],
        "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
        "logIndex": 254,
        "blockHash": "0x3d14e8ab1411cc12e52e3ad839497df01652a7c33802aaf4ffeda61da83e21da"
      }
    ],
    "blockNumber": 15792797,
    "cumulativeGasUsed": "12334717",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "0x605D26FBd5be761089281d5cec2Ce86eeA667109",
    "0x0B663CeaCEF01f2f88EB7451C70Aa069f19dB997",
    "0x2d264EBDb6632A06A1726193D4d37FeF1E5dbDcd"
  ],
  "numDeployments": 1,
  "solcInputHash": "43f6cf19a2aa111184cd0094b097bc92",
  "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"Token6\",\"name\":\"usdc_\",\"type\":\"address\"},{\"internalType\":\"Token18\",\"name\":\"dsu_\",\"type\":\"address\"},{\"internalType\":\"contract IBatcher\",\"name\":\"batcher_\",\"type\":\"address\"},{\"internalType\":\"contract ICollateral\",\"name\":\"collateral_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ForwarderNotContractAddressError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WrapAndDeposit\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DSU\",\"outputs\":[{\"internalType\":\"Token18\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"Token6\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batcher\",\"outputs\":[{\"internalType\":\"contract IBatcher\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"collateral\",\"outputs\":[{\"internalType\":\"contract ICollateral\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"wrapAndDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"batcher_\":\"The USDC-to-DSU batcher contract address\",\"collateral_\":\"The perennial collateral contract address\",\"dsu_\":\"The DSU token contract address\",\"usdc_\":\"The USDC token contract address\"}},\"wrapAndDeposit(address,address,uint256)\":{\"params\":{\"account\":\"Account to deposit the collateral for\",\"amount\":\"18 decimals-normalized stablecoin (USDC, DSU) value of collateral to deposit\",\"product\":\"Product to credit the collateral to\"}}},\"stateVariables\":{\"batcher\":{\"details\":\"Contract that wraps USDC to DSU\"},\"collateral\":{\"details\":\"Contract managing state for collateral accounts in the protocol\"}},\"title\":\"Forwarder\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Initializes the contract state\"},\"wrapAndDeposit(address,address,uint256)\":{\"notice\":\"Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU, and deposits it as collateral to `account`'s `product` account\"}},\"notice\":\"Facilitates collateral deposits to the protocol where the amount is supplied         in USDC then wrapped as DSU before being deposited.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/forwarder/Forwarder.sol\":\"Forwarder\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\":{\"content\":\"//SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\n\\ninterface IBatcher {\\n    event Wrap(address indexed to, UFixed18 amount);\\n    event Unwrap(address indexed to, UFixed18 amount);\\n    event Rebalance(UFixed18 newMinted, UFixed18 newRedeemed);\\n    event Close(UFixed18 amount);\\n\\n    error BatcherNotImplementedError();\\n    error BatcherBalanceMismatchError(UFixed18 oldBalance, UFixed18 newBalance);\\n\\n    function totalBalance() external view returns (UFixed18);\\n    function wrap(UFixed18 amount, address to) external;\\n    function unwrap(UFixed18 amount, address to) external;\\n    function rebalance() external;\\n}\\n\",\"keccak256\":\"0x5d49c13991d92df22f77377b4ae98149bdfb588e04a084e00feec70569499c8b\",\"license\":\"Apache-2.0\"},\"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\n\\ninterface IOracleProvider {\\n    /// @dev A singular oracle version with its corresponding data\\n    struct OracleVersion {\\n        /// @dev The iterative version\\n        uint256 version;\\n\\n        /// @dev the timestamp of the oracle update\\n        uint256 timestamp;\\n\\n        /// @dev The oracle price of the corresponding version\\n        Fixed18 price;\\n    }\\n\\n    function sync() external returns (OracleVersion memory);\\n    function currentVersion() external view returns (OracleVersion memory);\\n    function atVersion(uint256 oracleVersion) external view returns (OracleVersion memory);\\n}\\n\",\"keccak256\":\"0xde0f20d468ba8b91addfc356e13f2c74a4dc8abe68be323942217c723775d9c1\",\"license\":\"Apache-2.0\"},\"@equilibria/root/curve/CurveMath.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"../number/types/UFixed18.sol\\\";\\nimport \\\"../number/types/Fixed18.sol\\\";\\n\\n/**\\n * @title CurveMath\\n * @notice Library for managing math operations for utilization curves.\\n */\\nlibrary CurveMath {\\n    error CurveMathOutOfBoundsError();\\n\\n    /**\\n     * @notice Computes a linear interpolation between two points\\n     * @param startX First point's x-coordinate\\n     * @param startY First point's y-coordinate\\n     * @param endX Second point's x-coordinate\\n     * @param endY Second point's y-coordinate\\n     * @param targetX x-coordinate to interpolate\\n     * @return y-coordinate for `targetX` along the line from (`startX`, `startY`) -> (`endX`, `endY`)\\n     */\\n    function linearInterpolation(\\n        UFixed18 startX,\\n        Fixed18 startY,\\n        UFixed18 endX,\\n        Fixed18 endY,\\n        UFixed18 targetX\\n    ) internal pure returns (Fixed18) {\\n        if (targetX.lt(startX) || targetX.gt(endX)) revert CurveMathOutOfBoundsError();\\n\\n        UFixed18 xRange = endX.sub(startX);\\n        Fixed18 yRange = endY.sub(startY);\\n        UFixed18 xRatio = targetX.sub(startX).div(xRange);\\n        return yRange.mul(Fixed18Lib.from(xRatio)).add(startY);\\n    }\\n}\\n\",\"keccak256\":\"0x60d159f9ddf0dbe81124ecad58bba734b4cf82877637ff8d9d7f3e92f2da4ded\",\"license\":\"Apache-2.0\"},\"@equilibria/root/curve/types/JumpRateUtilizationCurve.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"../CurveMath.sol\\\";\\nimport \\\"../../number/types/PackedUFixed18.sol\\\";\\nimport \\\"../../number/types/PackedFixed18.sol\\\";\\n\\n/// @dev JumpRateUtilizationCurve type\\nstruct JumpRateUtilizationCurve {\\n    PackedFixed18 minRate;\\n    PackedFixed18 maxRate;\\n    PackedFixed18 targetRate;\\n    PackedUFixed18 targetUtilization;\\n}\\nusing JumpRateUtilizationCurveLib for JumpRateUtilizationCurve global;\\ntype JumpRateUtilizationCurveStorage is bytes32;\\nusing JumpRateUtilizationCurveStorageLib for JumpRateUtilizationCurveStorage global;\\n\\n/**\\n * @title JumpRateUtilizationCurveLib\\n * @notice Library for the Jump Rate utilization curve type\\n */\\nlibrary JumpRateUtilizationCurveLib {\\n    /**\\n     * @notice Computes the corresponding rate for a utilization ratio\\n     * @param utilization The utilization ratio\\n     * @return The corresponding rate\\n     */\\n    function compute(JumpRateUtilizationCurve memory self, UFixed18 utilization) internal pure returns (Fixed18) {\\n        UFixed18 targetUtilization = self.targetUtilization.unpack();\\n        if (utilization.lt(targetUtilization)) {\\n            return CurveMath.linearInterpolation(\\n                UFixed18Lib.ZERO,\\n                self.minRate.unpack(),\\n                targetUtilization,\\n                self.targetRate.unpack(),\\n                utilization\\n            );\\n        }\\n        if (utilization.lt(UFixed18Lib.ONE)) {\\n            return CurveMath.linearInterpolation(\\n                targetUtilization,\\n                self.targetRate.unpack(),\\n                UFixed18Lib.ONE,\\n                self.maxRate.unpack(),\\n                utilization\\n            );\\n        }\\n        return self.maxRate.unpack();\\n    }\\n}\\n\\nlibrary JumpRateUtilizationCurveStorageLib {\\n    function read(JumpRateUtilizationCurveStorage self) internal view returns (JumpRateUtilizationCurve memory) {\\n        return _storagePointer(self);\\n    }\\n\\n    function store(JumpRateUtilizationCurveStorage self, JumpRateUtilizationCurve memory value) internal {\\n        JumpRateUtilizationCurve storage storagePointer = _storagePointer(self);\\n\\n        storagePointer.minRate = value.minRate;\\n        storagePointer.maxRate = value.maxRate;\\n        storagePointer.targetRate = value.targetRate;\\n        storagePointer.targetUtilization = value.targetUtilization;\\n    }\\n\\n    function _storagePointer(JumpRateUtilizationCurveStorage self)\\n    private pure returns (JumpRateUtilizationCurve storage pointer) {\\n        assembly { pointer.slot := self }\\n    }\\n}\",\"keccak256\":\"0xae202813874bc306d51b3dab8194c86f6483bb20bf1f673ddaee16aa8de567ff\",\"license\":\"Apache-2.0\"},\"@equilibria/root/number/types/Fixed18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SignedMath.sol\\\";\\nimport \\\"./UFixed18.sol\\\";\\nimport \\\"./PackedFixed18.sol\\\";\\n\\n/// @dev Fixed18 type\\ntype Fixed18 is int256;\\nusing Fixed18Lib for Fixed18 global;\\ntype Fixed18Storage is bytes32;\\nusing Fixed18StorageLib for Fixed18Storage global;\\n\\n/**\\n * @title Fixed18Lib\\n * @notice Library for the signed fixed-decimal type.\\n */\\nlibrary Fixed18Lib {\\n    error Fixed18OverflowError(uint256 value);\\n    error Fixed18PackingOverflowError(int256 value);\\n    error Fixed18PackingUnderflowError(int256 value);\\n\\n    int256 private constant BASE = 1e18;\\n    Fixed18 public constant ZERO = Fixed18.wrap(0);\\n    Fixed18 public constant ONE = Fixed18.wrap(BASE);\\n    Fixed18 public constant NEG_ONE = Fixed18.wrap(-1 * BASE);\\n    Fixed18 public constant MAX = Fixed18.wrap(type(int256).max);\\n    Fixed18 public constant MIN = Fixed18.wrap(type(int256).min);\\n\\n    /**\\n     * @notice Creates a signed fixed-decimal from an unsigned fixed-decimal\\n     * @param a Unsigned fixed-decimal\\n     * @return New signed fixed-decimal\\n     */\\n    function from(UFixed18 a) internal pure returns (Fixed18) {\\n        uint256 value = UFixed18.unwrap(a);\\n        if (value > uint256(type(int256).max)) revert Fixed18OverflowError(value);\\n        return Fixed18.wrap(int256(value));\\n    }\\n\\n    /**\\n     * @notice Creates a signed fixed-decimal from a sign and an unsigned fixed-decimal\\n     * @param s Sign\\n     * @param m Unsigned fixed-decimal magnitude\\n     * @return New signed fixed-decimal\\n     */\\n    function from(int256 s, UFixed18 m) internal pure returns (Fixed18) {\\n        if (s > 0) return from(m);\\n        if (s < 0) return Fixed18.wrap(-1 * Fixed18.unwrap(from(m)));\\n        return ZERO;\\n    }\\n\\n    /**\\n     * @notice Creates a signed fixed-decimal from a signed integer\\n     * @param a Signed number\\n     * @return New signed fixed-decimal\\n     */\\n    function from(int256 a) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(a * BASE);\\n    }\\n\\n    /**\\n     * @notice Creates a packed signed fixed-decimal from an signed fixed-decimal\\n     * @param a signed fixed-decimal\\n     * @return New packed signed fixed-decimal\\n     */\\n    function pack(Fixed18 a) internal pure returns (PackedFixed18) {\\n        int256 value = Fixed18.unwrap(a);\\n        if (value > type(int128).max) revert Fixed18PackingOverflowError(value);\\n        if (value < type(int128).min) revert Fixed18PackingUnderflowError(value);\\n        return PackedFixed18.wrap(int128(value));\\n    }\\n\\n    /**\\n     * @notice Returns whether the signed fixed-decimal is equal to zero.\\n     * @param a Signed fixed-decimal\\n     * @return Whether the signed fixed-decimal is zero.\\n     */\\n    function isZero(Fixed18 a) internal pure returns (bool) {\\n        return Fixed18.unwrap(a) == 0;\\n    }\\n\\n    /**\\n     * @notice Adds two signed fixed-decimals `a` and `b` together\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Resulting summed signed fixed-decimal\\n     */\\n    function add(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(Fixed18.unwrap(a) + Fixed18.unwrap(b));\\n    }\\n\\n    /**\\n     * @notice Subtracts signed fixed-decimal `b` from `a`\\n     * @param a Signed fixed-decimal to subtract from\\n     * @param b Signed fixed-decimal to subtract\\n     * @return Resulting subtracted signed fixed-decimal\\n     */\\n    function sub(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(Fixed18.unwrap(a) - Fixed18.unwrap(b));\\n    }\\n\\n    /**\\n     * @notice Multiplies two signed fixed-decimals `a` and `b` together\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Resulting multiplied signed fixed-decimal\\n     */\\n    function mul(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(Fixed18.unwrap(a) * Fixed18.unwrap(b) / BASE);\\n    }\\n\\n    /**\\n     * @notice Divides signed fixed-decimal `a` by `b`\\n     * @param a Signed fixed-decimal to divide\\n     * @param b Signed fixed-decimal to divide by\\n     * @return Resulting divided signed fixed-decimal\\n     */\\n    function div(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(Fixed18.unwrap(a) * BASE / Fixed18.unwrap(b));\\n    }\\n\\n    /**\\n     * @notice Divides unsigned fixed-decimal `a` by `b`\\n     * @dev Does not revert on divide-by-0, instead returns `ONE` for `0/0`, `MAX` for `n/0`, and `MIN` for `-n/0`.\\n     * @param a Unsigned fixed-decimal to divide\\n     * @param b Unsigned fixed-decimal to divide by\\n     * @return Resulting divided unsigned fixed-decimal\\n     */\\n    function unsafeDiv(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\\n        if (isZero(b)) {\\n            if (gt(a, ZERO)) return MAX;\\n            if (lt(a, ZERO)) return MIN;\\n            return ONE;\\n        } else {\\n            return div(a, b);\\n        }\\n    }\\n\\n    /**\\n     * @notice Computes a * b / c without loss of precision due to BASE conversion\\n     * @param a First signed fixed-decimal\\n     * @param b Signed number to multiply by\\n     * @param c Signed number to divide by\\n     * @return Resulting computation\\n     */\\n    function muldiv(Fixed18 a, int256 b, int256 c) internal pure returns (Fixed18) {\\n        return muldiv(a, Fixed18.wrap(b), Fixed18.wrap(c));\\n    }\\n\\n    /**\\n     * @notice Computes a * b / c without loss of precision due to BASE conversion\\n     * @param a First signed fixed-decimal\\n     * @param b Signed fixed-decimal to multiply by\\n     * @param c Signed fixed-decimal to divide by\\n     * @return Resulting computation\\n     */\\n    function muldiv(Fixed18 a, Fixed18 b, Fixed18 c) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(Fixed18.unwrap(a) * Fixed18.unwrap(b) / Fixed18.unwrap(c));\\n    }\\n\\n    /**\\n     * @notice Returns whether signed fixed-decimal `a` is equal to `b`\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Whether `a` is equal to `b`\\n     */\\n    function eq(Fixed18 a, Fixed18 b) internal pure returns (bool) {\\n        return compare(a, b) == 1;\\n    }\\n\\n    /**\\n     * @notice Returns whether signed fixed-decimal `a` is greater than `b`\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Whether `a` is greater than `b`\\n     */\\n    function gt(Fixed18 a, Fixed18 b) internal pure returns (bool) {\\n        return compare(a, b) == 2;\\n    }\\n\\n    /**\\n     * @notice Returns whether signed fixed-decimal `a` is less than `b`\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Whether `a` is less than `b`\\n     */\\n    function lt(Fixed18 a, Fixed18 b) internal pure returns (bool) {\\n        return compare(a, b) == 0;\\n    }\\n\\n    /**\\n     * @notice Returns whether signed fixed-decimal `a` is greater than or equal to `b`\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Whether `a` is greater than or equal to `b`\\n     */\\n    function gte(Fixed18 a, Fixed18 b) internal pure returns (bool) {\\n        return gt(a, b) || eq(a, b);\\n    }\\n\\n    /**\\n     * @notice Returns whether signed fixed-decimal `a` is less than or equal to `b`\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Whether `a` is less than or equal to `b`\\n     */\\n    function lte(Fixed18 a, Fixed18 b) internal pure returns (bool) {\\n        return lt(a, b) || eq(a, b);\\n    }\\n\\n    /**\\n     * @notice Compares the signed fixed-decimals `a` and `b`\\n     * @dev Returns: 2 for greater than\\n     *               1 for equal to\\n     *               0 for less than\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Compare result of `a` and `b`\\n     */\\n    function compare(Fixed18 a, Fixed18 b) internal pure returns (uint256) {\\n        (int256 au, int256 bu) = (Fixed18.unwrap(a), Fixed18.unwrap(b));\\n        if (au > bu) return 2;\\n        if (au < bu) return 0;\\n        return 1;\\n    }\\n\\n    /**\\n     * @notice Returns a signed fixed-decimal representing the ratio of `a` over `b`\\n     * @param a First signed number\\n     * @param b Second signed number\\n     * @return Ratio of `a` over `b`\\n     */\\n    function ratio(int256 a, int256 b) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(a * BASE / b);\\n    }\\n\\n    /**\\n     * @notice Returns the minimum of signed fixed-decimals `a` and `b`\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Minimum of `a` and `b`\\n     */\\n    function min(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(SignedMath.min(Fixed18.unwrap(a), Fixed18.unwrap(b)));\\n    }\\n\\n    /**\\n     * @notice Returns the maximum of signed fixed-decimals `a` and `b`\\n     * @param a First signed fixed-decimal\\n     * @param b Second signed fixed-decimal\\n     * @return Maximum of `a` and `b`\\n     */\\n    function max(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(SignedMath.max(Fixed18.unwrap(a), Fixed18.unwrap(b)));\\n    }\\n\\n    /**\\n     * @notice Converts the signed fixed-decimal into an integer, truncating any decimal portion\\n     * @param a Signed fixed-decimal\\n     * @return Truncated signed number\\n     */\\n    function truncate(Fixed18 a) internal pure returns (int256) {\\n        return Fixed18.unwrap(a) / BASE;\\n    }\\n\\n    /**\\n     * @notice Returns the sign of the signed fixed-decimal\\n     * @dev Returns: -1 for negative\\n     *                0 for zero\\n     *                1 for positive\\n     * @param a Signed fixed-decimal\\n     * @return Sign of the signed fixed-decimal\\n     */\\n    function sign(Fixed18 a) internal pure returns (int256) {\\n        if (Fixed18.unwrap(a) > 0) return 1;\\n        if (Fixed18.unwrap(a) < 0) return -1;\\n        return 0;\\n    }\\n\\n    /**\\n     * @notice Returns the absolute value of the signed fixed-decimal\\n     * @param a Signed fixed-decimal\\n     * @return Absolute value of the signed fixed-decimal\\n     */\\n    function abs(Fixed18 a) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(SignedMath.abs(Fixed18.unwrap(a)));\\n    }\\n}\\n\\nlibrary Fixed18StorageLib {\\n    function read(Fixed18Storage self) internal view returns (Fixed18 value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    function store(Fixed18Storage self, Fixed18 value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x613587461ef3437ef33229cdda7d34ea746278721baf06e20b2e43977f43174d\",\"license\":\"Apache-2.0\"},\"@equilibria/root/number/types/PackedFixed18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"./Fixed18.sol\\\";\\n\\n/// @dev PackedFixed18 type\\ntype PackedFixed18 is int128;\\nusing PackedFixed18Lib for PackedFixed18 global;\\n\\n/**\\n * @title PackedFixed18Lib\\n * @dev A packed version of the Fixed18 which takes up half the storage space (two PackedFixed18 can be packed\\n *      into a single slot). Only valid within the range -1.7014118e+20 <= x <= 1.7014118e+20.\\n * @notice Library for the packed signed fixed-decimal type.\\n */\\nlibrary PackedFixed18Lib {\\n    PackedFixed18 public constant MAX = PackedFixed18.wrap(type(int128).max);\\n    PackedFixed18 public constant MIN = PackedFixed18.wrap(type(int128).min);\\n\\n    /**\\n     * @notice Creates an unpacked signed fixed-decimal from a packed signed fixed-decimal\\n     * @param self packed signed fixed-decimal\\n     * @return New unpacked signed fixed-decimal\\n     */\\n    function unpack(PackedFixed18 self) internal pure returns (Fixed18) {\\n        return Fixed18.wrap(int256(PackedFixed18.unwrap(self)));\\n    }\\n}\\n\",\"keccak256\":\"0xb52960cc8e3132e45d342bbbb1c6a96219022cd8557997933bd8250170268b64\",\"license\":\"Apache-2.0\"},\"@equilibria/root/number/types/PackedUFixed18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"./UFixed18.sol\\\";\\n\\n/// @dev PackedUFixed18 type\\ntype PackedUFixed18 is uint128;\\nusing PackedUFixed18Lib for PackedUFixed18 global;\\n\\n/**\\n * @title PackedUFixed18Lib\\n * @dev A packed version of the UFixed18 which takes up half the storage space (two PackedUFixed18 can be packed\\n *      into a single slot). Only valid within the range 0 <= x <= 3.4028237e+20.\\n * @notice Library for the packed unsigned fixed-decimal type.\\n */\\nlibrary PackedUFixed18Lib {\\n    PackedUFixed18 public constant MAX = PackedUFixed18.wrap(type(uint128).max);\\n\\n    /**\\n     * @notice Creates an unpacked unsigned fixed-decimal from a packed unsigned fixed-decimal\\n     * @param self packed unsigned fixed-decimal\\n     * @return New unpacked unsigned fixed-decimal\\n     */\\n    function unpack(PackedUFixed18 self) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(uint256(PackedUFixed18.unwrap(self)));\\n    }\\n}\\n\",\"keccak256\":\"0xb5c5cd32d6530b2fe75228b6be32ebcb7762f6d7988b85a6b85a289ce8256d51\",\"license\":\"Apache-2.0\"},\"@equilibria/root/number/types/UFixed18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"./Fixed18.sol\\\";\\nimport \\\"./PackedUFixed18.sol\\\";\\n\\n/// @dev UFixed18 type\\ntype UFixed18 is uint256;\\nusing UFixed18Lib for UFixed18 global;\\ntype UFixed18Storage is bytes32;\\nusing UFixed18StorageLib for UFixed18Storage global;\\n\\n/**\\n * @title UFixed18Lib\\n * @notice Library for the unsigned fixed-decimal type.\\n */\\nlibrary UFixed18Lib {\\n    error UFixed18UnderflowError(int256 value);\\n    error UFixed18PackingOverflowError(uint256 value);\\n\\n    uint256 private constant BASE = 1e18;\\n    UFixed18 public constant ZERO = UFixed18.wrap(0);\\n    UFixed18 public constant ONE = UFixed18.wrap(BASE);\\n    UFixed18 public constant MAX = UFixed18.wrap(type(uint256).max);\\n\\n    /**\\n     * @notice Creates a unsigned fixed-decimal from a signed fixed-decimal\\n     * @param a Signed fixed-decimal\\n     * @return New unsigned fixed-decimal\\n     */\\n    function from(Fixed18 a) internal pure returns (UFixed18) {\\n        int256 value = Fixed18.unwrap(a);\\n        if (value < 0) revert UFixed18UnderflowError(value);\\n        return UFixed18.wrap(uint256(value));\\n    }\\n\\n    /**\\n     * @notice Creates a unsigned fixed-decimal from a unsigned integer\\n     * @param a Unsigned number\\n     * @return New unsigned fixed-decimal\\n     */\\n    function from(uint256 a) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(a * BASE);\\n    }\\n\\n    /**\\n     * @notice Creates a packed unsigned fixed-decimal from an unsigned fixed-decimal\\n     * @param a unsigned fixed-decimal\\n     * @return New packed unsigned fixed-decimal\\n     */\\n    function pack(UFixed18 a) internal pure returns (PackedUFixed18) {\\n        uint256 value = UFixed18.unwrap(a);\\n        if (value > type(uint128).max) revert UFixed18PackingOverflowError(value);\\n        return PackedUFixed18.wrap(uint128(value));\\n    }\\n\\n    /**\\n     * @notice Returns whether the unsigned fixed-decimal is equal to zero.\\n     * @param a Unsigned fixed-decimal\\n     * @return Whether the unsigned fixed-decimal is zero.\\n     */\\n    function isZero(UFixed18 a) internal pure returns (bool) {\\n        return UFixed18.unwrap(a) == 0;\\n    }\\n\\n    /**\\n     * @notice Adds two unsigned fixed-decimals `a` and `b` together\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Resulting summed unsigned fixed-decimal\\n     */\\n    function add(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(UFixed18.unwrap(a) + UFixed18.unwrap(b));\\n    }\\n\\n    /**\\n     * @notice Subtracts unsigned fixed-decimal `b` from `a`\\n     * @param a Unsigned fixed-decimal to subtract from\\n     * @param b Unsigned fixed-decimal to subtract\\n     * @return Resulting subtracted unsigned fixed-decimal\\n     */\\n    function sub(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(UFixed18.unwrap(a) - UFixed18.unwrap(b));\\n    }\\n\\n    /**\\n     * @notice Multiplies two unsigned fixed-decimals `a` and `b` together\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Resulting multiplied unsigned fixed-decimal\\n     */\\n    function mul(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(UFixed18.unwrap(a) * UFixed18.unwrap(b) / BASE);\\n    }\\n\\n    /**\\n     * @notice Divides unsigned fixed-decimal `a` by `b`\\n     * @param a Unsigned fixed-decimal to divide\\n     * @param b Unsigned fixed-decimal to divide by\\n     * @return Resulting divided unsigned fixed-decimal\\n     */\\n    function div(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(UFixed18.unwrap(a) * BASE / UFixed18.unwrap(b));\\n    }\\n\\n    /**\\n     * @notice Divides unsigned fixed-decimal `a` by `b`\\n     * @dev Does not revert on divide-by-0, instead returns `ONE` for `0/0` and `MAX` for `n/0`.\\n     * @param a Unsigned fixed-decimal to divide\\n     * @param b Unsigned fixed-decimal to divide by\\n     * @return Resulting divided unsigned fixed-decimal\\n     */\\n    function unsafeDiv(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n        if (isZero(b)) {\\n            return isZero(a) ? ONE : MAX;\\n        } else {\\n            return div(a, b);\\n        }\\n    }\\n\\n    /**\\n     * @notice Computes a * b / c without loss of precision due to BASE conversion\\n     * @param a First unsigned fixed-decimal\\n     * @param b Unsigned number to multiply by\\n     * @param c Unsigned number to divide by\\n     * @return Resulting computation\\n     */\\n    function muldiv(UFixed18 a, uint256 b, uint256 c) internal pure returns (UFixed18) {\\n        return muldiv(a, UFixed18.wrap(b), UFixed18.wrap(c));\\n    }\\n\\n    /**\\n     * @notice Computes a * b / c without loss of precision due to BASE conversion\\n     * @param a First unsigned fixed-decimal\\n     * @param b Unsigned fixed-decimal to multiply by\\n     * @param c Unsigned fixed-decimal to divide by\\n     * @return Resulting computation\\n     */\\n    function muldiv(UFixed18 a, UFixed18 b, UFixed18 c) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(UFixed18.unwrap(a) * UFixed18.unwrap(b) / UFixed18.unwrap(c));\\n    }\\n\\n    /**\\n     * @notice Returns whether unsigned fixed-decimal `a` is equal to `b`\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Whether `a` is equal to `b`\\n     */\\n    function eq(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n        return compare(a, b) == 1;\\n    }\\n\\n    /**\\n     * @notice Returns whether unsigned fixed-decimal `a` is greater than `b`\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Whether `a` is greater than `b`\\n     */\\n    function gt(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n        return compare(a, b) == 2;\\n    }\\n\\n    /**\\n     * @notice Returns whether unsigned fixed-decimal `a` is less than `b`\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Whether `a` is less than `b`\\n     */\\n    function lt(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n        return compare(a, b) == 0;\\n    }\\n\\n    /**\\n     * @notice Returns whether unsigned fixed-decimal `a` is greater than or equal to `b`\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Whether `a` is greater than or equal to `b`\\n     */\\n    function gte(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n        return gt(a, b) || eq(a, b);\\n    }\\n\\n    /**\\n     * @notice Returns whether unsigned fixed-decimal `a` is less than or equal to `b`\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Whether `a` is less than or equal to `b`\\n     */\\n    function lte(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n        return lt(a, b) || eq(a, b);\\n    }\\n\\n    /**\\n     * @notice Compares the unsigned fixed-decimals `a` and `b`\\n     * @dev Returns: 2 for greater than\\n     *               1 for equal to\\n     *               0 for less than\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Compare result of `a` and `b`\\n     */\\n    function compare(UFixed18 a, UFixed18 b) internal pure returns (uint256) {\\n        (uint256 au, uint256 bu) = (UFixed18.unwrap(a), UFixed18.unwrap(b));\\n        if (au > bu) return 2;\\n        if (au < bu) return 0;\\n        return 1;\\n    }\\n\\n    /**\\n     * @notice Returns a unsigned fixed-decimal representing the ratio of `a` over `b`\\n     * @param a First unsigned number\\n     * @param b Second unsigned number\\n     * @return Ratio of `a` over `b`\\n     */\\n    function ratio(uint256 a, uint256 b) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(a * BASE / b);\\n    }\\n\\n    /**\\n     * @notice Returns the minimum of unsigned fixed-decimals `a` and `b`\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Minimum of `a` and `b`\\n     */\\n    function min(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(Math.min(UFixed18.unwrap(a), UFixed18.unwrap(b)));\\n    }\\n\\n    /**\\n     * @notice Returns the maximum of unsigned fixed-decimals `a` and `b`\\n     * @param a First unsigned fixed-decimal\\n     * @param b Second unsigned fixed-decimal\\n     * @return Maximum of `a` and `b`\\n     */\\n    function max(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(Math.max(UFixed18.unwrap(a), UFixed18.unwrap(b)));\\n    }\\n\\n    /**\\n     * @notice Converts the unsigned fixed-decimal into an integer, truncating any decimal portion\\n     * @param a Unsigned fixed-decimal\\n     * @return Truncated unsigned number\\n     */\\n    function truncate(UFixed18 a) internal pure returns (uint256) {\\n        return UFixed18.unwrap(a) / BASE;\\n    }\\n}\\n\\nlibrary UFixed18StorageLib {\\n    function read(UFixed18Storage self) internal view returns (UFixed18 value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    function store(UFixed18Storage self, UFixed18 value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x8ebef1e6c717f565b9ed545a876b5692b4007e6485c99f39d363f7405e591792\",\"license\":\"Apache-2.0\"},\"@equilibria/root/token/types/Token18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../../number/types/UFixed18.sol\\\";\\n\\n/// @dev Token18\\ntype Token18 is address;\\nusing Token18Lib for Token18 global;\\ntype Token18Storage is bytes32;\\nusing Token18StorageLib for Token18Storage global;\\n\\n/**\\n * @title Token18Lib\\n * @notice Library to manage 18-decimal ERC20s that is compliant with the fixed-decimal types.\\n * @dev Maintains significant gas savings over other Token implementations since no conversion take place\\n */\\nlibrary Token18Lib {\\n    using SafeERC20 for IERC20;\\n\\n    Token18 public constant ZERO = Token18.wrap(address(0));\\n\\n    /**\\n     * @notice Returns whether a token is the zero address\\n     * @param self Token to check for\\n     * @return Whether the token is the zero address\\n     */\\n    function isZero(Token18 self) internal pure returns (bool) {\\n        return Token18.unwrap(self) == Token18.unwrap(ZERO);\\n    }\\n\\n    /**\\n     * @notice Returns whether the two tokens are equal\\n     * @param a First token to compare\\n     * @param b Second token to compare\\n     * @return Whether the two tokens are equal\\n     */\\n    function eq(Token18 a, Token18 b) internal pure returns (bool) {\\n        return Token18.unwrap(a) ==  Token18.unwrap(b);\\n    }\\n\\n    /**\\n     * @notice Approves `grantee` to spend infinite tokens from the caller\\n     * @param self Token to transfer\\n     * @param grantee Address to allow spending\\n     */\\n    function approve(Token18 self, address grantee) internal {\\n        IERC20(Token18.unwrap(self)).safeApprove(grantee, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice Approves `grantee` to spend `amount` tokens from the caller\\n     * @dev There are important race conditions to be aware of when using this function\\n            with values other than 0. This will revert if moving from non-zero to non-zero amounts\\n            See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a55b7d13722e7ce850b626da2313f3e66ca1d101/contracts/token/ERC20/IERC20.sol#L57\\n     * @param self Token to transfer\\n     * @param grantee Address to allow spending\\n     * @param amount Amount of tokens to approve to spend\\n     */\\n    function approve(Token18 self, address grantee, UFixed18 amount) internal {\\n        IERC20(Token18.unwrap(self)).safeApprove(grantee, UFixed18.unwrap(amount));\\n    }\\n\\n    /**\\n     * @notice Transfers all held tokens from the caller to the `recipient`\\n     * @param self Token to transfer\\n     * @param recipient Address to receive the tokens\\n     */\\n    function push(Token18 self, address recipient) internal {\\n        push(self, recipient, balanceOf(self, address(this)));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the caller to the `recipient`\\n     * @param self Token to transfer\\n     * @param recipient Address to transfer tokens to\\n     * @param amount Amount of tokens to transfer\\n     */\\n    function push(Token18 self, address recipient, UFixed18 amount) internal {\\n        IERC20(Token18.unwrap(self)).safeTransfer(recipient, UFixed18.unwrap(amount));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the `benefactor` to the caller\\n     * @dev Reverts if trying to pull Ether\\n     * @param self Token to transfer\\n     * @param benefactor Address to transfer tokens from\\n     * @param amount Amount of tokens to transfer\\n     */\\n    function pull(Token18 self, address benefactor, UFixed18 amount) internal {\\n        IERC20(Token18.unwrap(self)).safeTransferFrom(benefactor, address(this), UFixed18.unwrap(amount));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the `benefactor` to `recipient`\\n     * @dev Reverts if trying to pull Ether\\n     * @param self Token to transfer\\n     * @param benefactor Address to transfer tokens from\\n     * @param recipient Address to transfer tokens to\\n     * @param amount Amount of tokens to transfer\\n     */\\n    function pullTo(Token18 self, address benefactor, address recipient, UFixed18 amount) internal {\\n        IERC20(Token18.unwrap(self)).safeTransferFrom(benefactor, recipient, UFixed18.unwrap(amount));\\n    }\\n\\n    /**\\n     * @notice Returns the name of the token\\n     * @param self Token to check for\\n     * @return Token name\\n     */\\n    function name(Token18 self) internal view returns (string memory) {\\n        return IERC20Metadata(Token18.unwrap(self)).name();\\n    }\\n\\n    /**\\n     * @notice Returns the symbol of the token\\n     * @param self Token to check for\\n     * @return Token symbol\\n     */\\n    function symbol(Token18 self) internal view returns (string memory) {\\n        return IERC20Metadata(Token18.unwrap(self)).symbol();\\n    }\\n\\n    /**\\n     * @notice Returns the `self` token balance of the caller\\n     * @param self Token to check for\\n     * @return Token balance of the caller\\n     */\\n    function balanceOf(Token18 self) internal view returns (UFixed18) {\\n        return balanceOf(self, address(this));\\n    }\\n\\n    /**\\n     * @notice Returns the `self` token balance of `account`\\n     * @param self Token to check for\\n     * @param account Account to check\\n     * @return Token balance of the account\\n     */\\n    function balanceOf(Token18 self, address account) internal view returns (UFixed18) {\\n        return UFixed18.wrap(IERC20(Token18.unwrap(self)).balanceOf(account));\\n    }\\n}\\n\\nlibrary Token18StorageLib {\\n    function read(Token18Storage self) internal view returns (Token18 value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    function store(Token18Storage self, Token18 value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x6b12afaece814f0ab186200a4729e93eb685a21d3e9b5a3372ff283a7ad5dc23\",\"license\":\"Apache-2.0\"},\"@equilibria/root/token/types/Token6.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"../../number/types/UFixed18.sol\\\";\\n\\n/// @dev Token6\\ntype Token6 is address;\\nusing Token6Lib for Token6 global;\\ntype Token6Storage is bytes32;\\nusing Token6StorageLib for Token6Storage global;\\n\\n/**\\n * @title Token6Lib\\n * @notice Library to manage 6-decimal ERC20s that is compliant with the fixed-decimal types.\\n * @dev Automatically converts from Base-6 token amounts to Base-18 UFixed18 amounts, with optional rounding\\n */\\nlibrary Token6Lib {\\n    using SafeERC20 for IERC20;\\n\\n    Token6 public constant ZERO = Token6.wrap(address(0));\\n\\n    uint256 private constant OFFSET = 1e12;\\n\\n    /**\\n     * @notice Returns whether a token is the zero address\\n     * @param self Token to check for\\n     * @return Whether the token is the zero address\\n     */\\n    function isZero(Token6 self) internal pure returns (bool) {\\n        return Token6.unwrap(self) == Token6.unwrap(ZERO);\\n    }\\n\\n    /**\\n     * @notice Returns whether the two tokens are equal\\n     * @param a First token to compare\\n     * @param b Second token to compare\\n     * @return Whether the two tokens are equal\\n     */\\n    function eq(Token6 a, Token6 b) internal pure returns (bool) {\\n        return Token6.unwrap(a) ==  Token6.unwrap(b);\\n    }\\n\\n    /**\\n     * @notice Approves `grantee` to spend infinite tokens from the caller\\n     * @param self Token to transfer\\n     * @param grantee Address to allow spending\\n     */\\n    function approve(Token6 self, address grantee) internal {\\n        IERC20(Token6.unwrap(self)).safeApprove(grantee, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice Approves `grantee` to spend `amount` tokens from the caller\\n     * @dev There are important race conditions to be aware of when using this function\\n            with values other than 0. This will revert if moving from non-zero to non-zero amounts\\n            See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a55b7d13722e7ce850b626da2313f3e66ca1d101/contracts/token/ERC20/IERC20.sol#L57\\n     * @param self Token to transfer\\n     * @param grantee Address to allow spending\\n     * @param amount Amount of tokens to approve to spend\\n     */\\n    function approve(Token6 self, address grantee, UFixed18 amount) internal {\\n        IERC20(Token6.unwrap(self)).safeApprove(grantee, toTokenAmount(amount, false));\\n    }\\n\\n    /**\\n     * @notice Approves `grantee` to spend `amount` tokens from the caller\\n     * @dev There are important race conditions to be aware of when using this function\\n            with values other than 0. This will revert if moving from non-zero to non-zero amounts\\n            See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a55b7d13722e7ce850b626da2313f3e66ca1d101/contracts/token/ERC20/IERC20.sol#L57\\n     * @param self Token to transfer\\n     * @param grantee Address to allow spending\\n     * @param amount Amount of tokens to approve to spend\\n     * @param roundUp Whether to round decimal token amount up to the next unit\\n     */\\n    function approve(Token6 self, address grantee, UFixed18 amount, bool roundUp) internal {\\n        IERC20(Token6.unwrap(self)).safeApprove(grantee, toTokenAmount(amount, roundUp));\\n    }\\n\\n    /**\\n     * @notice Transfers all held tokens from the caller to the `recipient`\\n     * @param self Token to transfer\\n     * @param recipient Address to receive the tokens\\n     */\\n    function push(Token6 self, address recipient) internal {\\n        push(self, recipient, balanceOf(self, address(this)));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the caller to the `recipient`\\n     * @param self Token to transfer\\n     * @param recipient Address to transfer tokens to\\n     * @param amount Amount of tokens to transfer\\n     */\\n    function push(Token6 self, address recipient, UFixed18 amount) internal {\\n        IERC20(Token6.unwrap(self)).safeTransfer(recipient, toTokenAmount(amount, false));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the caller to the `recipient`\\n     * @param self Token to transfer\\n     * @param recipient Address to transfer tokens to\\n     * @param amount Amount of tokens to transfer\\n     * @param roundUp Whether to round decimal token amount up to the next unit\\n     */\\n    function push(Token6 self, address recipient, UFixed18 amount, bool roundUp) internal {\\n        IERC20(Token6.unwrap(self)).safeTransfer(recipient, toTokenAmount(amount, roundUp));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the `benefactor` to the caller\\n     * @dev Reverts if trying to pull Ether\\n     * @param self Token to transfer\\n     * @param benefactor Address to transfer tokens from\\n     * @param amount Amount of tokens to transfer\\n     */\\n    function pull(Token6 self, address benefactor, UFixed18 amount) internal {\\n        IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, address(this), toTokenAmount(amount, false));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the `benefactor` to the caller\\n     * @dev Reverts if trying to pull Ether\\n     * @param self Token to transfer\\n     * @param benefactor Address to transfer tokens from\\n     * @param amount Amount of tokens to transfer\\n     * @param roundUp Whether to round decimal token amount up to the next unit\\n     */\\n    function pull(Token6 self, address benefactor, UFixed18 amount, bool roundUp) internal {\\n        IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, address(this), toTokenAmount(amount, roundUp));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the `benefactor` to `recipient`\\n     * @dev Reverts if trying to pull Ether\\n     * @param self Token to transfer\\n     * @param benefactor Address to transfer tokens from\\n     * @param recipient Address to transfer tokens to\\n     * @param amount Amount of tokens to transfer\\n     */\\n    function pullTo(Token6 self, address benefactor, address recipient, UFixed18 amount) internal {\\n        IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, recipient, toTokenAmount(amount, false));\\n    }\\n\\n    /**\\n     * @notice Transfers `amount` tokens from the `benefactor` to `recipient`\\n     * @dev Reverts if trying to pull Ether\\n     * @param self Token to transfer\\n     * @param benefactor Address to transfer tokens from\\n     * @param recipient Address to transfer tokens to\\n     * @param amount Amount of tokens to transfer\\n     * @param roundUp Whether to round decimal token amount up to the next unit\\n     */\\n    function pullTo(Token6 self, address benefactor, address recipient, UFixed18 amount, bool roundUp) internal {\\n        IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, recipient, toTokenAmount(amount, roundUp));\\n    }\\n\\n    /**\\n     * @notice Returns the name of the token\\n     * @param self Token to check for\\n     * @return Token name\\n     */\\n    function name(Token6 self) internal view returns (string memory) {\\n        return IERC20Metadata(Token6.unwrap(self)).name();\\n    }\\n\\n    /**\\n     * @notice Returns the symbol of the token\\n     * @param self Token to check for\\n     * @return Token symbol\\n     */\\n    function symbol(Token6 self) internal view returns (string memory) {\\n        return IERC20Metadata(Token6.unwrap(self)).symbol();\\n    }\\n\\n    /**\\n     * @notice Returns the `self` token balance of the caller\\n     * @param self Token to check for\\n     * @return Token balance of the caller\\n     */\\n    function balanceOf(Token6 self) internal view returns (UFixed18) {\\n        return balanceOf(self, address(this));\\n    }\\n\\n    /**\\n     * @notice Returns the `self` token balance of `account`\\n     * @param self Token to check for\\n     * @param account Account to check\\n     * @return Token balance of the account\\n     */\\n    function balanceOf(Token6 self, address account) internal view returns (UFixed18) {\\n        return fromTokenAmount(IERC20(Token6.unwrap(self)).balanceOf(account));\\n    }\\n\\n    /**\\n     * @notice Converts the unsigned fixed-decimal amount into the token amount according to\\n     *         it's defined decimals\\n     * @dev Provides the ability to \\\"round up\\\" the token amount which is useful in situations where\\n     *      are swapping one token for another and don't want to give away \\\"free\\\" units due to rounding\\n     *      errors in the favor of the user.\\n     * @param amount Amount to convert\\n     * @param roundUp Whether to round decimal token amount up to the next unit\\n     * @return Normalized token amount\\n     */\\n    function toTokenAmount(UFixed18 amount, bool roundUp) private pure returns (uint256) {\\n        return roundUp ? Math.ceilDiv(UFixed18.unwrap(amount), OFFSET) : UFixed18.unwrap(amount) / OFFSET;\\n    }\\n\\n    /**\\n     * @notice Converts the token amount into the unsigned fixed-decimal amount according to\\n     *         it's defined decimals\\n     * @param amount Token amount to convert\\n     * @return Normalized unsigned fixed-decimal amount\\n     */\\n    function fromTokenAmount(uint256 amount) private pure returns (UFixed18) {\\n        return UFixed18.wrap(amount * OFFSET);\\n    }\\n}\\n\\nlibrary Token6StorageLib {\\n    function read(Token6Storage self) internal view returns (Token6 value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    function store(Token6Storage self, Token6 value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x5ec7bee45a0e13f91ab2399472cf11136496073ad470cd70244855e12a7b6e65\",\"license\":\"Apache-2.0\"},\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n    /**\\n     * @dev Must return an address that can be used as a delegate call target.\\n     *\\n     * {BeaconProxy} will check that this address is a contract.\\n     */\\n    function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `to`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address to, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `from` to `to` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the symbol of the token.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the decimals places of the token.\\n     */\\n    function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n    using Address for address;\\n\\n    function safeTransfer(\\n        IERC20 token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(\\n        IERC20 token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n    }\\n\\n    /**\\n     * @dev Deprecated. This function has issues similar to the ones found in\\n     * {IERC20-approve}, and its usage is discouraged.\\n     *\\n     * Whenever possible, use {safeIncreaseAllowance} and\\n     * {safeDecreaseAllowance} instead.\\n     */\\n    function safeApprove(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        // safeApprove should only be called when setting an initial allowance,\\n        // or when resetting it to zero. To increase and decrease it, use\\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n        require(\\n            (value == 0) || (token.allowance(address(this), spender) == 0),\\n            \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n        );\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n    }\\n\\n    function safeIncreaseAllowance(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        unchecked {\\n            uint256 oldAllowance = token.allowance(address(this), spender);\\n            require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n            uint256 newAllowance = oldAllowance - value;\\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n        }\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     * @param token The token targeted by the call.\\n     * @param data The call data (encoded using abi.encode or one of its variants).\\n     */\\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n        // the target address contains contract code and also asserts for success in the low-level call.\\n\\n        bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n        if (returndata.length > 0) {\\n            // Return data is optional\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n     *\\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n     * constructor.\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize/address.code.length, which returns 0\\n        // for contracts in construction, since the code is only stored at the end\\n        // of the constructor execution.\\n\\n        return account.code.length > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain `call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(\\n        address target,\\n        bytes memory data,\\n        uint256 value\\n    ) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(\\n        address target,\\n        bytes memory data,\\n        uint256 value,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\\n        return verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n     * revert reason using the provided one.\\n     *\\n     * _Available since v4.3._\\n     */\\n    function verifyCallResult(\\n        bool success,\\n        bytes memory returndata,\\n        string memory errorMessage\\n    ) internal pure returns (bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n    /**\\n     * @dev Returns the largest of two numbers.\\n     */\\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a >= b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the smallest of two numbers.\\n     */\\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a < b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the average of two numbers. The result is rounded towards\\n     * zero.\\n     */\\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // (a + b) / 2 can overflow.\\n        return (a & b) + (a ^ b) / 2;\\n    }\\n\\n    /**\\n     * @dev Returns the ceiling of the division of two numbers.\\n     *\\n     * This differs from standard division with `/` in that it rounds up instead\\n     * of rounding down.\\n     */\\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // (a + b - 1) / b can overflow on addition, so we distribute.\\n        return a / b + (a % b == 0 ? 0 : 1);\\n    }\\n}\\n\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n    /**\\n     * @dev Returns the largest of two signed numbers.\\n     */\\n    function max(int256 a, int256 b) internal pure returns (int256) {\\n        return a >= b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the smallest of two signed numbers.\\n     */\\n    function min(int256 a, int256 b) internal pure returns (int256) {\\n        return a < b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the average of two signed numbers without overflow.\\n     * The result is rounded towards zero.\\n     */\\n    function average(int256 a, int256 b) internal pure returns (int256) {\\n        // Formula from the book \\\"Hacker's Delight\\\"\\n        int256 x = (a & b) + ((a ^ b) >> 1);\\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\\n    }\\n\\n    /**\\n     * @dev Returns the absolute unsigned value of a signed value.\\n     */\\n    function abs(int256 n) internal pure returns (uint256) {\\n        unchecked {\\n            // must be unchecked in order to support `n = type(int256).min`\\n            return uint256(n >= 0 ? n : -n);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\"},\"contracts/forwarder/Forwarder.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity 0.8.15;\\n\\nimport \\\"../interfaces/IForwarder.sol\\\";\\n\\n/**\\n * @title Forwarder\\n * @notice Facilitates collateral deposits to the protocol where the amount is supplied\\n *         in USDC then wrapped as DSU before being deposited.\\n */\\ncontract Forwarder is IForwarder {\\n    // @dev USDC stablecoin\\n    Token6 public immutable USDC; // solhint-disable-line var-name-mixedcase\\n\\n    // @dev DSU stablecoin\\n    Token18 public immutable DSU; // solhint-disable-line var-name-mixedcase\\n\\n    /// @dev Contract that wraps USDC to DSU\\n    IBatcher public immutable batcher;\\n\\n    /// @dev Contract managing state for collateral accounts in the protocol\\n    ICollateral public immutable collateral;\\n\\n    /**\\n     * @notice Initializes the contract state\\n     * @param usdc_ The USDC token contract address\\n     * @param dsu_ The DSU token contract address\\n     * @param batcher_ The USDC-to-DSU batcher contract address\\n     * @param collateral_ The perennial collateral contract address\\n     */\\n    constructor(\\n        Token6 usdc_,\\n        Token18 dsu_,\\n        IBatcher batcher_,\\n        ICollateral collateral_\\n    ) {\\n        if (!Address.isContract(Token6.unwrap(usdc_))) revert ForwarderNotContractAddressError();\\n        if (!Address.isContract(Token18.unwrap(dsu_))) revert ForwarderNotContractAddressError();\\n        if (!Address.isContract(address(batcher_))) revert ForwarderNotContractAddressError();\\n        if (!Address.isContract(address(collateral_))) revert ForwarderNotContractAddressError();\\n\\n        USDC = usdc_;\\n        DSU = dsu_;\\n        batcher = batcher_;\\n        collateral = collateral_;\\n\\n        USDC.approve(address(batcher));\\n        DSU.approve(address(collateral));\\n    }\\n\\n    /**\\n     * @notice Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU,\\n               and deposits it as collateral to `account`'s `product` account\\n     * @param account Account to deposit the collateral for\\n     * @param product Product to credit the collateral to\\n     * @param amount 18 decimals-normalized stablecoin (USDC, DSU) value of collateral to deposit\\n    */\\n    function wrapAndDeposit(\\n        address account,\\n        IProduct product,\\n        UFixed18 amount\\n    ) external {\\n        USDC.pull(msg.sender, amount, true);\\n        batcher.wrap(amount, address(this));\\n        collateral.depositTo(account, product, amount);\\n        emit WrapAndDeposit(account, product, amount);\\n    }\\n}\\n\",\"keccak256\":\"0x69355a55b01b5d1c259f0106600873a5c93f34774292c160f86a547bce86b881\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/ICollateral.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"./IController.sol\\\";\\nimport \\\"./IProduct.sol\\\";\\n\\ninterface ICollateral {\\n    event Deposit(address indexed user, IProduct indexed product, UFixed18 amount);\\n    event Withdrawal(address indexed user, IProduct indexed product, UFixed18 amount);\\n    event AccountSettle(IProduct indexed product, address indexed account, Fixed18 amount, UFixed18 newShortfall);\\n    event ProductSettle(IProduct indexed product, UFixed18 protocolFee, UFixed18 productFee);\\n    event Liquidation(address indexed user, IProduct indexed product, address liquidator, UFixed18 fee);\\n    event ShortfallResolution(IProduct indexed product, UFixed18 amount);\\n    event FeeClaim(address indexed account, UFixed18 amount);\\n\\n    error CollateralCantLiquidate(UFixed18 totalMaintenance, UFixed18 totalCollateral);\\n    error CollateralInsufficientCollateralError();\\n    error CollateralUnderLimitError();\\n    error CollateralZeroAddressError();\\n\\n    function token() external view returns (Token18);\\n    function fees(address account) external view returns (UFixed18);\\n    function initialize(IController controller_) external;\\n    function depositTo(address account, IProduct product, UFixed18 amount) external;\\n    function withdrawTo(address account, IProduct product, UFixed18 amount) external;\\n    function liquidate(address account, IProduct product) external;\\n    function settleAccount(address account, Fixed18 amount) external;\\n    function settleProduct(UFixed18 amount) external;\\n    function collateral(address account, IProduct product) external view returns (UFixed18);\\n    function collateral(IProduct product) external view returns (UFixed18);\\n    function shortfall(IProduct product) external view returns (UFixed18);\\n    function liquidatable(address account, IProduct product) external view returns (bool);\\n    function liquidatableNext(address account, IProduct product) external view returns (bool);\\n    function resolveShortfall(IProduct product, UFixed18 amount) external;\\n    function claimFee() external;\\n}\\n\",\"keccak256\":\"0xa5e7fdda92702f748e6eb8701e522450035a98a05e5fc1cf66d51c52e397d914\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IContractPayoffProvider.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\n\\ninterface IContractPayoffProvider {\\n    function payoff(Fixed18 price) external view returns (Fixed18 payoff);\\n}\\n\",\"keccak256\":\"0xd73df106d032e976fd959ee6713240e36f54277ce5f215eaec8d5a2c6720a86b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IController.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\\\";\\nimport \\\"./ICollateral.sol\\\";\\nimport \\\"./IIncentivizer.sol\\\";\\nimport \\\"./IProduct.sol\\\";\\nimport \\\"./types/PayoffDefinition.sol\\\";\\n\\ninterface IController {\\n    /// @dev Coordinator of a one or many products\\n    struct Coordinator {\\n        /// @dev Pending owner of the product, can accept ownership\\n        address pendingOwner;\\n\\n        /// @dev Owner of the product, allowed to update select parameters\\n        address owner;\\n\\n        /// @dev Treasury of the product, collects fees\\n        address treasury;\\n    }\\n\\n    event CollateralUpdated(ICollateral newCollateral);\\n    event IncentivizerUpdated(IIncentivizer newIncentivizer);\\n    event ProductBeaconUpdated(IBeacon newProductBeacon);\\n    event ProtocolFeeUpdated(UFixed18 newProtocolFee);\\n    event MinFundingFeeUpdated(UFixed18 newMinFundingFee);\\n    event LiquidationFeeUpdated(UFixed18 newLiquidationFee);\\n    event IncentivizationFeeUpdated(UFixed18 newIncentivizationFee);\\n    event MinCollateralUpdated(UFixed18 newMinCollateral);\\n    event ProgramsPerProductUpdated(uint256 newProgramsPerProduct);\\n    event PauserUpdated(address newPauser);\\n    event PausedUpdated(bool newPaused);\\n    event CoordinatorPendingOwnerUpdated(uint256 indexed coordinatorId, address newPendingOwner);\\n    event CoordinatorOwnerUpdated(uint256 indexed coordinatorId, address newOwner);\\n    event CoordinatorTreasuryUpdated(uint256 indexed coordinatorId, address newTreasury);\\n    event CoordinatorCreated(uint256 indexed coordinatorId, address owner);\\n    event ProductCreated(IProduct indexed product, IProduct.ProductInfo productInfo);\\n\\n    error ControllerNoZeroCoordinatorError();\\n    error ControllerNotPauserError();\\n    error ControllerNotOwnerError(uint256 controllerId);\\n    error ControllerNotPendingOwnerError(uint256 controllerId);\\n    error ControllerInvalidProtocolFeeError();\\n    error ControllerInvalidMinFundingFeeError();\\n    error ControllerInvalidLiquidationFeeError();\\n    error ControllerInvalidIncentivizationFeeError();\\n    error ControllerNotContractAddressError();\\n\\n    function collateral() external view returns (ICollateral);\\n    function incentivizer() external view returns (IIncentivizer);\\n    function productBeacon() external view returns (IBeacon);\\n    function coordinators(uint256 collateralId) external view returns (Coordinator memory);\\n    function coordinatorFor(IProduct product) external view returns (uint256);\\n    function protocolFee() external view returns (UFixed18);\\n    function minFundingFee() external view returns (UFixed18);\\n    function liquidationFee() external view returns (UFixed18);\\n    function incentivizationFee() external view returns (UFixed18);\\n    function minCollateral() external view returns (UFixed18);\\n    function programsPerProduct() external view returns (uint256);\\n    function pauser() external view returns (address);\\n    function paused() external view returns (bool);\\n    function initialize(ICollateral collateral_, IIncentivizer incentivizer_, IBeacon productBeacon_) external;\\n    function createCoordinator() external returns (uint256);\\n    function updateCoordinatorPendingOwner(uint256 coordinatorId, address newPendingOwner) external;\\n    function acceptCoordinatorOwner(uint256 coordinatorId) external;\\n    function updateCoordinatorTreasury(uint256 coordinatorId, address newTreasury) external;\\n    function createProduct(uint256 coordinatorId, IProduct.ProductInfo calldata productInfo) external returns (IProduct);\\n    function updateCollateral(ICollateral newCollateral) external;\\n    function updateIncentivizer(IIncentivizer newIncentivizer) external;\\n    function updateProductBeacon(IBeacon newProductBeacon) external;\\n    function updateProtocolFee(UFixed18 newProtocolFee) external;\\n    function updateMinFundingFee(UFixed18 newMinFundingFee) external;\\n    function updateLiquidationFee(UFixed18 newLiquidationFee) external;\\n    function updateIncentivizationFee(UFixed18 newIncentivizationFee) external;\\n    function updateMinCollateral(UFixed18 newMinCollateral) external;\\n    function updateProgramsPerProduct(uint256 newProductsPerProduct) external;\\n    function updatePauser(address newPauser) external;\\n    function updatePaused(bool newPaused) external;\\n    function isProduct(IProduct product) external view returns (bool);\\n    function owner() external view returns (address);\\n    function owner(uint256 coordinatorId) external view returns (address);\\n    function owner(IProduct product) external view returns (address);\\n    function treasury() external view returns (address);\\n    function treasury(uint256 coordinatorId) external view returns (address);\\n    function treasury(IProduct product) external view returns (address);\\n}\\n\",\"keccak256\":\"0xaabd3740f2265499eea7aad9bd94f9892f53241e5dccce9a50c0e43ed2a6a7cc\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IForwarder.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity 0.8.15;\\n\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"@equilibria/root/token/types/Token6.sol\\\";\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\\\";\\nimport \\\"./ICollateral.sol\\\";\\n\\ninterface IForwarder {\\n    error ForwarderNotContractAddressError();\\n\\n    event WrapAndDeposit(address indexed account, IProduct indexed product, UFixed18 amount);\\n\\n    function USDC() external view returns (Token6); // solhint-disable-line func-name-mixedcase\\n    function DSU() external view returns (Token18); // solhint-disable-line func-name-mixedcase\\n    function batcher() external view returns (IBatcher);\\n    function collateral() external view returns (ICollateral);\\n    function wrapAndDeposit(address account, IProduct product, UFixed18 amount) external;\\n}\\n\",\"keccak256\":\"0x800026180c5f82bba4ecd57d91dc2eb364326de8ca5ed0e56308620d58b6bc61\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IIncentivizer.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\\\";\\nimport \\\"./types/ProgramInfo.sol\\\";\\nimport \\\"./IController.sol\\\";\\nimport \\\"./IProduct.sol\\\";\\n\\ninterface IIncentivizer {\\n    event ProgramCreated(IProduct indexed product, uint256 indexed programId, ProgramInfo programInfo, UFixed18 programFeeAmount);\\n    event ProgramStarted(IProduct indexed product, uint256 indexed programId, uint256 version);\\n    event ProgramComplete(IProduct indexed product, uint256 indexed programId, uint256 version);\\n    event Claim(IProduct indexed product, address indexed account, uint256 indexed programId, UFixed18 amount);\\n    event FeeClaim(Token18 indexed token, UFixed18 amount);\\n\\n    error IncentivizerNotAllowedError(IProduct product);\\n    error IncentivizerTooManyProgramsError();\\n    error IncentivizerNotProgramOwnerError(IProduct product, uint256 programId);\\n    error IncentivizerInvalidProgramError(IProduct product, uint256 programId);\\n    error IncentivizerBatchClaimArgumentMismatchError();\\n\\n    function programInfos(IProduct product, uint256 programId) external view returns (ProgramInfo memory);\\n    function fees(Token18 token) external view returns (UFixed18);\\n    function initialize(IController controller_) external;\\n    function create(IProduct product, ProgramInfo calldata info) external returns (uint256);\\n    function complete(IProduct product, uint256 programId) external;\\n    function sync(IOracleProvider.OracleVersion memory currentOracleVersion) external;\\n    function syncAccount(address account, IOracleProvider.OracleVersion memory currentOracleVersion) external;\\n    function claim(IProduct product, uint256[] calldata programIds) external;\\n    function claim(IProduct[] calldata products, uint256[][] calldata programIds) external;\\n    function claimFee(Token18[] calldata tokens) external;\\n    function active(IProduct product) external view returns (uint256);\\n    function count(IProduct product) external view returns (uint256);\\n    function unclaimed(IProduct product, address account, uint256 programId) external view returns (UFixed18);\\n    function available(IProduct product, uint256 programId) external view returns (UFixed18);\\n    function versionStarted(IProduct product, uint256 programId) external view returns (uint256);\\n    function versionComplete(IProduct product, uint256 programId) external view returns (uint256);\\n    function owner(IProduct product, uint256 programId) external view returns (address);\\n    function treasury(IProduct product, uint256 programId) external view returns (address);\\n}\\n\",\"keccak256\":\"0x2f95de90dbb3ad35dbfef304f765a622bffff9229868d2898eca8d49c78e8c2c\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IParamProvider.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/root/curve/types/JumpRateUtilizationCurve.sol\\\";\\n\\ninterface IParamProvider {\\n    event MaintenanceUpdated(UFixed18 newMaintenance);\\n    event FundingFeeUpdated(UFixed18 newFundingFee);\\n    event MakerFeeUpdated(UFixed18 newMakerFee);\\n    event TakerFeeUpdated(UFixed18 newTakerFee);\\n    event MakerLimitUpdated(UFixed18 newMakerLimit);\\n    event JumpRateUtilizationCurveUpdated(\\n        Fixed18 minRate,\\n        Fixed18 maxRate,\\n        Fixed18 targetRate,\\n        UFixed18 targetUtilization\\n    );\\n\\n    error ParamProviderInvalidMakerFee();\\n    error ParamProviderInvalidTakerFee();\\n    error ParamProviderInvalidFundingFee();\\n    \\n    function maintenance() external view returns (UFixed18);\\n    function updateMaintenance(UFixed18 newMaintenance) external;\\n    function fundingFee() external view returns (UFixed18);\\n    function updateFundingFee(UFixed18 newFundingFee) external;\\n    function makerFee() external view returns (UFixed18);\\n    function updateMakerFee(UFixed18 newMakerFee) external;\\n    function takerFee() external view returns (UFixed18);\\n    function updateTakerFee(UFixed18 newTakerFee) external;\\n    function makerLimit() external view returns (UFixed18);\\n    function updateMakerLimit(UFixed18 newMakerLimit) external;\\n    function utilizationCurve() external view returns (JumpRateUtilizationCurve memory);\\n    function updateUtilizationCurve(JumpRateUtilizationCurve memory newUtilizationCurve) external;\\n}\\n\",\"keccak256\":\"0x2e2d40d0cf55f167118867e41f740b9b40614d05da50fc9bc33a8cede3eaf03e\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IPayoffProvider.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\nimport \\\"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\\\";\\nimport \\\"./types/PayoffDefinition.sol\\\";\\n\\ninterface IPayoffProvider {\\n    error PayoffProviderInvalidOracle();\\n    error PayoffProviderInvalidPayoffDefinitionError();\\n\\n    function oracle() external view returns (IOracleProvider);\\n    function payoffDefinition() external view returns (PayoffDefinition memory);\\n    function currentVersion() external view returns (IOracleProvider.OracleVersion memory);\\n    function atVersion(uint256 oracleVersion) external view returns (IOracleProvider.OracleVersion memory);\\n}\\n\",\"keccak256\":\"0xb83d80d624aa9431763f80ecb4bf0214803e25334a7419d954f929e5d0ee7467\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IProduct.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/root/curve/types/JumpRateUtilizationCurve.sol\\\";\\nimport \\\"./IPayoffProvider.sol\\\";\\nimport \\\"./IParamProvider.sol\\\";\\nimport \\\"./types/PayoffDefinition.sol\\\";\\nimport \\\"./types/Position.sol\\\";\\nimport \\\"./types/PrePosition.sol\\\";\\nimport \\\"./types/Accumulator.sol\\\";\\n\\ninterface IProduct is IPayoffProvider, IParamProvider {\\n    /// @dev Product Creation parameters\\n    struct ProductInfo {\\n        /// @dev name of the product\\n        string name;\\n\\n        /// @dev symbol of the product\\n        string symbol;\\n\\n        /// @dev product payoff definition\\n        PayoffDefinition payoffDefinition;\\n\\n        /// @dev oracle address\\n        IOracleProvider oracle;\\n\\n        /// @dev product maintenance ratio\\n        UFixed18 maintenance;\\n\\n        /// @dev product funding fee\\n        UFixed18 fundingFee;\\n\\n        /// @dev product maker fee\\n        UFixed18 makerFee;\\n\\n        /// @dev product taker fee\\n        UFixed18 takerFee;\\n\\n        /// @dev product maker limit\\n        UFixed18 makerLimit;\\n\\n        /// @dev utulization curve definition\\n        JumpRateUtilizationCurve utilizationCurve;\\n    }\\n\\n    event Settle(uint256 preVersion, uint256 toVersion);\\n    event AccountSettle(address indexed account, uint256 preVersion, uint256 toVersion);\\n    event MakeOpened(address indexed account, uint256 version, UFixed18 amount);\\n    event TakeOpened(address indexed account, uint256 version, UFixed18 amount);\\n    event MakeClosed(address indexed account, uint256 version, UFixed18 amount);\\n    event TakeClosed(address indexed account, uint256 version, UFixed18 amount);\\n    event ClosedUpdated(bool indexed newClosed, uint256 version);\\n\\n    error ProductInsufficientLiquidityError(UFixed18 socializationFactor);\\n    error ProductDoubleSidedError();\\n    error ProductOverClosedError();\\n    error ProductInsufficientCollateralError();\\n    error ProductInLiquidationError();\\n    error ProductMakerOverLimitError();\\n    error ProductOracleBootstrappingError();\\n    error ProductNotOwnerError();\\n    error ProductInvalidOracle();\\n    error ProductClosedError();\\n\\n    function name() external view returns (string memory);\\n    function symbol() external view returns (string memory);\\n    function initialize(ProductInfo calldata productInfo_) external;\\n    function settle() external;\\n    function settleAccount(address account) external;\\n    function openTake(UFixed18 amount) external;\\n    function closeTake(UFixed18 amount) external;\\n    function openMake(UFixed18 amount) external;\\n    function closeMake(UFixed18 amount) external;\\n    function closeAll(address account) external;\\n    function maintenance(address account) external view returns (UFixed18);\\n    function maintenanceNext(address account) external view returns (UFixed18);\\n    function isClosed(address account) external view returns (bool);\\n    function isLiquidating(address account) external view returns (bool);\\n    function position(address account) external view returns (Position memory);\\n    function pre(address account) external view returns (PrePosition memory);\\n    function latestVersion() external view returns (uint256);\\n    function positionAtVersion(uint256 oracleVersion) external view returns (Position memory);\\n    function pre() external view returns (PrePosition memory);\\n    function valueAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\\n    function shareAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\\n    function latestVersion(address account) external view returns (uint256);\\n    function rate(Position memory position) external view returns (Fixed18);\\n    function closed() external view returns (bool);\\n    function updateClosed(bool newClosed) external;\\n}\\n\",\"keccak256\":\"0xe1e80b818eadf4cdb070362e40c7cf3863b50c4f944816af27848e319f587241\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/Accumulator.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\nimport \\\"./PackedAccumulator.sol\\\";\\n\\n/// @dev Accumulator type\\nstruct Accumulator {\\n    /// @dev maker accumulator per share\\n    Fixed18 maker;\\n    /// @dev taker accumulator per share\\n    Fixed18 taker;\\n}\\nusing AccumulatorLib for Accumulator global;\\n\\n/**\\n * @title AccountAccumulatorLib\\n * @notice Library that surfaces math operations for the Accumulator type.\\n * @dev Accumulators track the cumulative change in position value over time for the maker and taker positions\\n *      respectively. Account-level accumulators can then use two of these values `a` and `a'` to compute the\\n *      change in position value since last sync. This change in value is then used to compute P&L and fees.\\n */\\nlibrary AccumulatorLib {\\n    /**\\n     * @notice Creates a packed accumulator from an accumulator\\n     * @param self an accumulator\\n     * @return New packed accumulator\\n     */\\n    function pack(Accumulator memory self) internal pure returns (PackedAccumulator memory) {\\n        return PackedAccumulator({maker: self.maker.pack(), taker: self.taker.pack()});\\n    }\\n\\n    /**\\n     * @notice Adds two accumulators together\\n     * @param a The first accumulator to sum\\n     * @param b The second accumulator to sum\\n     * @return The resulting summed accumulator\\n     */\\n    function add(Accumulator memory a, Accumulator memory b) internal pure returns (Accumulator memory) {\\n        return Accumulator({maker: a.maker.add(b.maker), taker: a.taker.add(b.taker)});\\n    }\\n\\n    /**\\n     * @notice Subtracts accumulator `b` from `a`\\n     * @param a The accumulator to subtract from\\n     * @param b The accumulator to subtract\\n     * @return The resulting subtracted accumulator\\n     */\\n    function sub(Accumulator memory a, Accumulator memory b) internal pure returns (Accumulator memory) {\\n        return Accumulator({maker: a.maker.sub(b.maker), taker: a.taker.sub(b.taker)});\\n    }\\n\\n    /**\\n     * @notice Multiplies two accumulators together\\n     * @param a The first accumulator to multiply\\n     * @param b The second accumulator to multiply\\n     * @return The resulting multiplied accumulator\\n     */\\n    function mul(Accumulator memory a, Accumulator memory b) internal pure returns (Accumulator memory) {\\n        return Accumulator({maker: a.maker.mul(b.maker), taker: a.taker.mul(b.taker)});\\n    }\\n\\n    /**\\n     * @notice Sums the maker and taker together from a single accumulator\\n     * @param self The struct to operate on\\n     * @return The sum of its maker and taker\\n     */\\n    function sum(Accumulator memory self) internal pure returns (Fixed18) {\\n        return self.maker.add(self.taker);\\n    }\\n}\\n\",\"keccak256\":\"0x7ccd0a72aa593cefb9f4337cf312799f357b82fcb3f0379de0dc503d1cb7e387\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/PackedAccumulator.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/PackedFixed18.sol\\\";\\nimport \\\"./Accumulator.sol\\\";\\n\\n/// @dev PackedAccumulator type\\nstruct PackedAccumulator {\\n    /// @dev maker accumulator per share\\n    PackedFixed18 maker;\\n    /// @dev taker accumulator per share\\n    PackedFixed18 taker;\\n}\\nusing PackedAccumulatorLib for PackedAccumulator global;\\n\\n/**\\n * @title PackedAccumulatorLib\\n * @dev A packed version of the Accumulator which takes up a single storage slot using `PackedFixed18` values.\\n * @notice Library for the packed Accumulator type.\\n */\\nlibrary PackedAccumulatorLib {\\n    /**\\n     * @notice Creates an accumulator from a packed accumulator\\n     * @param self packed accumulator\\n     * @return New accumulator\\n     */\\n    function unpack(PackedAccumulator memory self) internal pure returns (Accumulator memory) {\\n        return Accumulator({maker: self.maker.unpack(), taker: self.taker.unpack()});\\n    }\\n}\\n\",\"keccak256\":\"0xd83f2822d4f6c818087a232b54007730992c34ff77377fc307a282f886e7cf65\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/PackedPosition.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/PackedUFixed18.sol\\\";\\nimport \\\"./Position.sol\\\";\\n\\n/// @dev PackedPosition type\\nstruct PackedPosition {\\n    /// @dev Quantity of the maker position\\n    PackedUFixed18 maker;\\n    /// @dev Quantity of the taker position\\n    PackedUFixed18 taker;\\n}\\nusing PackedPositionLib for PackedPosition global;\\n\\n/**\\n * @title PackedPositionLib\\n * @dev A packed version of the Position which takes up a single storage slot using `PackedFixed18` values.\\n * @notice Library for the packed Position type.\\n */\\nlibrary PackedPositionLib {\\n    /**\\n     * @notice Creates an position from a packed position\\n     * @param self packed position\\n     * @return New position\\n     */\\n    function unpack(PackedPosition memory self) internal pure returns (Position memory) {\\n        return Position({maker: self.maker.unpack(), taker: self.taker.unpack()});\\n    }\\n}\\n\",\"keccak256\":\"0x04968e6794f6244cb3415cea111d640273a81faea957872988d0cb580f45df1e\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/PayoffDefinition.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity 0.8.15;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"../../interfaces/IContractPayoffProvider.sol\\\";\\n\\n/// @dev PayoffDefinition tyoe\\nstruct PayoffDefinition {\\n  PayoffDefinitionLib.PayoffType payoffType;\\n  PayoffDefinitionLib.PayoffDirection payoffDirection;\\n  bytes30 data;\\n}\\nusing PayoffDefinitionLib for PayoffDefinition global;\\ntype PayoffDefinitionStorage is bytes32;\\nusing PayoffDefinitionStorageLib for PayoffDefinitionStorage global;\\n\\n/**\\n * @title PayoffDefinitionLib\\n * @dev Library that surfaces logic for PayoffDefinition type functionality\\n * @notice Library for the PayoffDefinition type. Performs validity and price transformation\\n            based on the payoff definition type.\\n */\\nlibrary PayoffDefinitionLib {\\n  using Address for address;\\n\\n  error PayoffDefinitionUnsupportedTransform(PayoffType payoffType, PayoffDirection payoffDirection);\\n  error PayoffDefinitionNotContract(PayoffType payoffType, bytes30 data);\\n\\n  /// @dev Payoff function type enum\\n  enum PayoffType { PASSTHROUGH, CONTRACT }\\n  enum PayoffDirection { LONG, SHORT }\\n\\n  /**\\n   * @notice Checks validity of the payoff definition\\n   * @param self a payoff definition\\n   * @return Whether the payoff definition is valid for it's given type\\n   */\\n  function valid(PayoffDefinition memory self) internal view returns (bool) {\\n    if (self.payoffType == PayoffType.CONTRACT) return address(_providerContract(self)).isContract();\\n\\n    // All other payoff types should have no data\\n    return uint(bytes32(self.data)) == 0;\\n  }\\n\\n  /**\\n   * @notice Transforms a price based on the payoff definition\\n   * @param self a payoff definition\\n   * @param price raw oracle price\\n   * @return Price transformed by the payoff definition function\\n   */\\n  function transform(\\n    PayoffDefinition memory self,\\n    Fixed18 price\\n  ) internal view returns (Fixed18) {\\n    PayoffType payoffType = self.payoffType;\\n    PayoffDirection payoffDirection = self.payoffDirection;\\n    Fixed18 transformedPrice;\\n\\n    // First get the price depending on the type\\n    if (payoffType == PayoffType.PASSTHROUGH) transformedPrice = price;\\n    else if (payoffType == PayoffType.CONTRACT) transformedPrice =  _payoffFromContract(self, price);\\n    else revert PayoffDefinitionUnsupportedTransform(payoffType, payoffDirection);\\n\\n    // Then transform it depending on the direction flag\\n    if (self.payoffDirection == PayoffDirection.LONG) return transformedPrice;\\n    else if (self.payoffDirection == PayoffDirection.SHORT) return transformedPrice.mul(Fixed18Lib.NEG_ONE);\\n    else revert PayoffDefinitionUnsupportedTransform(payoffType, payoffDirection);\\n  }\\n\\n  /**\\n   * @notice Parses the data field into an address\\n   * @dev Reverts if payoffType is not CONTRACT\\n   * @param self a payoff definition\\n   * @return IContractPayoffProvider address\\n   */\\n  function _providerContract(\\n    PayoffDefinition memory self\\n  ) private pure returns (IContractPayoffProvider) {\\n    if (self.payoffType != PayoffType.CONTRACT) revert PayoffDefinitionNotContract(self.payoffType, self.data);\\n    // Shift to pull the last 20 bytes, then cast to an address\\n    return IContractPayoffProvider(address(bytes20(self.data << 80)));\\n  }\\n\\n  /**\\n   * @notice Performs a price transformation by calling the underlying payoff contract\\n   * @param self a payoff definition\\n   * @param price raw oracle price\\n   * @return Price transformed by the payoff definition function on the contract\\n   */\\n  function _payoffFromContract(\\n    PayoffDefinition memory self,\\n    Fixed18 price\\n  ) private view returns (Fixed18) {\\n    bytes memory ret = address(_providerContract(self)).functionStaticCall(\\n      abi.encodeCall(IContractPayoffProvider.payoff, price)\\n    );\\n    return Fixed18.wrap(abi.decode(ret, (int256)));\\n  }\\n}\\n\\n/**\\n * @title PayoffDefinitionStorageLib\\n * @notice Library that surfaces storage read and writes for the PayoffDefinition type\\n */\\nlibrary PayoffDefinitionStorageLib {\\n    function read(PayoffDefinitionStorage self) internal view returns (PayoffDefinition memory) {\\n        return _storagePointer(self);\\n    }\\n\\n    function store(PayoffDefinitionStorage self, PayoffDefinition memory value) internal {\\n        PayoffDefinition storage storagePointer = _storagePointer(self);\\n\\n        storagePointer.payoffType = value.payoffType;\\n        storagePointer.payoffDirection = value.payoffDirection;\\n        storagePointer.data = value.data;\\n    }\\n\\n    function _storagePointer(\\n      PayoffDefinitionStorage self\\n    ) private pure returns (PayoffDefinition storage pointer) {\\n        assembly { pointer.slot := self }\\n    }\\n}\\n\",\"keccak256\":\"0x4d3897f408f77381c5ae9990391465c8fd511ddf6ff3b39f6cb69d8c2bd554df\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/Position.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"../IProduct.sol\\\";\\nimport \\\"./Accumulator.sol\\\";\\nimport \\\"./PrePosition.sol\\\";\\nimport \\\"./PackedPosition.sol\\\";\\n\\n/// @dev Position type\\nstruct Position {\\n    /// @dev Quantity of the maker position\\n    UFixed18 maker;\\n    /// @dev Quantity of the taker position\\n    UFixed18 taker;\\n}\\nusing PositionLib for Position global;\\n\\n/**\\n * @title PositionLib\\n * @notice Library that surfaces math and settlement computations for the Position type.\\n * @dev Positions track the current quantity of the account's maker and taker positions respectively\\n *      denominated as a unit of the product's payoff function.\\n */\\nlibrary PositionLib {\\n    /**\\n     * @notice Creates a packed position from an position\\n     * @param self A position\\n     * @return New packed position\\n     */\\n    function pack(Position memory self) internal pure returns (PackedPosition memory) {\\n        return PackedPosition({maker: self.maker.pack(), taker: self.taker.pack()});\\n    }\\n\\n    /**\\n     * @notice Returns whether the position is fully empty\\n     * @param self A position\\n     * @return Whether the position is empty\\n     */\\n    function isEmpty(Position memory self) internal pure returns (bool) {\\n        return self.maker.isZero() && self.taker.isZero();\\n    }\\n\\n    /**\\n     * @notice Adds position `a` and `b` together, returning the result\\n     * @param a The first position to sum\\n     * @param b The second position to sum\\n     * @return Resulting summed position\\n     */\\n    function add(Position memory a, Position memory b) internal pure returns (Position memory) {\\n        return Position({maker: a.maker.add(b.maker), taker: a.taker.add(b.taker)});\\n    }\\n\\n    /**\\n     * @notice Subtracts position `b` from `a`, returning the result\\n     * @param a The position to subtract from\\n     * @param b The position to subtract\\n     * @return Resulting subtracted position\\n     */\\n    function sub(Position memory a, Position memory b) internal pure returns (Position memory) {\\n        return Position({maker: a.maker.sub(b.maker), taker: a.taker.sub(b.taker)});\\n    }\\n\\n    /**\\n     * @notice Multiplies position `self` by accumulator `accumulator` and returns the resulting accumulator\\n     * @param self The Position to operate on\\n     * @param accumulator The accumulator to multiply by\\n     * @return Resulting multiplied accumulator\\n     */\\n    function mul(Position memory self, Accumulator memory accumulator) internal pure returns (Accumulator memory) {\\n        return Accumulator({\\n            maker: Fixed18Lib.from(self.maker).mul(accumulator.maker),\\n            taker: Fixed18Lib.from(self.taker).mul(accumulator.taker)\\n        });\\n    }\\n\\n    /**\\n     * @notice Scales position `self` by fixed-decimal `scale` and returns the resulting position\\n     * @param self The Position to operate on\\n     * @param scale The Fixed-decimal to scale by\\n     * @return Resulting scaled position\\n     */\\n    function mul(Position memory self, UFixed18 scale) internal pure returns (Position memory) {\\n        return Position({maker: self.maker.mul(scale), taker: self.taker.mul(scale)});\\n    }\\n\\n    /**\\n     * @notice Divides position `self` by `b` and returns the resulting accumulator\\n     * @param self The Position to operate on\\n     * @param b The number to divide by\\n     * @return Resulting divided accumulator\\n     */\\n    function div(Position memory self, uint256 b) internal pure returns (Accumulator memory) {\\n        return Accumulator({\\n            maker: Fixed18Lib.from(self.maker).div(Fixed18Lib.from(UFixed18Lib.from(b))),\\n            taker: Fixed18Lib.from(self.taker).div(Fixed18Lib.from(UFixed18Lib.from(b)))\\n        });\\n    }\\n\\n    /**\\n     * @notice Returns the maximum of `self`'s maker and taker values\\n     * @param self The struct to operate on\\n     * @return Resulting maximum value\\n     */\\n    function max(Position memory self) internal pure returns (UFixed18) {\\n        return UFixed18Lib.max(self.maker, self.taker);\\n    }\\n\\n    /**\\n     * @notice Sums the maker and taker together from a single position\\n     * @param self The struct to operate on\\n     * @return The sum of its maker and taker\\n     */\\n    function sum(Position memory self) internal pure returns (UFixed18) {\\n        return self.maker.add(self.taker);\\n    }\\n\\n    /**\\n     * @notice Computes the next position after the pending-settlement position delta is included\\n     * @param self The current Position\\n     * @param pre The pending-settlement position delta\\n     * @return Next Position\\n     */\\n    function next(Position memory self, PrePosition memory pre) internal pure returns (Position memory) {\\n        return sub(add(self, pre.openPosition), pre.closePosition);\\n    }\\n\\n    /**\\n     * @notice Returns the settled position at oracle version `toOracleVersion`\\n     * @dev Checks if a new position is ready to be settled based on the provided `toOracleVersion`\\n     *      and `pre` and returns accordingly\\n     * @param self The current Position\\n     * @param pre The pending-settlement position delta\\n     * @param toOracleVersion The oracle version to settle to\\n     * @return Settled position at oracle version\\n     * @return Fee accrued from opening or closing the position\\n     * @return Whether a new position was settled\\n     */\\n    function settled(\\n        Position memory self,\\n        PrePosition memory pre,\\n        IOracleProvider.OracleVersion memory toOracleVersion\\n    ) internal view returns (Position memory, UFixed18, bool) {\\n        return pre.canSettle(toOracleVersion) ? (next(self, pre), pre.computeFee(toOracleVersion), true) : (self, UFixed18Lib.ZERO, false);\\n    }\\n\\n    /**\\n     * @notice Returns the socialization factor for the current position\\n     * @dev Socialization account for the case where `taker` > `maker` temporarily due to a liquidation\\n     *      on the maker side. This dampens the taker's exposure pro-rata to ensure that the maker side\\n     *      is never exposed over 1 x short.\\n     * @param self The Position to operate on\\n     * @return Socialization factor\\n     */\\n    function socializationFactor(Position memory self) internal pure returns (UFixed18) {\\n        return self.taker.isZero() ? UFixed18Lib.ONE : UFixed18Lib.min(UFixed18Lib.ONE, self.maker.div(self.taker));\\n    }\\n}\\n\",\"keccak256\":\"0x027fe392c4f56bf012ba2ca462fcf23e69f2c3b9d283c14089771813437af991\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/PrePosition.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\\\";\\nimport \\\"./Position.sol\\\";\\nimport \\\"../IProduct.sol\\\";\\n\\n/// @dev PrePosition type\\nstruct PrePosition {\\n    /// @dev Oracle version at which the new position delta was recorded\\n    uint256 oracleVersion;\\n\\n    /// @dev Size of position to open at oracle version\\n    Position openPosition;\\n\\n    /// @dev Size of position to close at oracle version\\n    Position closePosition;\\n}\\nusing PrePositionLib for PrePosition global;\\n\\n/**\\n * @title PrePositionLib\\n * @notice Library that manages a pre-settlement position delta.\\n * @dev PrePositions track the currently awaiting-settlement deltas to a settled Position. These are\\n *      Primarily necessary to introduce lag into the settlement system such that oracle lag cannot be\\n *      gamed to a user's advantage. When a user opens or closes a new position, it sits as a PrePosition\\n *      for one oracle version until it's settle into the Position, making it then effective. PrePositions\\n *      are automatically settled at the correct oracle version even if a flywheel call doesn't happen until\\n *      several version into the future by using the historical version lookups in the corresponding \\\"Versioned\\\"\\n *      global state types.\\n */\\nlibrary PrePositionLib {\\n    /**\\n     * @notice Returns whether there is no pending-settlement position delta\\n     * @dev Can be \\\"empty\\\" even with a non-zero oracleVersion if a position is opened and\\n     *      closed in the same version netting out to a zero position delta\\n     * @param self The struct to operate on\\n     * @return Whether the pending-settlement position delta is empty\\n     */\\n    function isEmpty(PrePosition memory self) internal pure returns (bool) {\\n        return self.openPosition.isEmpty() && self.closePosition.isEmpty();\\n    }\\n\\n    /**\\n     * @notice Increments the maker side of the open position delta\\n     * @dev Nets out open and close deltas to minimize the size of each\\n     * @param self The struct to operate on\\n     * @param currentVersion The current oracle version index\\n     * @param amount The position amount to open\\n     */\\n    function openMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n        self.openPosition.maker = self.openPosition.maker.add(amount);\\n        self.oracleVersion = currentVersion;\\n        _netMake(self);\\n    }\\n\\n    /**\\n     * @notice Increments the maker side of the close position delta\\n     * @dev Nets out open and close deltas to minimize the size of each\\n     * @param self The struct to operate on\\n     * @param currentVersion The current oracle version index\\n     * @param amount The maker position amount to close\\n     */\\n    function closeMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n        self.closePosition.maker = self.closePosition.maker.add(amount);\\n        self.oracleVersion = currentVersion;\\n        _netMake(self);\\n    }\\n\\n    /**\\n     * @notice Increments the taker side of the open position delta\\n     * @dev Nets out open and close deltas to minimize the size of each\\n     * @param self The struct to operate on\\n     * @param currentVersion The current oracle version index\\n     * @param amount The taker position amount to open\\n     */\\n    function openTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n        self.openPosition.taker = self.openPosition.taker.add(amount);\\n        self.oracleVersion = currentVersion;\\n        _netTake(self);\\n    }\\n\\n    /**\\n     * @notice Increments the taker side of the close position delta\\n     * @dev Nets out open and close deltas to minimize the size of each\\n     * @param self The struct to operate on\\n     * @param currentVersion The current oracle version index\\n     * @param amount The taker position amount to close\\n     */\\n    function closeTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n        self.closePosition.taker = self.closePosition.taker.add(amount);\\n        self.oracleVersion = currentVersion;\\n        _netTake(self);\\n    }\\n\\n    /**\\n     * @notice Nets out the open and close on the maker side of the position delta\\n     * @param self The struct to operate on\\n     */\\n    function _netMake(PrePosition storage self) private {\\n        if (self.openPosition.maker.gt(self.closePosition.maker)) {\\n            self.openPosition.maker = self.openPosition.maker.sub(self.closePosition.maker);\\n            self.closePosition.maker = UFixed18Lib.ZERO;\\n        } else {\\n            self.closePosition.maker = self.closePosition.maker.sub(self.openPosition.maker);\\n            self.openPosition.maker = UFixed18Lib.ZERO;\\n        }\\n    }\\n\\n    /**\\n     * @notice Nets out the open and close on the taker side of the position delta\\n     * @param self The struct to operate on\\n     */\\n    function _netTake(PrePosition storage self) private {\\n        if (self.openPosition.taker.gt(self.closePosition.taker)) {\\n            self.openPosition.taker = self.openPosition.taker.sub(self.closePosition.taker);\\n            self.closePosition.taker = UFixed18Lib.ZERO;\\n        } else {\\n            self.closePosition.taker = self.closePosition.taker.sub(self.openPosition.taker);\\n            self.openPosition.taker = UFixed18Lib.ZERO;\\n        }\\n    }\\n\\n    /**\\n     * @notice Returns whether the the pending position delta can be settled at version `toOracleVersion`\\n     * @dev Pending-settlement positions deltas can be settled (1) oracle version after they are recorded\\n     * @param self The struct to operate on\\n     * @param toOracleVersion The potential oracle version to settle\\n     * @return Whether the position delta can be settled\\n     */\\n    function canSettle(\\n        PrePosition memory self,\\n        IOracleProvider.OracleVersion memory toOracleVersion\\n    ) internal pure returns (bool) {\\n        return !isEmpty(self) && toOracleVersion.version > self.oracleVersion;\\n    }\\n\\n    /**\\n     * @notice Computes the fee incurred for opening or closing the pending-settlement position\\n     * @dev Must be called from a valid product to get the proper fee amounts\\n     * @param self The struct to operate on\\n     * @param toOracleVersion The oracle version at which settlement takes place\\n     * @return positionFee The maker / taker fee incurred\\n     */\\n    function computeFee(\\n        PrePosition memory self,\\n        IOracleProvider.OracleVersion memory toOracleVersion\\n    ) internal view returns (UFixed18) {\\n        Position memory positionDelta = self.openPosition.add(self.closePosition);\\n\\n        (UFixed18 makerNotional, UFixed18 takerNotional) = (\\n            Fixed18Lib.from(positionDelta.maker).mul(toOracleVersion.price).abs(),\\n            Fixed18Lib.from(positionDelta.taker).mul(toOracleVersion.price).abs()\\n        );\\n\\n        IProduct product = IProduct(address(this));\\n        return makerNotional.mul(product.makerFee()).add(takerNotional.mul(product.takerFee()));\\n    }\\n\\n    /**\\n     * @notice Computes the next oracle version to settle\\n     * @dev - If there is no pending-settlement position delta, returns the current oracle version\\n     *      - Otherwise returns the oracle version at which the pending-settlement position delta can be first settled\\n     *\\n     *      Corresponds to point (b) in the Position settlement flow\\n     * @param self The struct to operate on\\n     * @param currentVersion The current oracle version index\\n     * @return Next oracle version to settle\\n     */\\n    function settleVersion(PrePosition storage self, uint256 currentVersion) internal view returns (uint256) {\\n        uint256 _oracleVersion = self.oracleVersion;\\n        return _oracleVersion == 0 ? currentVersion : _oracleVersion + 1;\\n    }\\n}\\n\",\"keccak256\":\"0xa6f83f7b5f8139ec874235c406debd086a152977493c08b7f280df6f1737fb96\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/ProgramInfo.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"../IProduct.sol\\\";\\nimport \\\"./Position.sol\\\";\\nimport \\\"./Accumulator.sol\\\";\\n\\n/// @dev ProgramInfo type\\nstruct ProgramInfo {\\n    /// @dev Coordinator for this program\\n    uint256 coordinatorId;\\n\\n    /// @dev Amount of total maker and taker rewards\\n    Position amount;\\n\\n    /// @dev start timestamp of the program\\n    uint256 start;\\n\\n    /// @dev duration of the program (in seconds)\\n    uint256 duration;\\n\\n    /**\\n     * @dev Reward ERC20 token contract\\n     * @notice Perennial does not support non-standard ERC20s as reward tokens for incentive programs, including,\\n                but not limited to: fee on transfer and rebase tokens. Using such a non-standard token will likely\\n                result in loss of funds.\\n     */\\n    Token18 token;\\n}\\nusing ProgramInfoLib for ProgramInfo global;\\n\\n/**\\n * @title ProgramInfoLib\\n * @notice Library that snapshots the static information for a single program.\\n * @dev This information does not change during the operation of a program.\\n */\\nlibrary ProgramInfoLib {\\n    uint256 private constant MIN_DURATION = 1 days;\\n    uint256 private constant MAX_DURATION = 2 * 365 days;\\n\\n    error ProgramInvalidStartError();\\n    error ProgramInvalidDurationError();\\n\\n    /**\\n     * @notice Validates and creates a new Program\\n     * @dev Reverts for invalid programInfos\\n     * @param programInfo Un-sanitized static program information\\n     */\\n    function validate(ProgramInfo memory programInfo) internal view {\\n        if (isStarted(programInfo, block.timestamp)) revert ProgramInvalidStartError();\\n        if (programInfo.duration < MIN_DURATION || programInfo.duration > MAX_DURATION) revert ProgramInvalidDurationError();\\n    }\\n\\n    /**\\n     * @notice Computes a new program info with the fee taken out of the amount\\n     * @param programInfo Original program info\\n     * @param incentivizationFee The incentivization fee\\n     * @return New program info\\n     * @return Fee amount\\n     */\\n    function deductFee(ProgramInfo memory programInfo, UFixed18 incentivizationFee)\\n    internal pure returns (ProgramInfo memory, UFixed18) {\\n        Position memory newProgramAmount = programInfo.amount.mul(UFixed18Lib.ONE.sub(incentivizationFee));\\n        UFixed18 programFeeAmount = programInfo.amount.sub(newProgramAmount).sum();\\n        programInfo.amount = newProgramAmount;\\n        return (programInfo, programFeeAmount);\\n    }\\n\\n    /**\\n     * @notice Returns the maker and taker amounts per position share\\n     * @param self The ProgramInfo to operate on\\n     * @return programFee Amounts per share\\n     */\\n    function amountPerShare(ProgramInfo memory self) internal pure returns (Accumulator memory) {\\n        return self.amount.div(self.duration);\\n    }\\n\\n    /**\\n     * @notice Returns whether the program has started by timestamp `timestamp`\\n     * @param self The ProgramInfo to operate on\\n     * @param timestamp Timestamp to check for\\n     * @return Whether the program has started\\n     */\\n    function isStarted(ProgramInfo memory self, uint256 timestamp) internal pure returns (bool) {\\n        return timestamp >= self.start;\\n    }\\n\\n    /**\\n     * @notice Returns whether the program is completed by timestamp `timestamp`\\n     * @param self The ProgramInfo to operate on\\n     * @param timestamp Timestamp to check for\\n     * @return Whether the program is completed\\n     */\\n    function isComplete(ProgramInfo memory self, uint256 timestamp) internal pure returns (bool) {\\n        return timestamp >= (self.start + self.duration);\\n    }\\n}\\n\",\"keccak256\":\"0x280fcaf931b49abaec46b95ccbabaaf856a4b8e8d036413c9c3b3af25585d161\",\"license\":\"Apache-2.0\"}},\"version\":1}",
  "bytecode": "0x6101006040523480156200001257600080fd5b50604051620012ba380380620012ba83398101604081905262000035916200058a565b6200004b846200017160201b6200034b1760201c565b620000695760405163e5df3e0960e01b815260040160405180910390fd5b6200007f836200017160201b6200034b1760201c565b6200009d5760405163e5df3e0960e01b815260040160405180910390fd5b620000b3826200017160201b6200034b1760201c565b620000d15760405163e5df3e0960e01b815260040160405180910390fd5b620000e7816200017160201b6200034b1760201c565b620001055760405163e5df3e0960e01b815260040160405180910390fd5b6001600160a01b03848116608081905284821660a05283821660c081905291831660e052620001409162000180602090811b6200036717901c565b6200016760e05160a0516001600160a01b03166200018060201b620003671790919060201c565b50505050620006b6565b6001600160a01b03163b151590565b620001a781600019846001600160a01b0316620001ab60201b620003ac179092919060201c565b5050565b801580620002295750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801562000201573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002279190620005f2565b155b620002a15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620002f9918591620002fe16565b505050565b60006200035a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620003dc60201b620005b6179092919060201c565b805190915015620002f957808060200190518101906200037b91906200060c565b620002f95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000298565b6060620003ed8484600085620003f7565b90505b9392505050565b6060824710156200045a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000298565b6001600160a01b0385163b620004b35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000298565b600080866001600160a01b03168587604051620004d1919062000663565b60006040518083038185875af1925050503d806000811462000510576040519150601f19603f3d011682016040523d82523d6000602084013e62000515565b606091505b5090925090506200052882828662000533565b979650505050505050565b6060831562000544575081620003f0565b825115620005555782518084602001fd5b8160405162461bcd60e51b815260040162000298919062000681565b6001600160a01b03811681146200058757600080fd5b50565b60008060008060808587031215620005a157600080fd5b8451620005ae8162000571565b6020860151909450620005c18162000571565b6040860151909350620005d48162000571565b6060860151909250620005e78162000571565b939692955090935050565b6000602082840312156200060557600080fd5b5051919050565b6000602082840312156200061f57600080fd5b81518015158114620003f057600080fd5b60005b838110156200064d57818101518382015260200162000633565b838111156200065d576000848401525b50505050565b600082516200067781846020870162000630565b9190910192915050565b6020815260008251806020840152620006a281604085016020870162000630565b601f01601f19169190910160400192915050565b60805160a05160c05160e051610bb862000702600039600081816101240152610281015260008181607101526101be0152600060fd01526000818160d601526101600152610bb86000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806389a302711161005057806389a30271146100d1578063a2060bcf146100f8578063d8dfeb451461011f57600080fd5b8063025a3a291461006c57806344bc170a146100bc575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100cf6100ca3660046109d7565b610146565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b61018973ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016338360016105cf565b6040517f13bac820000000000000000000000000000000000000000000000000000000008152600481018290523060248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906313bac82090604401600060405180830381600087803b15801561021757600080fd5b505af115801561022b573d6000803e3d6000fd5b50506040517ff213159c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301528581166024830152604482018590527f000000000000000000000000000000000000000000000000000000000000000016925063f213159c9150606401600060405180830381600087803b1580156102c757600080fd5b505af11580156102db573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8e7ce60e353ab1a4cc59ca4782bdc69e0565713d1824dce27e0de2e362147ed08360405161033e91815260200190565b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6103a873ffffffffffffffffffffffffffffffffffffffff8316827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6103ac565b5050565b80158061044c57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015610426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044a9190610a18565b155b6104dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526105b19084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610603565b505050565b60606105c5848460008561070f565b90505b9392505050565b6105fd83306105de85856108a5565b73ffffffffffffffffffffffffffffffffffffffff88169291906108cf565b50505050565b6000610665826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166105b69092919063ffffffff16565b8051909150156105b157808060200190518101906106839190610a31565b6105b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016104d4565b6060824710156107a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016104d4565b73ffffffffffffffffffffffffffffffffffffffff85163b61081f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104d4565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516108489190610a7f565b60006040518083038185875af1925050503d8060008114610885576040519150601f19603f3d011682016040523d82523d6000602084013e61088a565b606091505b509150915061089a82828661092d565b979650505050505050565b6000816108c0576108bb64e8d4a5100084610aca565b6105c8565b6105c88364e8d4a51000610980565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105fd9085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161052f565b6060831561093c5750816105c8565b82511561094c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d49190610ade565b600061098c8284610b2f565b1561099857600161099b565b60005b60ff166109a88385610aca565b6105c89190610b43565b73ffffffffffffffffffffffffffffffffffffffff811681146109d457600080fd5b50565b6000806000606084860312156109ec57600080fd5b83356109f7816109b2565b92506020840135610a07816109b2565b929592945050506040919091013590565b600060208284031215610a2a57600080fd5b5051919050565b600060208284031215610a4357600080fd5b815180151581146105c857600080fd5b60005b83811015610a6e578181015183820152602001610a56565b838111156105fd5750506000910152565b60008251610a91818460208701610a53565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610ad957610ad9610a9b565b500490565b6020815260008251806020840152610afd816040850160208701610a53565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600082610b3e57610b3e610a9b565b500690565b60008219821115610b7d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea2646970667358221220ec9c4186939b8bfc3bd6ef92257a35503ebc51f749f10b706ec9c0022f7b049664736f6c634300080f0033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c806389a302711161005057806389a30271146100d1578063a2060bcf146100f8578063d8dfeb451461011f57600080fd5b8063025a3a291461006c57806344bc170a146100bc575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100cf6100ca3660046109d7565b610146565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b61018973ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016338360016105cf565b6040517f13bac820000000000000000000000000000000000000000000000000000000008152600481018290523060248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906313bac82090604401600060405180830381600087803b15801561021757600080fd5b505af115801561022b573d6000803e3d6000fd5b50506040517ff213159c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301528581166024830152604482018590527f000000000000000000000000000000000000000000000000000000000000000016925063f213159c9150606401600060405180830381600087803b1580156102c757600080fd5b505af11580156102db573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8e7ce60e353ab1a4cc59ca4782bdc69e0565713d1824dce27e0de2e362147ed08360405161033e91815260200190565b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6103a873ffffffffffffffffffffffffffffffffffffffff8316827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6103ac565b5050565b80158061044c57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015610426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044a9190610a18565b155b6104dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526105b19084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610603565b505050565b60606105c5848460008561070f565b90505b9392505050565b6105fd83306105de85856108a5565b73ffffffffffffffffffffffffffffffffffffffff88169291906108cf565b50505050565b6000610665826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166105b69092919063ffffffff16565b8051909150156105b157808060200190518101906106839190610a31565b6105b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016104d4565b6060824710156107a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016104d4565b73ffffffffffffffffffffffffffffffffffffffff85163b61081f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104d4565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516108489190610a7f565b60006040518083038185875af1925050503d8060008114610885576040519150601f19603f3d011682016040523d82523d6000602084013e61088a565b606091505b509150915061089a82828661092d565b979650505050505050565b6000816108c0576108bb64e8d4a5100084610aca565b6105c8565b6105c88364e8d4a51000610980565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105fd9085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161052f565b6060831561093c5750816105c8565b82511561094c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d49190610ade565b600061098c8284610b2f565b1561099857600161099b565b60005b60ff166109a88385610aca565b6105c89190610b43565b73ffffffffffffffffffffffffffffffffffffffff811681146109d457600080fd5b50565b6000806000606084860312156109ec57600080fd5b83356109f7816109b2565b92506020840135610a07816109b2565b929592945050506040919091013590565b600060208284031215610a2a57600080fd5b5051919050565b600060208284031215610a4357600080fd5b815180151581146105c857600080fd5b60005b83811015610a6e578181015183820152602001610a56565b838111156105fd5750506000910152565b60008251610a91818460208701610a53565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610ad957610ad9610a9b565b500490565b6020815260008251806020840152610afd816040850160208701610a53565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600082610b3e57610b3e610a9b565b500690565b60008219821115610b7d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea2646970667358221220ec9c4186939b8bfc3bd6ef92257a35503ebc51f749f10b706ec9c0022f7b049664736f6c634300080f0033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "constructor": {
        "params": {
          "batcher_": "The USDC-to-DSU batcher contract address",
          "collateral_": "The perennial collateral contract address",
          "dsu_": "The DSU token contract address",
          "usdc_": "The USDC token contract address"
        }
      },
      "wrapAndDeposit(address,address,uint256)": {
        "params": {
          "account": "Account to deposit the collateral for",
          "amount": "18 decimals-normalized stablecoin (USDC, DSU) value of collateral to deposit",
          "product": "Product to credit the collateral to"
        }
      }
    },
    "stateVariables": {
      "batcher": {
        "details": "Contract that wraps USDC to DSU"
      },
      "collateral": {
        "details": "Contract managing state for collateral accounts in the protocol"
      }
    },
    "title": "Forwarder",
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "constructor": {
        "notice": "Initializes the contract state"
      },
      "wrapAndDeposit(address,address,uint256)": {
        "notice": "Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU, and deposits it as collateral to `account`'s `product` account"
      }
    },
    "notice": "Facilitates collateral deposits to the protocol where the amount is supplied         in USDC then wrapped as DSU before being deposited.",
    "version": 1
  },
  "storageLayout": {
    "storage": [],
    "types": null
  }
}
