{
  "address": "0x0818E46C726810c2f7a1C513D0637a862bc0df6F",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "Token6",
          "name": "usdc_",
          "type": "address"
        },
        {
          "internalType": "contract IBatcher",
          "name": "batcher_",
          "type": "address"
        },
        {
          "internalType": "contract IEmptySetReserve",
          "name": "reserve_",
          "type": "address"
        },
        {
          "internalType": "contract IController",
          "name": "controller_",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "version",
          "type": "uint256"
        }
      ],
      "name": "UInitializableAlreadyInitializedError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "UInitializableNotInitializingError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "UInitializableZeroVersionError",
      "type": "error"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "version",
          "type": "uint256"
        }
      ],
      "name": "Initialized",
      "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": [],
      "name": "controller",
      "outputs": [
        {
          "internalType": "contract IController",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "initialize",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "enum IMultiInvoker.PerennialAction",
              "name": "action",
              "type": "uint8"
            },
            {
              "internalType": "bytes",
              "name": "args",
              "type": "bytes"
            }
          ],
          "internalType": "struct IMultiInvoker.Invocation[]",
          "name": "invocations",
          "type": "tuple[]"
        }
      ],
      "name": "invoke",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "reserve",
      "outputs": [
        {
          "internalType": "contract IEmptySetReserve",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "transactionHash": "0x07b19ac69f968040ca56413d3a461736058a293e79a3212b12aa93cd0420c207",
  "receipt": {
    "to": null,
    "from": "0x66a7fDB96C583c59597de16d8b2B989231415339",
    "contractAddress": "0x0818E46C726810c2f7a1C513D0637a862bc0df6F",
    "transactionIndex": 0,
    "gasUsed": "2029842",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x0bd9c1446a700a4bd806625ba79b171fbfa2c6a81d244aa7f6bf53ab35710718",
    "transactionHash": "0x07b19ac69f968040ca56413d3a461736058a293e79a3212b12aa93cd0420c207",
    "logs": [],
    "blockNumber": 4020123,
    "cumulativeGasUsed": "2029842",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0xf1485Aa729DF94083ab61B2C65EeA99894Aabdb3",
    "0x0000000000000000000000000000000000000000",
    "0xC5e9Ef91DC7E1D99bd44F9690FF0B982cAf846B9",
    "0xB5585A0cAac9f384A6Db545e89d0AC58215DBeFb"
  ],
  "numDeployments": 1,
  "solcInputHash": "0954eb4c5a9afab2c0aa2d884eb92458",
  "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"Token6\",\"name\":\"usdc_\",\"type\":\"address\"},{\"internalType\":\"contract IBatcher\",\"name\":\"batcher_\",\"type\":\"address\"},{\"internalType\":\"contract IEmptySetReserve\",\"name\":\"reserve_\",\"type\":\"address\"},{\"internalType\":\"contract IController\",\"name\":\"controller_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"UInitializableAlreadyInitializedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UInitializableNotInitializingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UInitializableZeroVersionError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"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\":[],\"name\":\"controller\",\"outputs\":[{\"internalType\":\"contract IController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"enum IMultiInvoker.PerennialAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"args\",\"type\":\"bytes\"}],\"internalType\":\"struct IMultiInvoker.Invocation[]\",\"name\":\"invocations\",\"type\":\"tuple[]\"}],\"name\":\"invoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"reserve\",\"outputs\":[{\"internalType\":\"contract IEmptySetReserve\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Called at implementation instantiate and constant for that implementation.\",\"params\":{\"batcher_\":\"Protocol Batcher address\",\"controller_\":\"Protocol Controller address\",\"reserve_\":\"EmptySet Reserve address\",\"usdc_\":\"USDC stablecoin address\"}},\"initialize()\":{\"details\":\"Must be called atomically as part of the upgradeable proxy deployment to      avoid front-running\"},\"invoke((uint8,bytes)[])\":{\"params\":{\"invocations\":\"The list of invocations to execute in order\"}}},\"stateVariables\":{\"DSU\":{\"details\":\"DSU address\"},\"USDC\":{\"details\":\"USDC stablecoin address\"},\"batcher\":{\"details\":\"Batcher address\"},\"collateral\":{\"details\":\"Collateral address\"},\"controller\":{\"details\":\"Controller address\"},\"reserve\":{\"details\":\"Reserve address\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Initializes the immutable contract state\"},\"initialize()\":{\"notice\":\"Initializes the contract state\"},\"invoke((uint8,bytes)[])\":{\"notice\":\"Executes a list of invocations in order\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/multiinvoker/MultiInvoker.sol\":\"MultiInvoker\"},\"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\\\";\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"@equilibria/root/token/types/Token6.sol\\\";\\nimport \\\"../interfaces/IEmptySetReserve.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 RESERVE() external view returns (IEmptySetReserve); // solhint-disable-line func-name-mixedcase\\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 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\":\"0xb9c0b0fc0dfcd44492b029ede04d304f6906b030cb925dc0fc2579e8c58d9734\",\"license\":\"Apache-2.0\"},\"@equilibria/emptyset-batcher/interfaces/IEmptySetReserve.sol\":{\"content\":\"//SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\n\\ninterface IEmptySetReserve {\\n    event Redeem(address indexed account, uint256 costAmount, uint256 redeemAmount);\\n    event Mint(address indexed account, uint256 mintAmount, uint256 costAmount);\\n    event Repay(address indexed account, uint256 repayAmount);\\n\\n    function debt(address borrower) external view returns (UFixed18);\\n    function repay(address borrower, UFixed18 amount) external;\\n    function mint(UFixed18 amount) external;\\n    function redeem(UFixed18 amount) external;\\n}\\n\",\"keccak256\":\"0xdb96e26082a471c7803e892ecd8d2877f23cd9e31f13a3e407dd5f8909078864\",\"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 Error for invalid oracle round\\n    error InvalidOracleRound();\\n\\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\":\"0x11e8ebb40917dcce08a6366e6fa8d25b037552d4ea66b96c13e6f45b1f817c52\",\"license\":\"Apache-2.0\"},\"@equilibria/root/control/unstructured/UInitializable.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"../../storage/UStorage.sol\\\";\\n\\n/**\\n * @title UInitializable\\n * @notice Library to manage the initialization lifecycle of upgradeable contracts\\n * @dev `UInitializable` allows the creation of pseudo-constructors for upgradeable contracts. One\\n *      `initializer` should be declared per top-level contract. Child contracts can use the `onlyInitializer`\\n *      modifier to tag their internal initialization functions to ensure that they can only be called\\n *      from a top-level `initializer` or a constructor.\\n */\\nabstract contract UInitializable {\\n    error UInitializableZeroVersionError();\\n    error UInitializableAlreadyInitializedError(uint256 version);\\n    error UInitializableNotInitializingError();\\n\\n    event Initialized(uint256 version);\\n\\n    /// @dev The initialized flag\\n    Uint256Storage private constant _version = Uint256Storage.wrap(keccak256(\\\"equilibria.root.UInitializable.version\\\"));\\n\\n    /// @dev The initializing flag\\n    BoolStorage private constant _initializing = BoolStorage.wrap(keccak256(\\\"equilibria.root.UInitializable.initializing\\\"));\\n\\n    /// @dev Can only be called once per version, `version` is 1-indexed\\n    modifier initializer(uint256 version) {\\n        if (version == 0) revert UInitializableZeroVersionError();\\n        if (_version.read() >= version) revert UInitializableAlreadyInitializedError(version);\\n\\n        _version.store(version);\\n        _initializing.store(true);\\n\\n        _;\\n\\n        _initializing.store(false);\\n        emit Initialized(version);\\n    }\\n\\n    /// @dev Can only be called from an initializer or constructor\\n    modifier onlyInitializer() {\\n        if (!_constructing() && !_initializing.read()) revert UInitializableNotInitializingError();\\n        _;\\n    }\\n\\n    /**\\n     * @notice Returns whether the contract is currently being constructed\\n     * @dev {Address.isContract} returns false for contracts currently in the process of being constructed\\n     * @return Whether the contract is currently being constructed\\n     */\\n    function _constructing() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\",\"keccak256\":\"0xd2743d8fcc220ed2ccdc0bba1db0a3e107741bd5c0cac47ca8c0b5a00ba2fd7f\",\"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/storage/UStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"../number/types/UFixed18.sol\\\";\\n\\n/// @dev Stored boolean slot\\ntype BoolStorage is bytes32;\\nusing BoolStorageLib for BoolStorage global;\\n\\n/// @dev Stored uint256 slot\\ntype Uint256Storage is bytes32;\\nusing Uint256StorageLib for Uint256Storage global;\\n\\n/// @dev Stored int256 slot\\ntype Int256Storage is bytes32;\\nusing Int256StorageLib for Int256Storage global;\\n\\n/// @dev Stored address slot\\ntype AddressStorage is bytes32;\\nusing AddressStorageLib for AddressStorage global;\\n\\n/// @dev Stored bytes32 slot\\ntype Bytes32Storage is bytes32;\\nusing Bytes32StorageLib for Bytes32Storage global;\\n\\n/**\\n * @title BoolStorageLib\\n * @notice Library to manage storage and retrival of a boolean at a fixed storage slot\\n */\\nlibrary BoolStorageLib {\\n    /**\\n     * @notice Retrieves the stored value\\n     * @param self Storage slot\\n     * @return value Stored bool value\\n     */\\n    function read(BoolStorage self) internal view returns (bool value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    /**\\n     * @notice Stores the value at the specific slot\\n     * @param self Storage slot\\n     * @param value boolean value to store\\n     */\\n    function store(BoolStorage self, bool value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\\n/**\\n * @title Uint256StorageLib\\n * @notice Library to manage storage and retrival of an uint256 at a fixed storage slot\\n */\\nlibrary Uint256StorageLib {\\n    /**\\n     * @notice Retrieves the stored value\\n     * @param self Storage slot\\n     * @return value Stored uint256 value\\n     */\\n    function read(Uint256Storage self) internal view returns (uint256 value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    /**\\n     * @notice Stores the value at the specific slot\\n     * @param self Storage slot\\n     * @param value uint256 value to store\\n     */\\n    function store(Uint256Storage self, uint256 value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\\n/**\\n * @title Int256StorageLib\\n * @notice Library to manage storage and retrival of an int256 at a fixed storage slot\\n */\\nlibrary Int256StorageLib {\\n    /**\\n     * @notice Retrieves the stored value\\n     * @param self Storage slot\\n     * @return value Stored int256 value\\n     */\\n    function read(Int256Storage self) internal view returns (int256 value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    /**\\n     * @notice Stores the value at the specific slot\\n     * @param self Storage slot\\n     * @param value int256 value to store\\n     */\\n    function store(Int256Storage self, int256 value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\\n/**\\n * @title AddressStorageLib\\n * @notice Library to manage storage and retrival of an address at a fixed storage slot\\n */\\nlibrary AddressStorageLib {\\n    /**\\n     * @notice Retrieves the stored value\\n     * @param self Storage slot\\n     * @return value Stored address value\\n     */\\n    function read(AddressStorage self) internal view returns (address value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    /**\\n     * @notice Stores the value at the specific slot\\n     * @param self Storage slot\\n     * @param value address value to store\\n     */\\n    function store(AddressStorage self, address value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\\n/**\\n * @title Bytes32StorageLib\\n * @notice Library to manage storage and retrival of a bytes32 at a fixed storage slot\\n */\\nlibrary Bytes32StorageLib {\\n    /**\\n     * @notice Retrieves the stored value\\n     * @param self Storage slot\\n     * @return value Stored bytes32 value\\n     */\\n    function read(Bytes32Storage self) internal view returns (bytes32 value) {\\n        assembly {\\n            value := sload(self)\\n        }\\n    }\\n\\n    /**\\n     * @notice Stores the value at the specific slot\\n     * @param self Storage slot\\n     * @param value bytes32 value to store\\n     */\\n    function store(Bytes32Storage self, bytes32 value) internal {\\n        assembly {\\n            sstore(self, value)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xe2b8491d1b5aa93f7e059e1a8f156b0ab37fef9ed973be97a64f2eabfc2cc172\",\"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/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    error CollateralAccountLiquidatingError(address account);\\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 receiver, IProduct product, UFixed18 amount) external;\\n    function withdrawFrom(address account, address receiver, 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\":\"0x6fb67eb5fc3ed4a74522677da3349d75105389369892756a60fcab4c901d352b\",\"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 \\\"./IMultiInvoker.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 MultiInvokerUpdated(IMultiInvoker newMultiInvoker);\\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 multiInvoker() external view returns (IMultiInvoker);\\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 updateMultiInvoker(IMultiInvoker newMultiInvoker) 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\":\"0xb6798b45b76edb91f6e56380eeeacdcfb37bbeb620a2d9c3e9993c39675bbd48\",\"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 claimFor(address account, 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\":\"0xd9d65d1190d830c8b797829f94194db86bb712e51f404e8c3e2c9b1df5645649\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMultiInvoker.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/token/types/Token6.sol\\\";\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\\\";\\nimport \\\"@equilibria/emptyset-batcher/interfaces/IEmptySetReserve.sol\\\";\\n\\nimport \\\"./IController.sol\\\";\\nimport \\\"./ICollateral.sol\\\";\\nimport \\\"./IProduct.sol\\\";\\n\\ninterface IMultiInvoker {\\n    /// @dev Core protocol actions that can be composed\\n    enum PerennialAction {\\n        NO_OP,\\n        DEPOSIT,\\n        WITHDRAW,\\n        OPEN_TAKE,\\n        CLOSE_TAKE,\\n        OPEN_MAKE,\\n        CLOSE_MAKE,\\n        CLAIM,\\n        WRAP,\\n        UNWRAP,\\n        WRAP_AND_DEPOSIT,\\n        WITHDRAW_AND_UNWRAP\\n    }\\n\\n    /// @dev Struct for action invocation\\n    struct Invocation {\\n        PerennialAction action;\\n        bytes args;\\n    }\\n\\n    function initialize() external;\\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 controller() external view returns (IController);\\n    function collateral() external view returns (ICollateral);\\n    function reserve() external view returns (IEmptySetReserve);\\n    function invoke(Invocation[] calldata invocations) external;\\n}\\n\",\"keccak256\":\"0x80e035472b990b026888f326b4dcceb7526491607b61e50592ceb8d36cc99728\",\"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\\\";\\nimport \\\"./types/PendingFeeUpdates.sol\\\";\\n\\ninterface IParamProvider {\\n    event MaintenanceUpdated(UFixed18 newMaintenance, uint256 version);\\n    event FundingFeeUpdated(UFixed18 newFundingFee, uint256 version);\\n    event MakerFeeUpdated(UFixed18 newMakerFee, uint256 version);\\n    event PendingMakerFeeUpdated(UFixed18 newMakerFee);\\n    event TakerFeeUpdated(UFixed18 newTakerFee, uint256 version);\\n    event PendingTakerFeeUpdated(UFixed18 newTakerFee);\\n    event PositionFeeUpdated(UFixed18 newPositionFee, uint256 version);\\n    event PendingPositionFeeUpdated(UFixed18 newPositionFee);\\n    event MakerLimitUpdated(UFixed18 newMakerLimit, uint256 version);\\n    event JumpRateUtilizationCurveUpdated(\\n        JumpRateUtilizationCurve,\\n        uint256 version\\n    );\\n\\n    error ParamProviderInvalidParamValue();\\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 positionFee() external view returns (UFixed18);\\n    function updatePositionFee(UFixed18 newPositionFee) 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    function pendingFeeUpdates() external view returns (PendingFeeUpdates memory);\\n}\\n\",\"keccak256\":\"0x21584bd07296eb4e8bd6076fd20afad320e781c19c60b479c9340c69b0f37517\",\"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    event OracleUpdated(address newOracle, uint256 oracleVersion);\\n\\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\":\"0x803d22f7513c2c5186f77f6bc7cc34673ed762e40f106f9aef512eb9b57018af\",\"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 position fee share\\n        UFixed18 positionFee;\\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 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 openTakeFor(address account, UFixed18 amount) external;\\n    function closeTake(UFixed18 amount) external;\\n    function closeTakeFor(address account, UFixed18 amount) external;\\n    function openMake(UFixed18 amount) external;\\n    function openMakeFor(address account, UFixed18 amount) external;\\n    function closeMake(UFixed18 amount) external;\\n    function closeMakeFor(address account, 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    function updateOracle(IOracleProvider newOracle) external;\\n}\\n\",\"keccak256\":\"0x8e53ea97d8d59519adcbc2aa3600b5e51de1d59efec485a88eca8b574a35a00f\",\"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.13;\\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 } // solhint-disable-line no-inline-assembly\\n    }\\n}\\n\",\"keccak256\":\"0x99f9b5d5facba16885a375beac2a05129e7b23a8cceee048a7affd7f12a18a8f\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/PendingFeeUpdates.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\n\\n/// @dev PendingFeeUpdates type. Fees can be between 0 and 1 ** 10^18, so uint64 is sufficient\\nstruct PendingFeeUpdates {\\n    bool makerFeeUpdated;\\n    uint64 pendingMakerFee;\\n    bool takerFeeUpdated;\\n    uint64 pendingTakerFee;\\n    bool positionFeeUpdated;\\n    uint64 pendingPositionFee;\\n}\\nusing PendingFeeUpdatesLib for PendingFeeUpdates global;\\ntype PendingFeeUpdatesStorage is bytes32;\\nusing PendingFeeUpdatesStorageLib for PendingFeeUpdatesStorage global;\\n\\n/**\\n * @title PendingFeeUpdatesLib\\n * @dev Library that surfaces convenience functions for the PendingFeeUpdates type\\n * @notice Library for the PendingFeeUpdates type. Allows for setting and reading fee updates and clearing state\\n */\\nlibrary PendingFeeUpdatesLib {\\n    error PendingFeeUpdatesUnsupportedValue(UFixed18 value);\\n\\n    /**\\n     * @notice Updates the pending maker fee to `newMakerFee` and sets the `makerFeeUpdated` flag\\n     * @dev Reverts if `newMakerFee` is invalid\\n     * @param self PendingFeeUpdates struct\\n     * @param newMakerFee new maker fee value\\n     */\\n    function updateMakerFee(PendingFeeUpdates memory self, UFixed18 newMakerFee) internal pure {\\n        if (UFixed18.unwrap(newMakerFee) > type(uint64).max) revert PendingFeeUpdatesUnsupportedValue(newMakerFee);\\n        self.pendingMakerFee = uint64(UFixed18.unwrap(newMakerFee));\\n        self.makerFeeUpdated = true;\\n    }\\n\\n    /// @dev Returns the UFixed18-wrapped pending maker fee\\n    function makerFee(PendingFeeUpdates memory self) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(uint256(self.pendingMakerFee));\\n    }\\n\\n    /**\\n     * @notice Updates the pending taker fee to `newTakerFee` and sets the `takerFeeUpdated` flag\\n     * @dev Reverts if `newTakerFee` is invalid\\n     * @param self PendingFeeUpdates struct\\n     * @param newTakerFee new taker fee value\\n     */\\n    function updateTakerFee(PendingFeeUpdates memory self, UFixed18 newTakerFee) internal pure {\\n        if (UFixed18.unwrap(newTakerFee) > type(uint64).max) revert PendingFeeUpdatesUnsupportedValue(newTakerFee);\\n        self.pendingTakerFee = uint64(UFixed18.unwrap(newTakerFee));\\n        self.takerFeeUpdated = true;\\n    }\\n\\n    /// @dev Returns the UFixed18-wrapped pending taker fee\\n    function takerFee(PendingFeeUpdates memory self) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(uint256(self.pendingTakerFee));\\n    }\\n\\n    /**\\n     * @notice Updates the pending position fee to `newPositionFee` and sets the `positionFeeUpdated` flag\\n     * @dev Reverts if `newPositionFee` is invalid\\n     * @param self PendingFeeUpdates struct\\n     * @param newPositionFee new position fee value\\n     */\\n    function updatePositionFee(PendingFeeUpdates memory self, UFixed18 newPositionFee) internal pure {\\n        if (UFixed18.unwrap(newPositionFee) > type(uint64).max) revert PendingFeeUpdatesUnsupportedValue(newPositionFee);\\n        self.pendingPositionFee = uint64(UFixed18.unwrap(newPositionFee));\\n        self.positionFeeUpdated = true;\\n    }\\n\\n    /// @dev Returns the UFixed18-wrapped pending position fee\\n    function positionFee(PendingFeeUpdates memory self) internal pure returns (UFixed18) {\\n        return UFixed18.wrap(uint256(self.pendingPositionFee));\\n    }\\n\\n    /// @dev Returns true if any of the updated flags are true\\n    function hasUpdates(PendingFeeUpdates memory self) internal pure returns (bool) {\\n        return self.makerFeeUpdated || self.takerFeeUpdated || self.positionFeeUpdated;\\n    }\\n\\n    /// @dev Resets all struct values to defaults\\n    function clear(PendingFeeUpdates memory self) internal pure {\\n        self.makerFeeUpdated = false;\\n        self.pendingMakerFee = 0;\\n        self.takerFeeUpdated = false;\\n        self.pendingTakerFee = 0;\\n        self.positionFeeUpdated = false;\\n        self.pendingPositionFee = 0;\\n    }\\n}\\n\\n/**\\n * @title PendingFeeUpdatesStorageLib\\n * @notice Library that surfaces storage read and writes for the PendingFeeUpdates type\\n */\\nlibrary PendingFeeUpdatesStorageLib {\\n    struct PendingFeeUpdatesStoragePointer {\\n        PendingFeeUpdates value;\\n    }\\n\\n    function read(PendingFeeUpdatesStorage self) internal view returns (PendingFeeUpdates memory) {\\n        return _storagePointer(self).value;\\n    }\\n\\n    function store(PendingFeeUpdatesStorage self, PendingFeeUpdates memory value) internal {\\n        _storagePointer(self).value = value;\\n    }\\n\\n    function _storagePointer(\\n        PendingFeeUpdatesStorage self\\n    ) private pure returns (PendingFeeUpdatesStoragePointer storage pointer) {\\n        /// @solidity memory-safe-assembly\\n        assembly { pointer.slot := self } // solhint-disable-line no-inline-assembly\\n    }\\n}\\n\",\"keccak256\":\"0xd98c681bdd6e1808e311615b3c4ac3b557ce5ec461f7b1cc645a51590eaf6f93\",\"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 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 pure returns (Position memory, bool) {\\n        return pre.canSettle(toOracleVersion) ? (next(self, pre), true) : (self, 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\":\"0x367918730021f3d6b7035f40c53b00b4316eb5e7fa409ed6285ba6d49971aab1\",\"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     * @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     * @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    }\\n\\n    /**\\n     * @notice Increments the maker side of the close position delta\\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    }\\n\\n    /**\\n     * @notice Increments the taker side of the open position delta\\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    }\\n\\n    /**\\n     * @notice Increments the taker side of the close position delta\\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    }\\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 latestOracleVersion The oracle version at which position was modified\\n     * @return The maker / taker fee incurred\\n     */\\n    function computeFee(\\n        PrePosition memory self,\\n        IOracleProvider.OracleVersion memory latestOracleVersion\\n    ) internal view returns (Position memory) {\\n        Position memory positionDelta = self.openPosition.add(self.closePosition);\\n\\n        (UFixed18 makerNotional, UFixed18 takerNotional) = (\\n            Fixed18Lib.from(positionDelta.maker).mul(latestOracleVersion.price).abs(),\\n            Fixed18Lib.from(positionDelta.taker).mul(latestOracleVersion.price).abs()\\n        );\\n\\n        IProduct product = IProduct(address(this));\\n        return Position(makerNotional.mul(product.makerFee()), 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\":\"0x4d4443c34648f0352ed7c26ce8b837b6c7613169e53e95d92c8c59ee9e335692\",\"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\"},\"contracts/multiinvoker/MultiInvoker.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.15;\\n\\nimport \\\"@equilibria/root/control/unstructured/UInitializable.sol\\\";\\n\\nimport \\\"../interfaces/IMultiInvoker.sol\\\";\\n\\ncontract MultiInvoker is IMultiInvoker, UInitializable {\\n    /// @dev USDC stablecoin address\\n    Token6 public immutable USDC; // solhint-disable-line var-name-mixedcase\\n\\n    /// @dev DSU address\\n    Token18 public immutable DSU; // solhint-disable-line var-name-mixedcase\\n\\n    /// @dev Batcher address\\n    IBatcher public immutable batcher;\\n\\n    /// @dev Controller address\\n    IController public immutable controller;\\n\\n    /// @dev Collateral address\\n    ICollateral public immutable collateral;\\n\\n    /// @dev Reserve address\\n    IEmptySetReserve public immutable reserve;\\n\\n    /**\\n     * @notice Initializes the immutable contract state\\n     * @dev Called at implementation instantiate and constant for that implementation.\\n     * @param usdc_ USDC stablecoin address\\n     * @param batcher_ Protocol Batcher address\\n     * @param reserve_ EmptySet Reserve address\\n     * @param controller_ Protocol Controller address\\n     */\\n    constructor(Token6 usdc_, IBatcher batcher_, IEmptySetReserve reserve_, IController controller_) {\\n        USDC = usdc_;\\n        batcher = batcher_;\\n        controller = controller_;\\n        collateral = controller.collateral();\\n        DSU = collateral.token();\\n        reserve = reserve_;\\n    }\\n\\n    /**\\n     * @notice Initializes the contract state\\n     * @dev Must be called atomically as part of the upgradeable proxy deployment to\\n     *      avoid front-running\\n     */\\n    function initialize() external initializer(2) {\\n        if (address(batcher) != address(0)) {\\n            DSU.approve(address(batcher), UFixed18Lib.ZERO);\\n            DSU.approve(address(batcher));\\n            USDC.approve(address(batcher), UFixed18Lib.ZERO);\\n            USDC.approve(address(batcher));\\n        }\\n\\n        DSU.approve(address(collateral), UFixed18Lib.ZERO);\\n        DSU.approve(address(collateral));\\n\\n        DSU.approve(address(reserve), UFixed18Lib.ZERO);\\n        DSU.approve(address(reserve));\\n        USDC.approve(address(reserve), UFixed18Lib.ZERO);\\n        USDC.approve(address(reserve));\\n    }\\n\\n    /**\\n     * @notice Executes a list of invocations in order\\n     * @param invocations The list of invocations to execute in order\\n     */\\n    function invoke(Invocation[] calldata invocations) external {\\n        for (uint256 i = 0; i < invocations.length; i++) {\\n            Invocation memory invocation = invocations[i];\\n\\n            // Deposit from `msg.sender` into `account`s `product` collateral account\\n            if (invocation.action == PerennialAction.DEPOSIT) {\\n                (address account, IProduct product, UFixed18 amount) = abi.decode(invocation.args, (address, IProduct, UFixed18));\\n                depositTo(account, product, amount);\\n\\n            // Withdraw from `msg.sender`s `product` collateral account to `receiver`\\n            } else if (invocation.action == PerennialAction.WITHDRAW) {\\n                (address receiver, IProduct product, UFixed18 amount) = abi.decode(invocation.args, (address, IProduct, UFixed18));\\n                collateral.withdrawFrom(msg.sender, receiver, product, amount);\\n\\n            // Open a take position on behalf of `msg.sender`\\n            } else if (invocation.action == PerennialAction.OPEN_TAKE) {\\n                (IProduct product, UFixed18 amount) = abi.decode(invocation.args, (IProduct, UFixed18));\\n                product.openTakeFor(msg.sender, amount);\\n\\n            // Close a take position on behalf of `msg.sender`\\n            } else if (invocation.action == PerennialAction.CLOSE_TAKE) {\\n                (IProduct product, UFixed18 amount) = abi.decode(invocation.args, (IProduct, UFixed18));\\n                product.closeTakeFor(msg.sender, amount);\\n\\n            // Open a make position on behalf of `msg.sender`\\n            } else if (invocation.action == PerennialAction.OPEN_MAKE) {\\n                (IProduct product, UFixed18 amount) = abi.decode(invocation.args, (IProduct, UFixed18));\\n                product.openMakeFor(msg.sender, amount);\\n\\n            // Close a make position on behalf of `msg.sender`\\n            } else if (invocation.action == PerennialAction.CLOSE_MAKE) {\\n                (IProduct product, UFixed18 amount) = abi.decode(invocation.args, (IProduct, UFixed18));\\n                product.closeMakeFor(msg.sender, amount);\\n\\n            // Claim `msg.sender`s incentive reward for `product` programs\\n            } else if (invocation.action == PerennialAction.CLAIM) {\\n                (IProduct product, uint256[] memory programIds) = abi.decode(invocation.args, (IProduct, uint256[]));\\n                controller.incentivizer().claimFor(msg.sender, product, programIds);\\n\\n            // Wrap `msg.sender`s USDC into DSU and return the DSU to `account`\\n            } else if (invocation.action == PerennialAction.WRAP) {\\n                (address receiver, UFixed18 amount) = abi.decode(invocation.args, (address, UFixed18));\\n                wrap(receiver, amount);\\n\\n            // Unwrap `msg.sender`s DSU into USDC and return the USDC to `account`\\n            } else if (invocation.action == PerennialAction.UNWRAP) {\\n                (address receiver, UFixed18 amount) = abi.decode(invocation.args, (address, UFixed18));\\n                unwrap(receiver, amount);\\n\\n            // Wrap `msg.sender`s USDC into DSU and deposit into `account`s `product` collateral account\\n            } else if (invocation.action == PerennialAction.WRAP_AND_DEPOSIT) {\\n                (address account, IProduct product, UFixed18 amount) = abi.decode(invocation.args, (address, IProduct, UFixed18));\\n                wrapAndDeposit(account, product, amount);\\n            }\\n\\n            // Withdraw DSU from `msg.sender`s `product` collateral account, unwrap into USDC, and return the USDC to `receiver`\\n            else if (invocation.action == PerennialAction.WITHDRAW_AND_UNWRAP) {\\n                (address receiver, IProduct product, UFixed18 amount) = abi.decode(invocation.args, (address, IProduct, UFixed18));\\n                withdrawAndUnwrap(receiver, product, amount);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice Deposits `amount` DSU from `msg.sender` into `account`s `product` collateral account\\n     * @param account Account to deposit funds on behalf of\\n     * @param product Product to deposit funds for\\n     * @param amount Amount of DSU to deposit into the collateral account\\n     */\\n    function depositTo(address account, IProduct product, UFixed18 amount) private {\\n        // Pull the token from the `msg.sender`\\n        DSU.pull(msg.sender, amount);\\n\\n        // Deposit the amount to the collateral account\\n        collateral.depositTo(account, product, amount);\\n    }\\n\\n    /**\\n     * @notice Wraps `amount` USDC into DSU, pulling from `msg.sender` and sending to `receiver`\\n     * @param receiver Address to receive the DSU\\n     * @param amount Amount of USDC to wrap\\n     */\\n    function wrap(address receiver, UFixed18 amount) private {\\n        // Pull USDC from the `msg.sender`\\n        USDC.pull(msg.sender, amount, true);\\n\\n        _wrap(receiver, amount);\\n    }\\n\\n    /**\\n     * @notice Unwraps `amount` DSU into USDC, pulling from `msg.sender` and sending  to `receiver`\\n     * @param receiver Address to receive the USDC\\n     * @param amount Amount of DSU to unwrap\\n     */\\n    function unwrap(address receiver, UFixed18 amount) private {\\n        // Pull the token from the `msg.sender`\\n        DSU.pull(msg.sender, amount);\\n\\n        _unwrap(receiver, amount);\\n    }\\n\\n    /**\\n     * @notice Wraps `amount` USDC from `msg.sender` into DSU, then deposits the USDC into `account`s `product` collateral account\\n     * @param account Account to deposit funds on behalf of\\n     * @param product Product to deposit funds for\\n     * @param amount Amount of USDC to deposit into the collateral account\\n     */\\n    function wrapAndDeposit(address account, IProduct product, UFixed18 amount) private {\\n        // Pull USDC from the `msg.sender`\\n        USDC.pull(msg.sender, amount, true);\\n\\n        _wrap(address(this), amount);\\n\\n        // Deposit the amount to the collateral account\\n        collateral.depositTo(account, product, amount);\\n    }\\n\\n    /**\\n     * @notice Withdraws `amount` DSU from `msg.sender`s `product` collateral account, then unwraps the DSU into USDC and sends it to `receiver`\\n     * @param receiver Address to receive the USDC\\n     * @param product Product to withdraw funds for\\n     * @param amount Amount of DSU to withdraw from the collateral account\\n     */\\n    function withdrawAndUnwrap(address receiver, IProduct product, UFixed18 amount) private {\\n        // Withdraw the amount from the collateral account\\n        collateral.withdrawFrom(msg.sender, address(this), product, amount);\\n\\n        _unwrap(receiver, amount);\\n    }\\n\\n    /**\\n     * @notice Helper function to wrap `amount` USDC from `msg.sender` into DSU using the batcher or reserve\\n     * @param receiver Address to receive the DSU\\n     * @param amount Amount of USDC to wrap\\n     */\\n    function _wrap(address receiver, UFixed18 amount) private {\\n        // If the batcher is 0 or  doesn't have enough for this wrap, go directly to the reserve\\n        if (address(batcher) == address(0) || amount.gt(DSU.balanceOf(address(batcher)))) {\\n            reserve.mint(amount);\\n            if (receiver != address(this)) DSU.push(receiver, amount);\\n        } else {\\n            // Wrap the USDC into DSU and return to the receiver\\n            batcher.wrap(amount, receiver);\\n        }\\n    }\\n\\n    /**\\n     * @notice Helper function to unwrap `amount` DSU into USDC and send to `receiver`\\n     * @param receiver Address to receive the USDC\\n     * @param amount Amount of DSU to unwrap\\n     */\\n    function _unwrap(address receiver, UFixed18 amount) private {\\n        // If the batcher is 0 or doesn't have enough for this unwrap, go directly to the reserve\\n        if (address(batcher) == address(0) || amount.gt(USDC.balanceOf(address(batcher)))) {\\n            reserve.redeem(amount);\\n            if (receiver != address(this)) USDC.push(receiver, amount);\\n        } else {\\n            // Unwrap the DSU into USDC and return to the receiver\\n            batcher.unwrap(amount, receiver);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x7d1c5824eceed016f4aa161ec955e4f975eb506e35eb9ae5e351fdc0ef5bc980\",\"license\":\"BUSL-1.1\"}},\"version\":1}",
  "bytecode": "0x6101406040523480156200001257600080fd5b50604051620026e9380380620026e983398101604081905262000035916200015c565b6001600160a01b0380851660805283811660c052811660e08190526040805163d8dfeb4560e01b8152905163d8dfeb45916004808201926020929091908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b29190620001c4565b6001600160a01b031661010081905260408051637e062a3560e11b8152905163fc0c546a916004808201926020929091908290030181865afa158015620000fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001239190620001c4565b6001600160a01b0390811660a052919091166101205250620001eb915050565b6001600160a01b03811681146200015957600080fd5b50565b600080600080608085870312156200017357600080fd5b8451620001808162000143565b6020860151909450620001938162000143565b6040860151909350620001a68162000143565b6060860151909250620001b98162000143565b939692955090935050565b600060208284031215620001d757600080fd5b8151620001e48162000143565b9392505050565b60805160a05160c05160e0516101005161012051612391620003586000396000818161014d0152818161053201528181610594015281816105f401528181610656015281816113ad01526115fe01526000818161017401528181610470015281816104d2015281816107f901528181610e440152610fe201526000818161019b0152610b1b015260008181609201528181610276015281816102ec0152818161034e015281816103ae01528181610410015281816112d30152818161134e015281816114c80152818161152b015281816115a60152611719015260008181610113015281816102ca0152818161032c0152818161044e015281816104b0015281816105100152818161057201528181610dc901528181610f0c0152818161132c015261145501526000818160ec0152818161038c015281816103ee015281816105d20152818161063401528181610ebf01528181610f570152818161158401526116a601526123916000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063bdec4a271161005b578063bdec4a2714610135578063cd3293de14610148578063d8dfeb451461016f578063f77c47911461019657600080fd5b8063025a3a291461008d5780638129fc1c146100dd57806389a30271146100e7578063a2060bcf1461010e575b600080fd5b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100e56101bd565b005b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100e5610143366004611d16565b6106d4565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6002806101e87f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b5490565b10610227576040517f1e7a9d95000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b6102507f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b829055565b60017fad57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398c557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16156104345761031273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d1c565b61037273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b6103d473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d82565b61043473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b61049673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d1c565b6104f673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b61055873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d1c565b6105b873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b61061a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d82565b61067a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b60007fad57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398c556040518181527fbe9b076dc5b65990cca9dd9d7366682482e7817a6f6bc7f4faf4dc32af497f329060200160405180910390a150565b60005b81811015610d175760008383838181106106f3576106f3611d8b565b90506020028101906107059190611dba565b61070e90611e9f565b905060018151600b81111561072557610725611f6f565b0361076057600080600083602001518060200190518101906107479190611fc3565b925092509250610758838383610daf565b505050610d04565b60028151600b81111561077557610775611f6f565b0361085f57600080600083602001518060200190518101906107979190611fc3565b6040517f2644131800000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff848116602483015283811660448301526064820183905293965091945092507f000000000000000000000000000000000000000000000000000000000000000090911690632644131890608401600060405180830381600087803b15801561083f57600080fd5b505af1158015610853573d6000803e3d6000fd5b50505050505050610d04565b60038151600b81111561087457610874611f6f565b036109275760008082602001518060200190518101906108949190612006565b6040517f9378bf7b00000000000000000000000000000000000000000000000000000000815233600482015260248101829052919350915073ffffffffffffffffffffffffffffffffffffffff831690639378bf7b906044015b600060405180830381600087803b15801561090857600080fd5b505af115801561091c573d6000803e3d6000fd5b505050505050610d04565b60048151600b81111561093c5761093c611f6f565b036109ba57600080826020015180602001905181019061095c9190612006565b6040517f2131ea4a00000000000000000000000000000000000000000000000000000000815233600482015260248101829052919350915073ffffffffffffffffffffffffffffffffffffffff831690632131ea4a906044016108ee565b60058151600b8111156109cf576109cf611f6f565b03610a4d5760008082602001518060200190518101906109ef9190612006565b6040517f2d2e52be00000000000000000000000000000000000000000000000000000000815233600482015260248101829052919350915073ffffffffffffffffffffffffffffffffffffffff831690632d2e52be906044016108ee565b60068151600b811115610a6257610a62611f6f565b03610ae0576000808260200151806020019051810190610a829190612006565b6040517fe503b00700000000000000000000000000000000000000000000000000000000815233600482015260248101829052919350915073ffffffffffffffffffffffffffffffffffffffff83169063e503b007906044016108ee565b60078151600b811115610af557610af5611f6f565b03610be3576000808260200151806020019051810190610b159190612034565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636fc6407c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba891906120f1565b73ffffffffffffffffffffffffffffffffffffffff16628240533384846040518463ffffffff1660e01b81526004016108ee9392919061210e565b60088151600b811115610bf857610bf8611f6f565b03610c2d576000808260200151806020019051810190610c189190612006565b91509150610c268282610ea5565b5050610d04565b60098151600b811115610c4257610c42611f6f565b03610c70576000808260200151806020019051810190610c629190612006565b91509150610c268282610ef2565b600a8151600b811115610c8557610c85611f6f565b03610cb85760008060008360200151806020019051810190610ca79190611fc3565b925092509250610758838383610f3d565b600b8151600b811115610ccd57610ccd611f6f565b03610d045760008060008360200151806020019051810190610cef9190611fc3565b925092509250610d00838383610f8a565b5050505b5080610d0f816121ad565b9150506106d7565b505050565b610d1773ffffffffffffffffffffffffffffffffffffffff84168383611048565b610d7e73ffffffffffffffffffffffffffffffffffffffff8316827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611048565b5050565b610d1782610d91836000611248565b73ffffffffffffffffffffffffffffffffffffffff86169190611048565b610df073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016338361127b565b6040517ff213159c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301528381166024830152604482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f213159c90606401600060405180830381600087803b158015610e8857600080fd5b505af1158015610e9c573d6000803e3d6000fd5b50505050505050565b610ee873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383600161129d565b610d7e82826112d1565b610f3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016338361127b565b610d7e8282611529565b610f8073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383600161129d565b610df030826112d1565b6040517f2644131800000000000000000000000000000000000000000000000000000000815233600482015230602482015273ffffffffffffffffffffffffffffffffffffffff8381166044830152606482018390527f00000000000000000000000000000000000000000000000000000000000000001690632644131890608401600060405180830381600087803b15801561102657600080fd5b505af115801561103a573d6000803e3d6000fd5b50505050610d178382611529565b8015806110e857506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156110c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e691906121e5565b155b611174576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840161021e565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610d179084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611748565b6000816112635761125e64e8d4a510008461222d565b611272565b6112728364e8d4a51000611854565b90505b92915050565b610d1773ffffffffffffffffffffffffffffffffffffffff8416833084611886565b6112cb83306112ac8585611248565b73ffffffffffffffffffffffffffffffffffffffff8816929190611886565b50505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161580611379575061137961137273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006118e4565b8290611978565b1561147c576040517fa0712d68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a0712d6890602401600060405180830381600087803b15801561140657600080fd5b505af115801561141a573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff82163014610d7e57610d7e73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016838361198e565b6040517f13bac8200000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff83811660248301527f000000000000000000000000000000000000000000000000000000000000000016906313bac820906044015b600060405180830381600087803b15801561150d57600080fd5b505af1158015611521573d6000803e3d6000fd5b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1615806115ca57506115ca61137273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006119af565b156116cd576040517fdb006a75000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063db006a7590602401600060405180830381600087803b15801561165757600080fd5b505af115801561166b573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff82163014610d7e57610d7e73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168383611a4b565b6040517f7647691d0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff83811660248301527f00000000000000000000000000000000000000000000000000000000000000001690637647691d906044016114f3565b60006117aa826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611a789092919063ffffffff16565b805190915015610d1757808060200190518101906117c89190612241565b610d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161021e565b60006118608284612263565b1561186c57600161186f565b60005b60ff1661187c838561222d565b6112729190612277565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526112cb9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016111c6565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152600091908416906370a0823190602401602060405180830381865afa158015611954573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127291906121e5565b60006119848383611a91565b6002149392505050565b610d1773ffffffffffffffffffffffffffffffffffffffff84168383611ac6565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152600091611272918516906370a0823190602401602060405180830381865afa158015611a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4691906121e5565b611b1c565b610d1782611a5a836000611248565b73ffffffffffffffffffffffffffffffffffffffff86169190611ac6565b6060611a878484600085611b2d565b90505b9392505050565b6000828280821115611aa857600292505050611275565b80821015611abb57600092505050611275565b506001949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610d179084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016111c6565b600061127564e8d4a510008361228f565b606082471015611bbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161021e565b73ffffffffffffffffffffffffffffffffffffffff85163b611c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161021e565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611c6691906122f8565b60006040518083038185875af1925050503d8060008114611ca3576040519150601f19603f3d011682016040523d82523d6000602084013e611ca8565b606091505b5091509150611cb8828286611cc3565b979650505050505050565b60608315611cd2575081611a8a565b825115611ce25782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021e919061230a565b60008060208385031215611d2957600080fd5b823567ffffffffffffffff80821115611d4157600080fd5b818501915085601f830112611d5557600080fd5b813581811115611d6457600080fd5b8660208260051b8501011115611d7957600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611dee57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611e4a57611e4a611df8565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e9757611e97611df8565b604052919050565b600060408236031215611eb157600080fd5b611eb9611e27565b8235600c8110611ec857600080fd5b815260208381013567ffffffffffffffff80821115611ee657600080fd5b9085019036601f830112611ef957600080fd5b813581811115611f0b57611f0b611df8565b611f3b847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611e50565b91508082523684828501011115611f5157600080fd5b80848401858401376000908201840152918301919091525092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff81168114611fc057600080fd5b50565b600080600060608486031215611fd857600080fd5b8351611fe381611f9e565b6020850151909350611ff481611f9e565b80925050604084015190509250925092565b6000806040838503121561201957600080fd5b825161202481611f9e565b6020939093015192949293505050565b6000806040838503121561204757600080fd5b825161205281611f9e565b8092505060208084015167ffffffffffffffff8082111561207257600080fd5b818601915086601f83011261208657600080fd5b81518181111561209857612098611df8565b8060051b91506120a9848301611e50565b81815291830184019184810190898411156120c357600080fd5b938501935b838510156120e1578451825293850193908501906120c8565b8096505050505050509250929050565b60006020828403121561210357600080fd5b8151611a8a81611f9e565b60006060820173ffffffffffffffffffffffffffffffffffffffff8087168452602081871681860152606060408601528291508551808452608086019250818701935060005b8181101561217057845184529382019392820192600101612154565b509198975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121de576121de61217e565b5060010190565b6000602082840312156121f757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261223c5761223c6121fe565b500490565b60006020828403121561225357600080fd5b81518015158114611a8a57600080fd5b600082612272576122726121fe565b500690565b6000821982111561228a5761228a61217e565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156122c7576122c761217e565b500290565b60005b838110156122e75781810151838201526020016122cf565b838111156112cb5750506000910152565b60008251611dee8184602087016122cc565b60208152600082518060208401526123298160408501602087016122cc565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea264697066735822122061727f6801d5abe5d43296853dd91f7a018d3bb2c39ea20b014e388cfc0b741164736f6c634300080f0033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063bdec4a271161005b578063bdec4a2714610135578063cd3293de14610148578063d8dfeb451461016f578063f77c47911461019657600080fd5b8063025a3a291461008d5780638129fc1c146100dd57806389a30271146100e7578063a2060bcf1461010e575b600080fd5b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100e56101bd565b005b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100e5610143366004611d16565b6106d4565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6002806101e87f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b5490565b10610227576040517f1e7a9d95000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b6102507f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b829055565b60017fad57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398c557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16156104345761031273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d1c565b61037273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b6103d473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d82565b61043473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b61049673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d1c565b6104f673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b61055873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d1c565b6105b873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b61061a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006000610d82565b61067a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610d3d565b60007fad57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398c556040518181527fbe9b076dc5b65990cca9dd9d7366682482e7817a6f6bc7f4faf4dc32af497f329060200160405180910390a150565b60005b81811015610d175760008383838181106106f3576106f3611d8b565b90506020028101906107059190611dba565b61070e90611e9f565b905060018151600b81111561072557610725611f6f565b0361076057600080600083602001518060200190518101906107479190611fc3565b925092509250610758838383610daf565b505050610d04565b60028151600b81111561077557610775611f6f565b0361085f57600080600083602001518060200190518101906107979190611fc3565b6040517f2644131800000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff848116602483015283811660448301526064820183905293965091945092507f000000000000000000000000000000000000000000000000000000000000000090911690632644131890608401600060405180830381600087803b15801561083f57600080fd5b505af1158015610853573d6000803e3d6000fd5b50505050505050610d04565b60038151600b81111561087457610874611f6f565b036109275760008082602001518060200190518101906108949190612006565b6040517f9378bf7b00000000000000000000000000000000000000000000000000000000815233600482015260248101829052919350915073ffffffffffffffffffffffffffffffffffffffff831690639378bf7b906044015b600060405180830381600087803b15801561090857600080fd5b505af115801561091c573d6000803e3d6000fd5b505050505050610d04565b60048151600b81111561093c5761093c611f6f565b036109ba57600080826020015180602001905181019061095c9190612006565b6040517f2131ea4a00000000000000000000000000000000000000000000000000000000815233600482015260248101829052919350915073ffffffffffffffffffffffffffffffffffffffff831690632131ea4a906044016108ee565b60058151600b8111156109cf576109cf611f6f565b03610a4d5760008082602001518060200190518101906109ef9190612006565b6040517f2d2e52be00000000000000000000000000000000000000000000000000000000815233600482015260248101829052919350915073ffffffffffffffffffffffffffffffffffffffff831690632d2e52be906044016108ee565b60068151600b811115610a6257610a62611f6f565b03610ae0576000808260200151806020019051810190610a829190612006565b6040517fe503b00700000000000000000000000000000000000000000000000000000000815233600482015260248101829052919350915073ffffffffffffffffffffffffffffffffffffffff83169063e503b007906044016108ee565b60078151600b811115610af557610af5611f6f565b03610be3576000808260200151806020019051810190610b159190612034565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636fc6407c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba891906120f1565b73ffffffffffffffffffffffffffffffffffffffff16628240533384846040518463ffffffff1660e01b81526004016108ee9392919061210e565b60088151600b811115610bf857610bf8611f6f565b03610c2d576000808260200151806020019051810190610c189190612006565b91509150610c268282610ea5565b5050610d04565b60098151600b811115610c4257610c42611f6f565b03610c70576000808260200151806020019051810190610c629190612006565b91509150610c268282610ef2565b600a8151600b811115610c8557610c85611f6f565b03610cb85760008060008360200151806020019051810190610ca79190611fc3565b925092509250610758838383610f3d565b600b8151600b811115610ccd57610ccd611f6f565b03610d045760008060008360200151806020019051810190610cef9190611fc3565b925092509250610d00838383610f8a565b5050505b5080610d0f816121ad565b9150506106d7565b505050565b610d1773ffffffffffffffffffffffffffffffffffffffff84168383611048565b610d7e73ffffffffffffffffffffffffffffffffffffffff8316827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611048565b5050565b610d1782610d91836000611248565b73ffffffffffffffffffffffffffffffffffffffff86169190611048565b610df073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016338361127b565b6040517ff213159c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301528381166024830152604482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f213159c90606401600060405180830381600087803b158015610e8857600080fd5b505af1158015610e9c573d6000803e3d6000fd5b50505050505050565b610ee873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383600161129d565b610d7e82826112d1565b610f3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016338361127b565b610d7e8282611529565b610f8073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383600161129d565b610df030826112d1565b6040517f2644131800000000000000000000000000000000000000000000000000000000815233600482015230602482015273ffffffffffffffffffffffffffffffffffffffff8381166044830152606482018390527f00000000000000000000000000000000000000000000000000000000000000001690632644131890608401600060405180830381600087803b15801561102657600080fd5b505af115801561103a573d6000803e3d6000fd5b50505050610d178382611529565b8015806110e857506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156110c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e691906121e5565b155b611174576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840161021e565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610d179084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611748565b6000816112635761125e64e8d4a510008461222d565b611272565b6112728364e8d4a51000611854565b90505b92915050565b610d1773ffffffffffffffffffffffffffffffffffffffff8416833084611886565b6112cb83306112ac8585611248565b73ffffffffffffffffffffffffffffffffffffffff8816929190611886565b50505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161580611379575061137961137273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006118e4565b8290611978565b1561147c576040517fa0712d68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a0712d6890602401600060405180830381600087803b15801561140657600080fd5b505af115801561141a573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff82163014610d7e57610d7e73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016838361198e565b6040517f13bac8200000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff83811660248301527f000000000000000000000000000000000000000000000000000000000000000016906313bac820906044015b600060405180830381600087803b15801561150d57600080fd5b505af1158015611521573d6000803e3d6000fd5b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1615806115ca57506115ca61137273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006119af565b156116cd576040517fdb006a75000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063db006a7590602401600060405180830381600087803b15801561165757600080fd5b505af115801561166b573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff82163014610d7e57610d7e73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168383611a4b565b6040517f7647691d0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff83811660248301527f00000000000000000000000000000000000000000000000000000000000000001690637647691d906044016114f3565b60006117aa826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611a789092919063ffffffff16565b805190915015610d1757808060200190518101906117c89190612241565b610d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161021e565b60006118608284612263565b1561186c57600161186f565b60005b60ff1661187c838561222d565b6112729190612277565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526112cb9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016111c6565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152600091908416906370a0823190602401602060405180830381865afa158015611954573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127291906121e5565b60006119848383611a91565b6002149392505050565b610d1773ffffffffffffffffffffffffffffffffffffffff84168383611ac6565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152600091611272918516906370a0823190602401602060405180830381865afa158015611a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4691906121e5565b611b1c565b610d1782611a5a836000611248565b73ffffffffffffffffffffffffffffffffffffffff86169190611ac6565b6060611a878484600085611b2d565b90505b9392505050565b6000828280821115611aa857600292505050611275565b80821015611abb57600092505050611275565b506001949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610d179084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016111c6565b600061127564e8d4a510008361228f565b606082471015611bbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161021e565b73ffffffffffffffffffffffffffffffffffffffff85163b611c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161021e565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611c6691906122f8565b60006040518083038185875af1925050503d8060008114611ca3576040519150601f19603f3d011682016040523d82523d6000602084013e611ca8565b606091505b5091509150611cb8828286611cc3565b979650505050505050565b60608315611cd2575081611a8a565b825115611ce25782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021e919061230a565b60008060208385031215611d2957600080fd5b823567ffffffffffffffff80821115611d4157600080fd5b818501915085601f830112611d5557600080fd5b813581811115611d6457600080fd5b8660208260051b8501011115611d7957600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611dee57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611e4a57611e4a611df8565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e9757611e97611df8565b604052919050565b600060408236031215611eb157600080fd5b611eb9611e27565b8235600c8110611ec857600080fd5b815260208381013567ffffffffffffffff80821115611ee657600080fd5b9085019036601f830112611ef957600080fd5b813581811115611f0b57611f0b611df8565b611f3b847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611e50565b91508082523684828501011115611f5157600080fd5b80848401858401376000908201840152918301919091525092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff81168114611fc057600080fd5b50565b600080600060608486031215611fd857600080fd5b8351611fe381611f9e565b6020850151909350611ff481611f9e565b80925050604084015190509250925092565b6000806040838503121561201957600080fd5b825161202481611f9e565b6020939093015192949293505050565b6000806040838503121561204757600080fd5b825161205281611f9e565b8092505060208084015167ffffffffffffffff8082111561207257600080fd5b818601915086601f83011261208657600080fd5b81518181111561209857612098611df8565b8060051b91506120a9848301611e50565b81815291830184019184810190898411156120c357600080fd5b938501935b838510156120e1578451825293850193908501906120c8565b8096505050505050509250929050565b60006020828403121561210357600080fd5b8151611a8a81611f9e565b60006060820173ffffffffffffffffffffffffffffffffffffffff8087168452602081871681860152606060408601528291508551808452608086019250818701935060005b8181101561217057845184529382019392820192600101612154565b509198975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121de576121de61217e565b5060010190565b6000602082840312156121f757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261223c5761223c6121fe565b500490565b60006020828403121561225357600080fd5b81518015158114611a8a57600080fd5b600082612272576122726121fe565b500690565b6000821982111561228a5761228a61217e565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156122c7576122c761217e565b500290565b60005b838110156122e75781810151838201526020016122cf565b838111156112cb5750506000910152565b60008251611dee8184602087016122cc565b60208152600082518060208401526123298160408501602087016122cc565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea264697066735822122061727f6801d5abe5d43296853dd91f7a018d3bb2c39ea20b014e388cfc0b741164736f6c634300080f0033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "constructor": {
        "details": "Called at implementation instantiate and constant for that implementation.",
        "params": {
          "batcher_": "Protocol Batcher address",
          "controller_": "Protocol Controller address",
          "reserve_": "EmptySet Reserve address",
          "usdc_": "USDC stablecoin address"
        }
      },
      "initialize()": {
        "details": "Must be called atomically as part of the upgradeable proxy deployment to      avoid front-running"
      },
      "invoke((uint8,bytes)[])": {
        "params": {
          "invocations": "The list of invocations to execute in order"
        }
      }
    },
    "stateVariables": {
      "DSU": {
        "details": "DSU address"
      },
      "USDC": {
        "details": "USDC stablecoin address"
      },
      "batcher": {
        "details": "Batcher address"
      },
      "collateral": {
        "details": "Collateral address"
      },
      "controller": {
        "details": "Controller address"
      },
      "reserve": {
        "details": "Reserve address"
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "constructor": {
        "notice": "Initializes the immutable contract state"
      },
      "initialize()": {
        "notice": "Initializes the contract state"
      },
      "invoke((uint8,bytes)[])": {
        "notice": "Executes a list of invocations in order"
      }
    },
    "version": 1
  },
  "storageLayout": {
    "storage": [],
    "types": null
  }
}
