diff --git a/packages/perennial/contracts/forwarder/Forwarder.sol b/packages/perennial/contracts/forwarder/Forwarder.sol index 4ea298e7..8d495db4 100644 --- a/packages/perennial/contracts/forwarder/Forwarder.sol +++ b/packages/perennial/contracts/forwarder/Forwarder.sol @@ -55,7 +55,7 @@ contract Forwarder is IForwarder { IProduct product, UFixed18 amount ) external { - USDC.pull(msg.sender, amount); + USDC.pull(msg.sender, amount, true); batcher.wrap(amount, address(this)); collateral.depositTo(account, product, amount); emit WrapAndDeposit(account, product, amount); diff --git a/packages/perennial/contracts/interfaces/IForwarder.sol b/packages/perennial/contracts/interfaces/IForwarder.sol index 6f265b02..0f2df710 100644 --- a/packages/perennial/contracts/interfaces/IForwarder.sol +++ b/packages/perennial/contracts/interfaces/IForwarder.sol @@ -10,8 +10,8 @@ import "./ICollateral.sol"; interface IForwarder { event WrapAndDeposit(address indexed account, IProduct indexed product, UFixed18 amount); - function USDC() external view returns (Token6); - function DSU() external view returns (Token18); + function USDC() external view returns (Token6); // solhint-disable-line func-name-mixedcase + function DSU() external view returns (Token18); // solhint-disable-line func-name-mixedcase function batcher() external view returns (IBatcher); function collateral() external view returns (ICollateral); function wrapAndDeposit(address account, IProduct product, UFixed18 amount) external; diff --git a/packages/perennial/deployments/kovan/Forwarder.json b/packages/perennial/deployments/kovan/Forwarder.json index ea71a865..40889517 100644 --- a/packages/perennial/deployments/kovan/Forwarder.json +++ b/packages/perennial/deployments/kovan/Forwarder.json @@ -1,5 +1,5 @@ { - "address": "0x4616998f93943359AE996841f16EFe00508b1b08", + "address": "0x52C64b8998eB7C80b6F526E99E29ABdcC86B841b", "abi": [ { "inputs": [ @@ -128,48 +128,48 @@ "type": "function" } ], - "transactionHash": "0x84a2b07658d23d9b4824f23b57d47394c771bd0b0d860899cebce40a94a35dae", + "transactionHash": "0x9a1e98e0f082ac102be2ecbaeb90a4392e50dec44037a3908531f4f1b66973ab", "receipt": { "to": null, - "from": "0xb779541EcE2bFFF7CB803cfcddfA220A753879b6", - "contractAddress": "0x4616998f93943359AE996841f16EFe00508b1b08", - "transactionIndex": 0, - "gasUsed": "674838", - "logsBloom": "0x00000000000000000000000000000000000000000000200000000000000000000000000000000000000000080000000000000000000000000000002000200000040000000800000000000000000000000000000000000000000000200000000040000080000000000000000000008000000000000000000000000000000000000000000000000004000400000000000000000000000004000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000010000000000000000000000010000000000000000000000000000000040000", - "blockHash": "0xd895d2d19a6f85a7cd863e3fb4e56e311b57c44c9108954d0807889cef580577", - "transactionHash": "0x84a2b07658d23d9b4824f23b57d47394c771bd0b0d860899cebce40a94a35dae", + "from": "0x66a7fDB96C583c59597de16d8b2B989231415339", + "contractAddress": "0x52C64b8998eB7C80b6F526E99E29ABdcC86B841b", + "transactionIndex": 1, + "gasUsed": "1155660", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000400002000200000040000000800000000000000000000000000000000000000000000200000000040000000000000000000000000008000000000000000000000000000000000000000000000000000000400000000000000000000000004000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000100000000000000010000000000000000000000010000000000000004000000000000000040000", + "blockHash": "0x7f4d2a99c24e52729a4b976e2c568f110a8a3df98f3fdf6df51ea7c3ceff4fe0", + "transactionHash": "0x9a1e98e0f082ac102be2ecbaeb90a4392e50dec44037a3908531f4f1b66973ab", "logs": [ { - "transactionIndex": 0, - "blockNumber": 31777869, - "transactionHash": "0x84a2b07658d23d9b4824f23b57d47394c771bd0b0d860899cebce40a94a35dae", + "transactionIndex": 1, + "blockNumber": 31989292, + "transactionHash": "0x9a1e98e0f082ac102be2ecbaeb90a4392e50dec44037a3908531f4f1b66973ab", "address": "0xb7a4F3E9097C08dA09517b5aB877F7a917224ede", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x0000000000000000000000004616998f93943359ae996841f16efe00508b1b08", + "0x00000000000000000000000052c64b8998eb7c80b6f526e99e29abdcc86b841b", "0x000000000000000000000000d9a05f4b6277cd968f60c05f498f6e3719469c2f" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 0, - "blockHash": "0xd895d2d19a6f85a7cd863e3fb4e56e311b57c44c9108954d0807889cef580577" + "blockHash": "0x7f4d2a99c24e52729a4b976e2c568f110a8a3df98f3fdf6df51ea7c3ceff4fe0" }, { - "transactionIndex": 0, - "blockNumber": 31777869, - "transactionHash": "0x84a2b07658d23d9b4824f23b57d47394c771bd0b0d860899cebce40a94a35dae", + "transactionIndex": 1, + "blockNumber": 31989292, + "transactionHash": "0x9a1e98e0f082ac102be2ecbaeb90a4392e50dec44037a3908531f4f1b66973ab", "address": "0x1e7d42D73291A9580F1f9b6483928319CE1c3d75", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x0000000000000000000000004616998f93943359ae996841f16efe00508b1b08", + "0x00000000000000000000000052c64b8998eb7c80b6f526e99e29abdcc86b841b", "0x000000000000000000000000af146a62ab4cfd042338d5a6bf22b1dce9b23dbc" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "logIndex": 1, - "blockHash": "0xd895d2d19a6f85a7cd863e3fb4e56e311b57c44c9108954d0807889cef580577" + "blockHash": "0x7f4d2a99c24e52729a4b976e2c568f110a8a3df98f3fdf6df51ea7c3ceff4fe0" } ], - "blockNumber": 31777869, - "cumulativeGasUsed": "674838", + "blockNumber": 31989292, + "cumulativeGasUsed": "1786292", "status": 1, "byzantium": true }, @@ -180,13 +180,21 @@ "0xaf146A62aB4Cfd042338d5a6Bf22b1DcE9b23Dbc" ], "numDeployments": 1, - "solcInputHash": "65527db1409d6958fd38b19b43619005", - "metadata": "{\"compiler\":{\"version\":\"0.8.14+commit.80d49f37\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"Token6\",\"name\":\"usdc_\",\"type\":\"address\"},{\"internalType\":\"Token18\",\"name\":\"dsu_\",\"type\":\"address\"},{\"internalType\":\"contract IBatcher\",\"name\":\"batcher_\",\"type\":\"address\"},{\"internalType\":\"contract ICollateral\",\"name\":\"collateral_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WrapAndDeposit\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DSU\",\"outputs\":[{\"internalType\":\"Token18\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"Token6\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batcher\",\"outputs\":[{\"internalType\":\"contract IBatcher\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"collateral\",\"outputs\":[{\"internalType\":\"contract ICollateral\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"wrapAndDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"wrapAndDeposit(address,address,uint256)\":{\"params\":{\"account\":\"Account to deposit the collateral for\",\"amount\":\"18 decimals-normalized stablecoin (USDC, DSU) value of collateral to deposit\",\"product\":\"Product to credit the collateral to\"}}},\"stateVariables\":{\"batcher\":{\"details\":\"Contract that wraps USDC to DSU\"},\"collateral\":{\"details\":\"Contract managing state for collateral accounts in the protocol\"}},\"title\":\"Forwarder\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"wrapAndDeposit(address,address,uint256)\":{\"notice\":\"Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU, and deposits it as collateral to `account`'s `product` account \"}},\"notice\":\"Facilitates collateral deposits to the protocol where the amount is supplied in USDC then wrapped as DSU before being deposited.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/forwarder/Forwarder.sol\":\"Forwarder\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[]},\"sources\":{\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\":{\"content\":\"//SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.0;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\n\\ninterface IBatcher {\\n event Wrap(address indexed to, UFixed18 amount);\\n event Unwrap(address indexed to, UFixed18 amount);\\n event Rebalance(UFixed18 newMinted, UFixed18 newRedeemed);\\n event Close(UFixed18 amount);\\n\\n error BatcherNotImplementedError();\\n error BatcherBalanceMismatchError(UFixed18 oldBalance, UFixed18 newBalance);\\n\\n function totalBalance() external view returns (UFixed18);\\n function wrap(UFixed18 amount, address to) external;\\n function unwrap(UFixed18 amount, address to) external;\\n function rebalance() external;\\n}\\n\",\"keccak256\":\"0x236ca1cbd0422fef72a5460c7e10bcc469d0491a269513d85c7a64371845ef36\",\"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 a signed fixed-decimal from a sign and an unsigned fixed-decimal\\n * @param self Sign\\n * @return New 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\":\"0x860a1c54ea451289abde9ad678d5dc2e92432b17df648f0421bc6ffbf48b00b2\",\"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 a signed fixed-decimal from a sign and an unsigned fixed-decimal\\n * @param self Sign\\n * @return New signed fixed-decimal\\n */\\n function unpack(PackedUFixed18 self) internal pure returns (UFixed18) {\\n return UFixed18.wrap(uint256(PackedUFixed18.unwrap(self)));\\n }\\n}\\n\",\"keccak256\":\"0xa12f541b8e2a2a3d5efeebdb3f39caec1db69cb7ce9ad5c6de12235a55a47a2d\",\"license\":\"Apache-2.0\"},\"@equilibria/root/number/types/UFixed18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"./Fixed18.sol\\\";\\nimport \\\"./PackedUFixed18.sol\\\";\\n\\n/// @dev UFixed18 type\\ntype UFixed18 is uint256;\\nusing UFixed18Lib for UFixed18 global;\\ntype UFixed18Storage is bytes32;\\nusing UFixed18StorageLib for UFixed18Storage global;\\n\\n/**\\n * @title UFixed18Lib\\n * @notice Library for the unsigned fixed-decimal type.\\n */\\nlibrary UFixed18Lib {\\n error UFixed18UnderflowError(int256 value);\\n error UFixed18PackingOverflowError(uint256 value);\\n\\n uint256 private constant BASE = 1e18;\\n UFixed18 public constant ZERO = UFixed18.wrap(0);\\n UFixed18 public constant ONE = UFixed18.wrap(BASE);\\n UFixed18 public constant MAX = UFixed18.wrap(type(uint256).max);\\n\\n /**\\n * @notice Creates a unsigned fixed-decimal from a signed fixed-decimal\\n * @param a Signed fixed-decimal\\n * @return New unsigned fixed-decimal\\n */\\n function from(Fixed18 a) internal pure returns (UFixed18) {\\n int256 value = Fixed18.unwrap(a);\\n if (value < 0) revert UFixed18UnderflowError(value);\\n return UFixed18.wrap(uint256(value));\\n }\\n\\n /**\\n * @notice Creates a unsigned fixed-decimal from a unsigned integer\\n * @param a Unsigned number\\n * @return New unsigned fixed-decimal\\n */\\n function from(uint256 a) internal pure returns (UFixed18) {\\n return UFixed18.wrap(a * BASE);\\n }\\n\\n /**\\n * @notice Creates a packed unsigned fixed-decimal from an unsigned fixed-decimal\\n * @param a unsigned fixed-decimal\\n * @return New packed unsigned fixed-decimal\\n */\\n function pack(UFixed18 a) internal pure returns (PackedUFixed18) {\\n uint256 value = UFixed18.unwrap(a);\\n if (value > type(uint128).max) revert UFixed18PackingOverflowError(value);\\n return PackedUFixed18.wrap(uint128(value));\\n }\\n\\n /**\\n * @notice Returns whether the unsigned fixed-decimal is equal to zero.\\n * @param a Unsigned fixed-decimal\\n * @return Whether the unsigned fixed-decimal is zero.\\n */\\n function isZero(UFixed18 a) internal pure returns (bool) {\\n return UFixed18.unwrap(a) == 0;\\n }\\n\\n /**\\n * @notice Adds two unsigned fixed-decimals `a` and `b` together\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Resulting summed unsigned fixed-decimal\\n */\\n function add(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) + UFixed18.unwrap(b));\\n }\\n\\n /**\\n * @notice Subtracts unsigned fixed-decimal `b` from `a`\\n * @param a Unsigned fixed-decimal to subtract from\\n * @param b Unsigned fixed-decimal to subtract\\n * @return Resulting subtracted unsigned fixed-decimal\\n */\\n function sub(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) - UFixed18.unwrap(b));\\n }\\n\\n /**\\n * @notice Multiplies two unsigned fixed-decimals `a` and `b` together\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Resulting multiplied unsigned fixed-decimal\\n */\\n function mul(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) * UFixed18.unwrap(b) / BASE);\\n }\\n\\n /**\\n * @notice Divides unsigned fixed-decimal `a` by `b`\\n * @param a Unsigned fixed-decimal to divide\\n * @param b Unsigned fixed-decimal to divide by\\n * @return Resulting divided unsigned fixed-decimal\\n */\\n function div(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) * BASE / UFixed18.unwrap(b));\\n }\\n\\n /**\\n * @notice Divides unsigned fixed-decimal `a` by `b`\\n * @dev Does not revert on divide-by-0, instead returns `ONE` for `0/0` and `MAX` for `n/0`.\\n * @param a Unsigned fixed-decimal to divide\\n * @param b Unsigned fixed-decimal to divide by\\n * @return Resulting divided unsigned fixed-decimal\\n */\\n function unsafeDiv(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n if (isZero(b)) {\\n return isZero(a) ? ONE : MAX;\\n } else {\\n return div(a, b);\\n }\\n }\\n\\n /**\\n * @notice Computes a * b / c without loss of precision due to BASE conversion\\n * @param a First unsigned fixed-decimal\\n * @param b Unsigned number to multiply by\\n * @param c Unsigned number to divide by\\n * @return Resulting computation\\n */\\n function muldiv(UFixed18 a, uint256 b, uint256 c) internal pure returns (UFixed18) {\\n return muldiv(a, UFixed18.wrap(b), UFixed18.wrap(c));\\n }\\n\\n /**\\n * @notice Computes a * b / c without loss of precision due to BASE conversion\\n * @param a First unsigned fixed-decimal\\n * @param b Unsigned fixed-decimal to multiply by\\n * @param c Unsigned fixed-decimal to divide by\\n * @return Resulting computation\\n */\\n function muldiv(UFixed18 a, UFixed18 b, UFixed18 c) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) * UFixed18.unwrap(b) / UFixed18.unwrap(c));\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is equal to `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is equal to `b`\\n */\\n function eq(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return compare(a, b) == 1;\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is greater than `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is greater than `b`\\n */\\n function gt(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return compare(a, b) == 2;\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is less than `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is less than `b`\\n */\\n function lt(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return compare(a, b) == 0;\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is greater than or equal to `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is greater than or equal to `b`\\n */\\n function gte(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return gt(a, b) || eq(a, b);\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is less than or equal to `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is less than or equal to `b`\\n */\\n function lte(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return lt(a, b) || eq(a, b);\\n }\\n\\n /**\\n * @notice Compares the unsigned fixed-decimals `a` and `b`\\n * @dev Returns: 2 for greater than\\n * 1 for equal to\\n * 0 for less than\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Compare result of `a` and `b`\\n */\\n function compare(UFixed18 a, UFixed18 b) internal pure returns (uint256) {\\n (uint256 au, uint256 bu) = (UFixed18.unwrap(a), UFixed18.unwrap(b));\\n if (au > bu) return 2;\\n if (au < bu) return 0;\\n return 1;\\n }\\n\\n /**\\n * @notice Returns a unsigned fixed-decimal representing the ratio of `a` over `b`\\n * @param a First unsigned number\\n * @param b Second unsigned number\\n * @return Ratio of `a` over `b`\\n */\\n function ratio(uint256 a, uint256 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(a * BASE / b);\\n }\\n\\n /**\\n * @notice Returns the minimum of unsigned fixed-decimals `a` and `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Minimum of `a` and `b`\\n */\\n function min(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(Math.min(UFixed18.unwrap(a), UFixed18.unwrap(b)));\\n }\\n\\n /**\\n * @notice Returns the maximum of unsigned fixed-decimals `a` and `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Maximum of `a` and `b`\\n */\\n function max(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(Math.max(UFixed18.unwrap(a), UFixed18.unwrap(b)));\\n }\\n\\n /**\\n * @notice Converts the unsigned fixed-decimal into an integer, truncating any decimal portion\\n * @param a Unsigned fixed-decimal\\n * @return Truncated unsigned number\\n */\\n function truncate(UFixed18 a) internal pure returns (uint256) {\\n return UFixed18.unwrap(a) / BASE;\\n }\\n}\\n\\nlibrary UFixed18StorageLib {\\n function read(UFixed18Storage self) internal view returns (UFixed18 value) {\\n assembly {\\n value := sload(self)\\n }\\n }\\n\\n function store(UFixed18Storage self, UFixed18 value) internal {\\n assembly {\\n sstore(self, value)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8ebef1e6c717f565b9ed545a876b5692b4007e6485c99f39d363f7405e591792\",\"license\":\"Apache-2.0\"},\"@equilibria/root/token/types/Token18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../../number/types/UFixed18.sol\\\";\\n\\n/// @dev Token18\\ntype Token18 is address;\\nusing Token18Lib for Token18 global;\\ntype Token18Storage is bytes32;\\nusing Token18StorageLib for Token18Storage global;\\n\\n/**\\n * @title Token18Lib\\n * @notice Library to manage 18-decimal ERC20s that is compliant with the fixed-decimal types.\\n * @dev Maintains significant gas savings over other Token implementations since no conversion take place\\n */\\nlibrary Token18Lib {\\n using SafeERC20 for IERC20;\\n\\n Token18 public constant ZERO = Token18.wrap(address(0));\\n\\n /**\\n * @notice Returns whether a token is the zero address\\n * @param self Token to check for\\n * @return Whether the token is the zero address\\n */\\n function isZero(Token18 self) internal pure returns (bool) {\\n return Token18.unwrap(self) == Token18.unwrap(ZERO);\\n }\\n\\n /**\\n * @notice Returns whether the two tokens are equal\\n * @param a First token to compare\\n * @param b Second token to compare\\n * @return Whether the two tokens are equal\\n */\\n function eq(Token18 a, Token18 b) internal pure returns (bool) {\\n return Token18.unwrap(a) == Token18.unwrap(b);\\n }\\n\\n /**\\n * @notice Approves `grantee` to spend infinite tokens from the caller\\n * @param self Token to transfer\\n * @param grantee Address to allow spending\\n */\\n function approve(Token18 self, address grantee) internal {\\n IERC20(Token18.unwrap(self)).safeApprove(grantee, type(uint256).max);\\n }\\n\\n /**\\n * @notice Approves `grantee` to spend `amount` tokens from the caller\\n * @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\":\"0x318b6f49c3225000baeeaeb6a7dde25799d7b5d966fcff2a87b52ddcfc3ae381\",\"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 * @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 * @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\":\"0x8371d28bc629762e0599ce5984b56431d90626cdfe2b770e92e9d8858d409bad\",\"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.5.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 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 /**\\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\",\"keccak256\":\"0xbbc8ac883ac3c0078ce5ad3e288fbb3ffcc8a30c3a98c0fda0114d64fc44fca2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a / b + (a % b == 0 ? 0 : 1);\\n }\\n}\\n\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\"},\"contracts/forwarder/Forwarder.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity 0.8.14;\\n\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"@equilibria/root/token/types/Token6.sol\\\";\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\\\";\\nimport \\\"../interfaces/ICollateral.sol\\\";\\n\\n/**\\n * @title Forwarder\\n * @notice Facilitates collateral deposits to the protocol where the amount is supplied\\n * in USDC then wrapped as DSU before being deposited.\\n */\\ncontract Forwarder {\\n // @dev USDC stablecoin\\n Token6 public immutable USDC;\\n\\n // @dev DSU stablecoin\\n Token18 public immutable DSU;\\n\\n /// @dev Contract that wraps USDC to DSU\\n IBatcher public immutable batcher;\\n\\n /// @dev Contract managing state for collateral accounts in the protocol\\n ICollateral public immutable collateral;\\n\\n event WrapAndDeposit(address indexed account, IProduct indexed product, UFixed18 amount);\\n\\n constructor(\\n Token6 usdc_,\\n Token18 dsu_,\\n IBatcher batcher_,\\n ICollateral collateral_\\n ) {\\n USDC = usdc_;\\n DSU = dsu_;\\n batcher = batcher_;\\n collateral = collateral_;\\n\\n USDC.approve(address(batcher));\\n DSU.approve(address(collateral));\\n }\\n\\n /**\\n * @notice Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU,\\n and deposits it as collateral to `account`'s `product` account \\n * @param account Account to deposit the collateral for\\n * @param product Product to credit the collateral to\\n * @param amount 18 decimals-normalized stablecoin (USDC, DSU) value of collateral to deposit\\n */\\n function wrapAndDeposit(\\n address account,\\n IProduct product,\\n UFixed18 amount\\n ) external {\\n USDC.pull(msg.sender, amount);\\n batcher.wrap(amount, address(this));\\n collateral.depositTo(account, product, amount);\\n emit WrapAndDeposit(account, product, amount);\\n }\\n}\\n\",\"keccak256\":\"0x2e9b2891d3946a70dbcf4866c9ee13b695f3b82039286da5616f6fd3e836c096\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/ICollateral.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"./IController.sol\\\";\\nimport \\\"./IProduct.sol\\\";\\n\\ninterface ICollateral {\\n event Deposit(address indexed user, IProduct indexed product, UFixed18 amount);\\n event Withdrawal(address indexed user, IProduct indexed product, UFixed18 amount);\\n event AccountSettle(IProduct indexed product, address indexed account, Fixed18 amount, UFixed18 newShortfall);\\n event ProductSettle(IProduct indexed product, UFixed18 protocolFee, UFixed18 productFee);\\n event Liquidation(address indexed user, IProduct indexed product, address liquidator, UFixed18 fee);\\n event ShortfallResolution(IProduct indexed product, UFixed18 amount);\\n event FeeClaim(address indexed account, UFixed18 amount);\\n\\n error CollateralCantLiquidate(UFixed18 totalMaintenance, UFixed18 totalCollateral);\\n error CollateralInsufficientCollateralError();\\n error CollateralUnderLimitError();\\n error CollateralZeroAddressError();\\n\\n function token() external view returns (Token18);\\n function fees(address account) external view returns (UFixed18);\\n function initialize(IController controller_) external;\\n function depositTo(address account, IProduct product, UFixed18 amount) external;\\n function withdrawTo(address account, IProduct product, UFixed18 amount) external;\\n function liquidate(address account, IProduct product) external;\\n function settleAccount(address account, Fixed18 amount) external;\\n function settleProduct(UFixed18 amount) external;\\n function collateral(address account, IProduct product) external view returns (UFixed18);\\n function collateral(IProduct product) external view returns (UFixed18);\\n function shortfall(IProduct product) external view returns (UFixed18);\\n function liquidatable(address account, IProduct product) external view returns (bool);\\n function liquidatableNext(address account, IProduct product) external view returns (bool);\\n function resolveShortfall(IProduct product, UFixed18 amount) external;\\n function claimFee() external;\\n}\\n\",\"keccak256\":\"0xa5e7fdda92702f748e6eb8701e522450035a98a05e5fc1cf66d51c52e397d914\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/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 \\\"./IProductProvider.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 /// @dev the address that is allowed to pause the coordinated products (0-address defaults to owner)\\n address pauser;\\n\\n /// @dev Whether the coordinated products are paused\\n bool paused;\\n }\\n\\n event CollateralUpdated(ICollateral newCollateral);\\n event IncentivizerUpdated(IIncentivizer newIncentivizer);\\n event ProductBeaconUpdated(IBeacon newProductBeacon);\\n event ProtocolFeeUpdated(UFixed18 newProtocolFee);\\n event MinFundingFeeUpdated(UFixed18 newMinFundingFee);\\n event LiquidationFeeUpdated(UFixed18 newLiquidationFee);\\n event IncentivizationFeeUpdated(UFixed18 newIncentivizationFee);\\n event MinCollateralUpdated(UFixed18 newMinCollateral);\\n event ProgramsPerProductUpdated(uint256 newProgramsPerProduct);\\n event CoordinatorPendingOwnerUpdated(uint256 indexed coordinatorId, address newPendingOwner);\\n event CoordinatorOwnerUpdated(uint256 indexed coordinatorId, address newOwner);\\n event CoordinatorTreasuryUpdated(uint256 indexed coordinatorId, address newTreasury);\\n event CoordinatorPauserUpdated(uint256 indexed coordinatorId, address pauser);\\n event CoordinatorPausedUpdated(uint256 indexed coordinatorId, bool paused);\\n event CoordinatorCreated(uint256 indexed coordinatorId, address owner);\\n event ProductCreated(IProduct indexed product, IProductProvider provider);\\n\\n error ControllerAlreadyInitializedError();\\n error ControllerNoZeroCoordinatorError();\\n error ControllerNotPauserError(uint256 coordinatorId);\\n error ControllerNotOwnerError(uint256 controllerId);\\n error ControllerNotPendingOwnerError(uint256 controllerId);\\n error ControllerInvalidProtocolFeeError();\\n error ControllerInvalidMinFundingFeeError();\\n error ControllerInvalidLiquidationFeeError();\\n error ControllerInvalidIncentivizationFeeError();\\n\\n function collateral() external view returns (ICollateral);\\n function incentivizer() external view returns (IIncentivizer);\\n function productBeacon() external view returns (IBeacon);\\n function coordinators(uint256 collateralId) external view returns (Coordinator memory);\\n function coordinatorFor(IProduct product) external view returns (uint256);\\n function protocolFee() external view returns (UFixed18);\\n function minFundingFee() external view returns (UFixed18);\\n function liquidationFee() external view returns (UFixed18);\\n function incentivizationFee() external view returns (UFixed18);\\n function minCollateral() external view returns (UFixed18);\\n function programsPerProduct() external view returns (uint256);\\n function initialize(ICollateral collateral_, IIncentivizer incentivizer_, IBeacon productBeacon_) external;\\n function createCoordinator(address coordinatorOwner) 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 updateCoordinatorPauser(uint256 coordinatorId, address newPauser) external;\\n function updateCoordinatorPaused(uint256 coordinatorId, bool newPaused) external;\\n function createProduct(uint256 coordinatorId, IProductProvider provider) external returns (IProduct);\\n function updateCollateral(ICollateral newCollateral) external;\\n function updateIncentivizer(IIncentivizer newIncentivizer) external;\\n function updateProductBeacon(IBeacon newProductBeacon) external;\\n function updateProtocolFee(UFixed18 newProtocolFee) external;\\n function updateMinFundingFee(UFixed18 newMinFundingFee) external;\\n function updateLiquidationFee(UFixed18 newLiquidationFee) external;\\n function updateIncentivizationFee(UFixed18 newIncentivizationFee) external;\\n function updateMinCollateral(UFixed18 newMinCollateral) external;\\n function updateProgramsPerProduct(uint256 newProductsPerProduct) external;\\n function 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 function pauser() external view returns (address);\\n function pauser(uint256 coordinatorId) external view returns (address);\\n function pauser(IProduct product) external view returns (address);\\n function paused() external view returns (bool);\\n function paused(uint256 coordinatorId) external view returns (bool);\\n function paused(IProduct product) external view returns (bool);\\n}\",\"keccak256\":\"0xe3e848c947097c36ac1ac1ee408c035aa5888a30112e99394a863a28fcfaf146\",\"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 \\\"./types/ProgramInfo.sol\\\";\\nimport \\\"./IOracleProvider.sol\\\";\\nimport \\\"./IController.sol\\\";\\nimport \\\"./IProduct.sol\\\";\\n\\ninterface IIncentivizer {\\n event ProgramCreated(IProduct indexed product, uint256 indexed programId, uint256 coordinatorId, Token18 token, UFixed18 amountMaker, UFixed18 amountTaker, uint256 start, uint256 duration, 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\\n function programInfos(IProduct product, uint256 programId) external view returns (ProgramInfo memory);\\n function fees(Token18 token) external view returns (UFixed18);\\n function initialize(IController controller_) external;\\n function create(IProduct product, ProgramInfo calldata info) external returns (uint256);\\n function complete(IProduct product, uint256 programId) external;\\n function sync(IOracleProvider.OracleVersion memory currentOracleVersion) external;\\n function syncAccount(address account, IOracleProvider.OracleVersion memory currentOracleVersion) external;\\n function claim(IProduct product, uint256[] calldata programIds) external;\\n function claim(IProduct[] calldata products, uint256[][] calldata programIds) external;\\n function claimFee(Token18[] calldata tokens) external;\\n function active(IProduct product) external view returns (uint256);\\n function count(IProduct product) external view returns (uint256);\\n function unclaimed(IProduct product, address account, uint256 programId) external view returns (UFixed18);\\n function available(IProduct product, uint256 programId) external view returns (UFixed18);\\n function versionStarted(IProduct product, uint256 programId) external view returns (uint256);\\n function versionComplete(IProduct product, uint256 programId) external view returns (uint256);\\n function owner(IProduct product, uint256 programId) external view returns (address);\\n function treasury(IProduct product, uint256 programId) external view returns (address);\\n}\\n\",\"keccak256\":\"0x46f3cbdb6ff3214609d88069a18dae1d607833bcc92d67304955017cbd9f3f67\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IOracleProvider.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\n\\ninterface IOracleProvider {\\n /// @dev A singular oracle version with its corresponding data\\n struct OracleVersion {\\n /// @dev The iterative version\\n uint256 version;\\n\\n /// @dev the timestamp of the oracle update\\n uint256 timestamp;\\n\\n /// @dev The oracle price of the corresponding version\\n Fixed18 price;\\n }\\n\\n function sync() external returns (OracleVersion memory);\\n function currentVersion() external view returns (OracleVersion memory);\\n function atVersion(uint256 oracleVersion) external view returns (OracleVersion memory);\\n}\\n\",\"keccak256\":\"0xde0f20d468ba8b91addfc356e13f2c74a4dc8abe68be323942217c723775d9c1\",\"license\":\"Apache-2.0\"},\"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 \\\"./types/Position.sol\\\";\\nimport \\\"./types/PrePosition.sol\\\";\\nimport \\\"./types/Accumulator.sol\\\";\\nimport \\\"./IProductProvider.sol\\\";\\n\\ninterface IProduct {\\n event Settle(uint256 preVersion, uint256 toVersion);\\n event AccountSettle(address indexed account, uint256 preVersion, uint256 toVersion);\\n event MakeOpened(address indexed account, UFixed18 amount);\\n event TakeOpened(address indexed account, UFixed18 amount);\\n event MakeClosed(address indexed account, UFixed18 amount);\\n event TakeClosed(address indexed account, UFixed18 amount);\\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\\n function productProvider() external view returns (IProductProvider);\\n function initialize(IProductProvider productProvider_) external;\\n function settle() external;\\n function settleAccount(address account) external;\\n function openTake(UFixed18 amount) external;\\n function closeTake(UFixed18 amount) external;\\n function openMake(UFixed18 amount) external;\\n function closeMake(UFixed18 amount) external;\\n function closeAll(address account) external;\\n function maintenance(address account) external view returns (UFixed18);\\n function maintenanceNext(address account) external view returns (UFixed18);\\n function isClosed(address account) external view returns (bool);\\n function isLiquidating(address account) external view returns (bool);\\n function position(address account) external view returns (Position memory);\\n function pre(address account) external view returns (PrePosition memory);\\n function latestVersion() external view returns (uint256);\\n function positionAtVersion(uint256 oracleVersion) external view returns (Position memory);\\n function pre() external view returns (PrePosition memory);\\n function valueAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\\n function shareAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\\n function latestVersion(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd6088e950e92511095c64f37aa747304ff56eb26beeda077441adac3aba3e523\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IProductProvider.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 \\\"./types/Position.sol\\\";\\nimport \\\"./IOracleProvider.sol\\\";\\n\\ninterface IProductProvider is IOracleProvider {\\n function oracle() external view returns (IOracleProvider);\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function rate(Position memory position) external view returns (Fixed18);\\n function maintenance() external view returns (UFixed18);\\n function fundingFee() external view returns (UFixed18);\\n function makerFee() external view returns (UFixed18);\\n function takerFee() external view returns (UFixed18);\\n function makerLimit() external view returns (UFixed18);\\n}\\n\",\"keccak256\":\"0xeed08e4335ca553a639e6a77274df69c01413dd652e4d764f36ad7ae50016a8b\",\"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/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 \\\"./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 provider The parameter provider of the product\\n * @param toOracleVersion The oracle version to settle to\\n * @return Settled position at oracle version\\n * @return Fee accrued from opening or closing the position\\n * @return Whether a new position was settled\\n */\\n function settled(\\n Position memory self,\\n PrePosition memory pre,\\n IProductProvider provider,\\n IOracleProvider.OracleVersion memory toOracleVersion\\n ) internal view returns (Position memory, UFixed18, bool) {\\n return pre.canSettle(toOracleVersion) ? (next(self, pre), pre.computeFee(provider, toOracleVersion), true) : (self, UFixed18Lib.ZERO, false);\\n }\\n\\n /**\\n * @notice Returns the socialization factor for the current position\\n * @dev Socialization account for the case where `taker` > `maker` temporarily due to a liquidation\\n * on the maker side. This dampens the taker's exposure pro-rata to ensure that the maker side\\n * is never exposed over 1 x short.\\n * @param self The Position to operate on\\n * @return Socialization factor\\n */\\n function socializationFactor(Position memory self) internal pure returns (UFixed18) {\\n return self.taker.isZero() ? UFixed18Lib.ONE : UFixed18Lib.min(UFixed18Lib.ONE, self.maker.div(self.taker));\\n }\\n}\\n\",\"keccak256\":\"0x238013d5792bcca49c815845fbd815ccd4ae97f8994ab33359827bdcc769c16b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/PrePosition.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"./Position.sol\\\";\\nimport \\\"./ProductProvider.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 using ProductProviderLib for IProductProvider;\\n\\n /**\\n * @notice Returns whether there is no pending-settlement position delta\\n * @dev Can be \\\"empty\\\" even with a non-zero oracleVersion if a position is opened and\\n * closed in the same version netting out to a zero position delta\\n * @param self The struct to operate on\\n * @return Whether the pending-settlement position delta is empty\\n */\\n function isEmpty(PrePosition memory self) internal pure returns (bool) {\\n return self.openPosition.isEmpty() && self.closePosition.isEmpty();\\n }\\n\\n /**\\n * @notice Increments the maker side of the open position delta\\n * @dev Nets out open and close deltas to minimize the size of each\\n * @param self The struct to operate on\\n * @param currentVersion The current oracle version index\\n * @param amount The position amount to open\\n */\\n function openMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n self.openPosition.maker = self.openPosition.maker.add(amount);\\n self.oracleVersion = currentVersion;\\n _netMake(self);\\n }\\n\\n /**\\n * @notice Increments the maker side of the close position delta\\n * @dev Nets out open and close deltas to minimize the size of each\\n * @param self The struct to operate on\\n * @param currentVersion The current oracle version index\\n * @param amount The maker position amount to close\\n */\\n function closeMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n self.closePosition.maker = self.closePosition.maker.add(amount);\\n self.oracleVersion = currentVersion;\\n _netMake(self);\\n }\\n\\n /**\\n * @notice Increments the taker side of the open position delta\\n * @dev Nets out open and close deltas to minimize the size of each\\n * @param self The struct to operate on\\n * @param currentVersion The current oracle version index\\n * @param amount The taker position amount to open\\n */\\n function openTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n self.openPosition.taker = self.openPosition.taker.add(amount);\\n self.oracleVersion = currentVersion;\\n _netTake(self);\\n }\\n\\n /**\\n * @notice Increments the taker side of the close position delta\\n * @dev Nets out open and close deltas to minimize the size of each\\n * @param self The struct to operate on\\n * @param currentVersion The current oracle version index\\n * @param amount The taker position amount to close\\n */\\n function closeTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n self.closePosition.taker = self.closePosition.taker.add(amount);\\n self.oracleVersion = currentVersion;\\n _netTake(self);\\n }\\n\\n /**\\n * @notice Nets out the open and close on the maker side of the position delta\\n * @param self The struct to operate on\\n */\\n function _netMake(PrePosition storage self) private {\\n if (self.openPosition.maker.gt(self.closePosition.maker)) {\\n self.openPosition.maker = self.openPosition.maker.sub(self.closePosition.maker);\\n self.closePosition.maker = UFixed18Lib.ZERO;\\n } else {\\n self.closePosition.maker = self.closePosition.maker.sub(self.openPosition.maker);\\n self.openPosition.maker = UFixed18Lib.ZERO;\\n }\\n }\\n\\n /**\\n * @notice Nets out the open and close on the taker side of the position delta\\n * @param self The struct to operate on\\n */\\n function _netTake(PrePosition storage self) private {\\n if (self.openPosition.taker.gt(self.closePosition.taker)) {\\n self.openPosition.taker = self.openPosition.taker.sub(self.closePosition.taker);\\n self.closePosition.taker = UFixed18Lib.ZERO;\\n } else {\\n self.closePosition.taker = self.closePosition.taker.sub(self.openPosition.taker);\\n self.openPosition.taker = UFixed18Lib.ZERO;\\n }\\n }\\n\\n /**\\n * @notice Returns whether the the pending position delta can be settled at version `toOracleVersion`\\n * @dev Pending-settlement positions deltas can be settled (1) oracle version after they are recorded\\n * @param self The struct to operate on\\n * @param toOracleVersion The potential oracle version to settle\\n * @return Whether the position delta can be settled\\n */\\n function canSettle(\\n PrePosition memory self,\\n IOracleProvider.OracleVersion memory toOracleVersion\\n ) internal pure returns (bool) {\\n return !isEmpty(self) && toOracleVersion.version > self.oracleVersion;\\n }\\n\\n /**\\n * @notice Computes the fee incurred for opening or closing the pending-settlement position\\n * @param self The struct to operate on\\n * @param provider The parameter provider of the product\\n * @param toOracleVersion The oracle version at which settlement takes place\\n * @return positionFee The maker / taker fee incurred\\n */\\n function computeFee(\\n PrePosition memory self,\\n IProductProvider provider,\\n IOracleProvider.OracleVersion memory toOracleVersion\\n ) internal view returns (UFixed18) {\\n Position memory positionDelta = self.openPosition.add(self.closePosition);\\n\\n (UFixed18 makerNotional, UFixed18 takerNotional) = (\\n Fixed18Lib.from(positionDelta.maker).mul(toOracleVersion.price).abs(),\\n Fixed18Lib.from(positionDelta.taker).mul(toOracleVersion.price).abs()\\n );\\n\\n return makerNotional.mul(provider.safeMakerFee()).add(takerNotional.mul(provider.safeTakerFee()));\\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\":\"0xdf84172a254686f8cd721cd0c25f56e24a6f423f7ab780e7aa19bbf27352b392\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/ProductProvider.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"../IProductProvider.sol\\\";\\nimport \\\"../IController.sol\\\";\\n\\n/**\\n * @title ProductProviderLib\\n * @notice Library that adds a safeguard wrapper to certain product parameters.\\n * @dev Product providers are semi-untrusted as they contain custom code from the product owners. Owners\\n * have full control over this parameter-setting code, however there are some \\\"known ranges\\\" that\\n * a parameter cannot be outside of (i.e. a fee being over 100%).\\n */\\nlibrary ProductProviderLib {\\n /**\\n * @notice Returns the minimum funding fee parameter with a capped range for safety\\n * @dev Caps controller.minFundingFee() <= self.minFundingFee() <= 1\\n * @param self The parameter provider to operate on\\n * @param controller The protocol Factory contract\\n * @return Safe minimum funding fee parameter\\n */\\n function safeFundingFee(IProductProvider self, IController controller) internal view returns (UFixed18) {\\n return self.fundingFee().max(controller.minFundingFee()).min(UFixed18Lib.ONE);\\n }\\n\\n /**\\n * @notice Returns the maker fee parameter with a capped range for safety\\n * @dev Caps self.makerFee() <= 1\\n * @param self The parameter provider to operate on\\n * @return Safe maker fee parameter\\n */\\n function safeMakerFee(IProductProvider self) internal view returns (UFixed18) {\\n return self.makerFee().min(UFixed18Lib.ONE);\\n }\\n\\n /**\\n * @notice Returns the taker fee parameter with a capped range for safety\\n * @dev Caps self.takerFee() <= 1\\n * @param self The parameter provider to operate on\\n * @return Safe taker fee parameter\\n */\\n function safeTakerFee(IProductProvider self) internal view returns (UFixed18) {\\n return self.takerFee().min(UFixed18Lib.ONE);\\n }\\n}\\n\",\"keccak256\":\"0x70f535ebe9b53f5ad94761e6e3da2b96ec261dce1c6c318e1f70b4e9e12b92b7\",\"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\\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 /// @dev Reward ERC20 token contract\\n Token18 token;\\n}\\nusing ProgramInfoLib for ProgramInfo global;\\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\":\"0x56aa72056fb4e4021b2e2bd69a707821173370d3a382fdb0ba797686afa09629\",\"license\":\"Apache-2.0\"}},\"version\":1}", - "bytecode": "0x6101006040523480156200001257600080fd5b5060405162000fed38038062000fed8339810160408190526200003591620004ab565b6001600160a01b03848116608081905284821660a05283821660c081905291831660e0526200007091620000a1602090811b620002fb17901c565b6200009760e05160a0516001600160a01b0316620000a160201b620002fb1790919060201c565b50505050620005d7565b620000c881600019846001600160a01b0316620000cc60201b62000315179092919060201c565b5050565b8015806200014a5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000148919062000513565b155b620001c25760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091526200021a9185916200021f16565b505050565b60006200027b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620002fd60201b620004cd179092919060201c565b8051909150156200021a57808060200190518101906200029c91906200052d565b6200021a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620001b9565b60606200030e848460008562000318565b90505b9392505050565b6060824710156200037b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620001b9565b6001600160a01b0385163b620003d45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001b9565b600080866001600160a01b03168587604051620003f2919062000584565b60006040518083038185875af1925050503d806000811462000431576040519150601f19603f3d011682016040523d82523d6000602084013e62000436565b606091505b5090925090506200044982828662000454565b979650505050505050565b606083156200046557508162000311565b825115620004765782518084602001fd5b8160405162461bcd60e51b8152600401620001b99190620005a2565b6001600160a01b0381168114620004a857600080fd5b50565b60008060008060808587031215620004c257600080fd5b8451620004cf8162000492565b6020860151909450620004e28162000492565b6040860151909350620004f58162000492565b6060860151909250620005088162000492565b939692955090935050565b6000602082840312156200052657600080fd5b5051919050565b6000602082840312156200054057600080fd5b815180151581146200031157600080fd5b60005b838110156200056e57818101518382015260200162000554565b838111156200057e576000848401525b50505050565b600082516200059881846020870162000551565b9190910192915050565b6020815260008251806020840152620005c381604085016020870162000551565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516109ca6200062360003960008181610117015261024b015260008181607101526101a20152600060f001526000818160c9015261014601526109ca6000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806389a302711161005057806389a30271146100c4578063a2060bcf146100eb578063d8dfeb451461011257600080fd5b8063025a3a291461006c57806344bc170a146100af575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b6100c26100bd366004610839565b610139565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b61016d6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836104e6565b6040517f13bac820000000000000000000000000000000000000000000000000000000008152600481018290523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906313bac82090604401600060405180830381600087803b1580156101ee57600080fd5b505af1158015610202573d6000803e3d6000fd5b50506040517ff213159c0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301528581166024830152604482018590527f000000000000000000000000000000000000000000000000000000000000000016925063f213159c9150606401600060405180830381600087803b15801561029157600080fd5b505af11580156102a5573d6000803e3d6000fd5b50505050816001600160a01b0316836001600160a01b03167f8e7ce60e353ab1a4cc59ca4782bdc69e0565713d1824dce27e0de2e362147ed0836040516102ee91815260200190565b60405180910390a3505050565b6103116001600160a01b03831682600019610315565b5050565b8015806103a857506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015610382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a6919061087a565b155b61041f5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b6040516001600160a01b0383166024820152604481018290526104c89084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610508565b505050565b60606104dc84846000856105ed565b90505b9392505050565b6104c882306104f6846000610735565b6001600160a01b03871692919061075f565b600061055d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166104cd9092919063ffffffff16565b8051909150156104c8578080602001905181019061057b9190610893565b6104c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610416565b6060824710156106655760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610416565b6001600160a01b0385163b6106bc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610416565b600080866001600160a01b031685876040516106d891906108e1565b60006040518083038185875af1925050503d8060008114610715576040519150601f19603f3d011682016040523d82523d6000602084013e61071a565b606091505b509150915061072a8282866107b6565b979650505050505050565b6000816107505761074b64e8d4a5100084610913565b6104df565b6104df8364e8d4a510006107ef565b6040516001600160a01b03808516602483015283166044820152606481018290526107b09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401610464565b50505050565b606083156107c55750816104df565b8251156107d55782518084602001fd5b8160405162461bcd60e51b81526004016104169190610927565b60006107fb828461095a565b1561080757600161080a565b60005b60ff166108178385610913565b6104df919061096e565b6001600160a01b038116811461083657600080fd5b50565b60008060006060848603121561084e57600080fd5b833561085981610821565b9250602084013561086981610821565b929592945050506040919091013590565b60006020828403121561088c57600080fd5b5051919050565b6000602082840312156108a557600080fd5b815180151581146104df57600080fd5b60005b838110156108d05781810151838201526020016108b8565b838111156107b05750506000910152565b600082516108f38184602087016108b5565b9190910192915050565b634e487b7160e01b600052601260045260246000fd5b600082610922576109226108fd565b500490565b60208152600082518060208401526109468160408501602087016108b5565b601f01601f19169190910160400192915050565b600082610969576109696108fd565b500690565b6000821982111561098f57634e487b7160e01b600052601160045260246000fd5b50019056fea264697066735822122074611a7b14bb80ed345fc040890e35c88de8dd6deca0b5ed15f13b5a8e9d712564736f6c634300080e0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c806389a302711161005057806389a30271146100c4578063a2060bcf146100eb578063d8dfeb451461011257600080fd5b8063025a3a291461006c57806344bc170a146100af575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b6100c26100bd366004610839565b610139565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b61016d6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836104e6565b6040517f13bac820000000000000000000000000000000000000000000000000000000008152600481018290523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906313bac82090604401600060405180830381600087803b1580156101ee57600080fd5b505af1158015610202573d6000803e3d6000fd5b50506040517ff213159c0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301528581166024830152604482018590527f000000000000000000000000000000000000000000000000000000000000000016925063f213159c9150606401600060405180830381600087803b15801561029157600080fd5b505af11580156102a5573d6000803e3d6000fd5b50505050816001600160a01b0316836001600160a01b03167f8e7ce60e353ab1a4cc59ca4782bdc69e0565713d1824dce27e0de2e362147ed0836040516102ee91815260200190565b60405180910390a3505050565b6103116001600160a01b03831682600019610315565b5050565b8015806103a857506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015610382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a6919061087a565b155b61041f5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b6040516001600160a01b0383166024820152604481018290526104c89084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610508565b505050565b60606104dc84846000856105ed565b90505b9392505050565b6104c882306104f6846000610735565b6001600160a01b03871692919061075f565b600061055d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166104cd9092919063ffffffff16565b8051909150156104c8578080602001905181019061057b9190610893565b6104c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610416565b6060824710156106655760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610416565b6001600160a01b0385163b6106bc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610416565b600080866001600160a01b031685876040516106d891906108e1565b60006040518083038185875af1925050503d8060008114610715576040519150601f19603f3d011682016040523d82523d6000602084013e61071a565b606091505b509150915061072a8282866107b6565b979650505050505050565b6000816107505761074b64e8d4a5100084610913565b6104df565b6104df8364e8d4a510006107ef565b6040516001600160a01b03808516602483015283166044820152606481018290526107b09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401610464565b50505050565b606083156107c55750816104df565b8251156107d55782518084602001fd5b8160405162461bcd60e51b81526004016104169190610927565b60006107fb828461095a565b1561080757600161080a565b60005b60ff166108178385610913565b6104df919061096e565b6001600160a01b038116811461083657600080fd5b50565b60008060006060848603121561084e57600080fd5b833561085981610821565b9250602084013561086981610821565b929592945050506040919091013590565b60006020828403121561088c57600080fd5b5051919050565b6000602082840312156108a557600080fd5b815180151581146104df57600080fd5b60005b838110156108d05781810151838201526020016108b8565b838111156107b05750506000910152565b600082516108f38184602087016108b5565b9190910192915050565b634e487b7160e01b600052601260045260246000fd5b600082610922576109226108fd565b500490565b60208152600082518060208401526109468160408501602087016108b5565b601f01601f19169190910160400192915050565b600082610969576109696108fd565b500690565b6000821982111561098f57634e487b7160e01b600052601160045260246000fd5b50019056fea264697066735822122074611a7b14bb80ed345fc040890e35c88de8dd6deca0b5ed15f13b5a8e9d712564736f6c634300080e0033", + "solcInputHash": "b8274f6dd1d105c22962cd6c5ef4c924", + "metadata": "{\"compiler\":{\"version\":\"0.8.14+commit.80d49f37\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"Token6\",\"name\":\"usdc_\",\"type\":\"address\"},{\"internalType\":\"Token18\",\"name\":\"dsu_\",\"type\":\"address\"},{\"internalType\":\"contract IBatcher\",\"name\":\"batcher_\",\"type\":\"address\"},{\"internalType\":\"contract ICollateral\",\"name\":\"collateral_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WrapAndDeposit\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DSU\",\"outputs\":[{\"internalType\":\"Token18\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"USDC\",\"outputs\":[{\"internalType\":\"Token6\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batcher\",\"outputs\":[{\"internalType\":\"contract IBatcher\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"collateral\",\"outputs\":[{\"internalType\":\"contract ICollateral\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"wrapAndDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"batcher_\":\"The USDC-to-DSU batcher contract address\",\"collateral_\":\"The perennial collateral contract address\",\"dsu_\":\"The DSU token contract address\",\"usdc_\":\"The USDC token contract address\"}},\"wrapAndDeposit(address,address,uint256)\":{\"params\":{\"account\":\"Account to deposit the collateral for\",\"amount\":\"18 decimals-normalized stablecoin (USDC, DSU) value of collateral to deposit\",\"product\":\"Product to credit the collateral to\"}}},\"stateVariables\":{\"batcher\":{\"details\":\"Contract that wraps USDC to DSU\"},\"collateral\":{\"details\":\"Contract managing state for collateral accounts in the protocol\"}},\"title\":\"Forwarder\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Initializes the contract state\"},\"wrapAndDeposit(address,address,uint256)\":{\"notice\":\"Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU, and deposits it as collateral to `account`'s `product` account\"}},\"notice\":\"Facilitates collateral deposits to the protocol where the amount is supplied in USDC then wrapped as DSU before being deposited.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/forwarder/Forwarder.sol\":\"Forwarder\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":1000},\"remappings\":[]},\"sources\":{\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\":{\"content\":\"//SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.0;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\n\\ninterface IBatcher {\\n event Wrap(address indexed to, UFixed18 amount);\\n event Unwrap(address indexed to, UFixed18 amount);\\n event Rebalance(UFixed18 newMinted, UFixed18 newRedeemed);\\n event Close(UFixed18 amount);\\n\\n error BatcherNotImplementedError();\\n error BatcherBalanceMismatchError(UFixed18 oldBalance, UFixed18 newBalance);\\n\\n function totalBalance() external view returns (UFixed18);\\n function wrap(UFixed18 amount, address to) external;\\n function unwrap(UFixed18 amount, address to) external;\\n function rebalance() external;\\n}\\n\",\"keccak256\":\"0x236ca1cbd0422fef72a5460c7e10bcc469d0491a269513d85c7a64371845ef36\",\"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 a signed fixed-decimal from a sign and an unsigned fixed-decimal\\n * @param self Sign\\n * @return New 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\":\"0x860a1c54ea451289abde9ad678d5dc2e92432b17df648f0421bc6ffbf48b00b2\",\"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 a signed fixed-decimal from a sign and an unsigned fixed-decimal\\n * @param self Sign\\n * @return New signed fixed-decimal\\n */\\n function unpack(PackedUFixed18 self) internal pure returns (UFixed18) {\\n return UFixed18.wrap(uint256(PackedUFixed18.unwrap(self)));\\n }\\n}\\n\",\"keccak256\":\"0xa12f541b8e2a2a3d5efeebdb3f39caec1db69cb7ce9ad5c6de12235a55a47a2d\",\"license\":\"Apache-2.0\"},\"@equilibria/root/number/types/UFixed18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"./Fixed18.sol\\\";\\nimport \\\"./PackedUFixed18.sol\\\";\\n\\n/// @dev UFixed18 type\\ntype UFixed18 is uint256;\\nusing UFixed18Lib for UFixed18 global;\\ntype UFixed18Storage is bytes32;\\nusing UFixed18StorageLib for UFixed18Storage global;\\n\\n/**\\n * @title UFixed18Lib\\n * @notice Library for the unsigned fixed-decimal type.\\n */\\nlibrary UFixed18Lib {\\n error UFixed18UnderflowError(int256 value);\\n error UFixed18PackingOverflowError(uint256 value);\\n\\n uint256 private constant BASE = 1e18;\\n UFixed18 public constant ZERO = UFixed18.wrap(0);\\n UFixed18 public constant ONE = UFixed18.wrap(BASE);\\n UFixed18 public constant MAX = UFixed18.wrap(type(uint256).max);\\n\\n /**\\n * @notice Creates a unsigned fixed-decimal from a signed fixed-decimal\\n * @param a Signed fixed-decimal\\n * @return New unsigned fixed-decimal\\n */\\n function from(Fixed18 a) internal pure returns (UFixed18) {\\n int256 value = Fixed18.unwrap(a);\\n if (value < 0) revert UFixed18UnderflowError(value);\\n return UFixed18.wrap(uint256(value));\\n }\\n\\n /**\\n * @notice Creates a unsigned fixed-decimal from a unsigned integer\\n * @param a Unsigned number\\n * @return New unsigned fixed-decimal\\n */\\n function from(uint256 a) internal pure returns (UFixed18) {\\n return UFixed18.wrap(a * BASE);\\n }\\n\\n /**\\n * @notice Creates a packed unsigned fixed-decimal from an unsigned fixed-decimal\\n * @param a unsigned fixed-decimal\\n * @return New packed unsigned fixed-decimal\\n */\\n function pack(UFixed18 a) internal pure returns (PackedUFixed18) {\\n uint256 value = UFixed18.unwrap(a);\\n if (value > type(uint128).max) revert UFixed18PackingOverflowError(value);\\n return PackedUFixed18.wrap(uint128(value));\\n }\\n\\n /**\\n * @notice Returns whether the unsigned fixed-decimal is equal to zero.\\n * @param a Unsigned fixed-decimal\\n * @return Whether the unsigned fixed-decimal is zero.\\n */\\n function isZero(UFixed18 a) internal pure returns (bool) {\\n return UFixed18.unwrap(a) == 0;\\n }\\n\\n /**\\n * @notice Adds two unsigned fixed-decimals `a` and `b` together\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Resulting summed unsigned fixed-decimal\\n */\\n function add(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) + UFixed18.unwrap(b));\\n }\\n\\n /**\\n * @notice Subtracts unsigned fixed-decimal `b` from `a`\\n * @param a Unsigned fixed-decimal to subtract from\\n * @param b Unsigned fixed-decimal to subtract\\n * @return Resulting subtracted unsigned fixed-decimal\\n */\\n function sub(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) - UFixed18.unwrap(b));\\n }\\n\\n /**\\n * @notice Multiplies two unsigned fixed-decimals `a` and `b` together\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Resulting multiplied unsigned fixed-decimal\\n */\\n function mul(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) * UFixed18.unwrap(b) / BASE);\\n }\\n\\n /**\\n * @notice Divides unsigned fixed-decimal `a` by `b`\\n * @param a Unsigned fixed-decimal to divide\\n * @param b Unsigned fixed-decimal to divide by\\n * @return Resulting divided unsigned fixed-decimal\\n */\\n function div(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) * BASE / UFixed18.unwrap(b));\\n }\\n\\n /**\\n * @notice Divides unsigned fixed-decimal `a` by `b`\\n * @dev Does not revert on divide-by-0, instead returns `ONE` for `0/0` and `MAX` for `n/0`.\\n * @param a Unsigned fixed-decimal to divide\\n * @param b Unsigned fixed-decimal to divide by\\n * @return Resulting divided unsigned fixed-decimal\\n */\\n function unsafeDiv(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n if (isZero(b)) {\\n return isZero(a) ? ONE : MAX;\\n } else {\\n return div(a, b);\\n }\\n }\\n\\n /**\\n * @notice Computes a * b / c without loss of precision due to BASE conversion\\n * @param a First unsigned fixed-decimal\\n * @param b Unsigned number to multiply by\\n * @param c Unsigned number to divide by\\n * @return Resulting computation\\n */\\n function muldiv(UFixed18 a, uint256 b, uint256 c) internal pure returns (UFixed18) {\\n return muldiv(a, UFixed18.wrap(b), UFixed18.wrap(c));\\n }\\n\\n /**\\n * @notice Computes a * b / c without loss of precision due to BASE conversion\\n * @param a First unsigned fixed-decimal\\n * @param b Unsigned fixed-decimal to multiply by\\n * @param c Unsigned fixed-decimal to divide by\\n * @return Resulting computation\\n */\\n function muldiv(UFixed18 a, UFixed18 b, UFixed18 c) internal pure returns (UFixed18) {\\n return UFixed18.wrap(UFixed18.unwrap(a) * UFixed18.unwrap(b) / UFixed18.unwrap(c));\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is equal to `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is equal to `b`\\n */\\n function eq(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return compare(a, b) == 1;\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is greater than `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is greater than `b`\\n */\\n function gt(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return compare(a, b) == 2;\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is less than `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is less than `b`\\n */\\n function lt(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return compare(a, b) == 0;\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is greater than or equal to `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is greater than or equal to `b`\\n */\\n function gte(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return gt(a, b) || eq(a, b);\\n }\\n\\n /**\\n * @notice Returns whether unsigned fixed-decimal `a` is less than or equal to `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Whether `a` is less than or equal to `b`\\n */\\n function lte(UFixed18 a, UFixed18 b) internal pure returns (bool) {\\n return lt(a, b) || eq(a, b);\\n }\\n\\n /**\\n * @notice Compares the unsigned fixed-decimals `a` and `b`\\n * @dev Returns: 2 for greater than\\n * 1 for equal to\\n * 0 for less than\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Compare result of `a` and `b`\\n */\\n function compare(UFixed18 a, UFixed18 b) internal pure returns (uint256) {\\n (uint256 au, uint256 bu) = (UFixed18.unwrap(a), UFixed18.unwrap(b));\\n if (au > bu) return 2;\\n if (au < bu) return 0;\\n return 1;\\n }\\n\\n /**\\n * @notice Returns a unsigned fixed-decimal representing the ratio of `a` over `b`\\n * @param a First unsigned number\\n * @param b Second unsigned number\\n * @return Ratio of `a` over `b`\\n */\\n function ratio(uint256 a, uint256 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(a * BASE / b);\\n }\\n\\n /**\\n * @notice Returns the minimum of unsigned fixed-decimals `a` and `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Minimum of `a` and `b`\\n */\\n function min(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(Math.min(UFixed18.unwrap(a), UFixed18.unwrap(b)));\\n }\\n\\n /**\\n * @notice Returns the maximum of unsigned fixed-decimals `a` and `b`\\n * @param a First unsigned fixed-decimal\\n * @param b Second unsigned fixed-decimal\\n * @return Maximum of `a` and `b`\\n */\\n function max(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\\n return UFixed18.wrap(Math.max(UFixed18.unwrap(a), UFixed18.unwrap(b)));\\n }\\n\\n /**\\n * @notice Converts the unsigned fixed-decimal into an integer, truncating any decimal portion\\n * @param a Unsigned fixed-decimal\\n * @return Truncated unsigned number\\n */\\n function truncate(UFixed18 a) internal pure returns (uint256) {\\n return UFixed18.unwrap(a) / BASE;\\n }\\n}\\n\\nlibrary UFixed18StorageLib {\\n function read(UFixed18Storage self) internal view returns (UFixed18 value) {\\n assembly {\\n value := sload(self)\\n }\\n }\\n\\n function store(UFixed18Storage self, UFixed18 value) internal {\\n assembly {\\n sstore(self, value)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8ebef1e6c717f565b9ed545a876b5692b4007e6485c99f39d363f7405e591792\",\"license\":\"Apache-2.0\"},\"@equilibria/root/token/types/Token18.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../../number/types/UFixed18.sol\\\";\\n\\n/// @dev Token18\\ntype Token18 is address;\\nusing Token18Lib for Token18 global;\\ntype Token18Storage is bytes32;\\nusing Token18StorageLib for Token18Storage global;\\n\\n/**\\n * @title Token18Lib\\n * @notice Library to manage 18-decimal ERC20s that is compliant with the fixed-decimal types.\\n * @dev Maintains significant gas savings over other Token implementations since no conversion take place\\n */\\nlibrary Token18Lib {\\n using SafeERC20 for IERC20;\\n\\n Token18 public constant ZERO = Token18.wrap(address(0));\\n\\n /**\\n * @notice Returns whether a token is the zero address\\n * @param self Token to check for\\n * @return Whether the token is the zero address\\n */\\n function isZero(Token18 self) internal pure returns (bool) {\\n return Token18.unwrap(self) == Token18.unwrap(ZERO);\\n }\\n\\n /**\\n * @notice Returns whether the two tokens are equal\\n * @param a First token to compare\\n * @param b Second token to compare\\n * @return Whether the two tokens are equal\\n */\\n function eq(Token18 a, Token18 b) internal pure returns (bool) {\\n return Token18.unwrap(a) == Token18.unwrap(b);\\n }\\n\\n /**\\n * @notice Approves `grantee` to spend infinite tokens from the caller\\n * @param self Token to transfer\\n * @param grantee Address to allow spending\\n */\\n function approve(Token18 self, address grantee) internal {\\n IERC20(Token18.unwrap(self)).safeApprove(grantee, type(uint256).max);\\n }\\n\\n /**\\n * @notice Approves `grantee` to spend `amount` tokens from the caller\\n * @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\":\"0x318b6f49c3225000baeeaeb6a7dde25799d7b5d966fcff2a87b52ddcfc3ae381\",\"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 * @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 * @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\":\"0x8371d28bc629762e0599ce5984b56431d90626cdfe2b770e92e9d8858d409bad\",\"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.5.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 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 /**\\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\",\"keccak256\":\"0xbbc8ac883ac3c0078ce5ad3e288fbb3ffcc8a30c3a98c0fda0114d64fc44fca2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a / b + (a % b == 0 ? 0 : 1);\\n }\\n}\\n\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\"},\"contracts/forwarder/Forwarder.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity 0.8.14;\\n\\nimport \\\"../interfaces/IForwarder.sol\\\";\\n\\n/**\\n * @title Forwarder\\n * @notice Facilitates collateral deposits to the protocol where the amount is supplied\\n * in USDC then wrapped as DSU before being deposited.\\n */\\ncontract Forwarder is IForwarder {\\n // @dev USDC stablecoin\\n Token6 public immutable USDC; // solhint-disable-line var-name-mixedcase\\n\\n // @dev DSU stablecoin\\n Token18 public immutable DSU; // solhint-disable-line var-name-mixedcase\\n\\n /// @dev Contract that wraps USDC to DSU\\n IBatcher public immutable batcher;\\n\\n /// @dev Contract managing state for collateral accounts in the protocol\\n ICollateral public immutable collateral;\\n\\n /**\\n * @notice Initializes the contract state\\n * @param usdc_ The USDC token contract address\\n * @param dsu_ The DSU token contract address\\n * @param batcher_ The USDC-to-DSU batcher contract address\\n * @param collateral_ The perennial collateral contract address\\n */\\n constructor(\\n Token6 usdc_,\\n Token18 dsu_,\\n IBatcher batcher_,\\n ICollateral collateral_\\n ) {\\n USDC = usdc_;\\n DSU = dsu_;\\n batcher = batcher_;\\n collateral = collateral_;\\n\\n USDC.approve(address(batcher));\\n DSU.approve(address(collateral));\\n }\\n\\n /**\\n * @notice Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU,\\n and deposits it as collateral to `account`'s `product` account\\n * @param account Account to deposit the collateral for\\n * @param product Product to credit the collateral to\\n * @param amount 18 decimals-normalized stablecoin (USDC, DSU) value of collateral to deposit\\n */\\n function wrapAndDeposit(\\n address account,\\n IProduct product,\\n UFixed18 amount\\n ) external {\\n USDC.pull(msg.sender, amount, true);\\n batcher.wrap(amount, address(this));\\n collateral.depositTo(account, product, amount);\\n emit WrapAndDeposit(account, product, amount);\\n }\\n}\\n\",\"keccak256\":\"0x72784ac75a6f1719f09f26b2cb4303081c2b1923630233baef1201a511cb7fa0\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/ICollateral.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"./IController.sol\\\";\\nimport \\\"./IProduct.sol\\\";\\n\\ninterface ICollateral {\\n event Deposit(address indexed user, IProduct indexed product, UFixed18 amount);\\n event Withdrawal(address indexed user, IProduct indexed product, UFixed18 amount);\\n event AccountSettle(IProduct indexed product, address indexed account, Fixed18 amount, UFixed18 newShortfall);\\n event ProductSettle(IProduct indexed product, UFixed18 protocolFee, UFixed18 productFee);\\n event Liquidation(address indexed user, IProduct indexed product, address liquidator, UFixed18 fee);\\n event ShortfallResolution(IProduct indexed product, UFixed18 amount);\\n event FeeClaim(address indexed account, UFixed18 amount);\\n\\n error CollateralCantLiquidate(UFixed18 totalMaintenance, UFixed18 totalCollateral);\\n error CollateralInsufficientCollateralError();\\n error CollateralUnderLimitError();\\n error CollateralZeroAddressError();\\n\\n function token() external view returns (Token18);\\n function fees(address account) external view returns (UFixed18);\\n function initialize(IController controller_) external;\\n function depositTo(address account, IProduct product, UFixed18 amount) external;\\n function withdrawTo(address account, IProduct product, UFixed18 amount) external;\\n function liquidate(address account, IProduct product) external;\\n function settleAccount(address account, Fixed18 amount) external;\\n function settleProduct(UFixed18 amount) external;\\n function collateral(address account, IProduct product) external view returns (UFixed18);\\n function collateral(IProduct product) external view returns (UFixed18);\\n function shortfall(IProduct product) external view returns (UFixed18);\\n function liquidatable(address account, IProduct product) external view returns (bool);\\n function liquidatableNext(address account, IProduct product) external view returns (bool);\\n function resolveShortfall(IProduct product, UFixed18 amount) external;\\n function claimFee() external;\\n}\\n\",\"keccak256\":\"0xa5e7fdda92702f748e6eb8701e522450035a98a05e5fc1cf66d51c52e397d914\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/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 \\\"./IProductProvider.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 /// @dev the address that is allowed to pause the coordinated products (0-address defaults to owner)\\n address pauser;\\n\\n /// @dev Whether the coordinated products are paused\\n bool paused;\\n }\\n\\n event CollateralUpdated(ICollateral newCollateral);\\n event IncentivizerUpdated(IIncentivizer newIncentivizer);\\n event ProductBeaconUpdated(IBeacon newProductBeacon);\\n event ProtocolFeeUpdated(UFixed18 newProtocolFee);\\n event MinFundingFeeUpdated(UFixed18 newMinFundingFee);\\n event LiquidationFeeUpdated(UFixed18 newLiquidationFee);\\n event IncentivizationFeeUpdated(UFixed18 newIncentivizationFee);\\n event MinCollateralUpdated(UFixed18 newMinCollateral);\\n event ProgramsPerProductUpdated(uint256 newProgramsPerProduct);\\n event CoordinatorPendingOwnerUpdated(uint256 indexed coordinatorId, address newPendingOwner);\\n event CoordinatorOwnerUpdated(uint256 indexed coordinatorId, address newOwner);\\n event CoordinatorTreasuryUpdated(uint256 indexed coordinatorId, address newTreasury);\\n event CoordinatorPauserUpdated(uint256 indexed coordinatorId, address pauser);\\n event CoordinatorPausedUpdated(uint256 indexed coordinatorId, bool paused);\\n event CoordinatorCreated(uint256 indexed coordinatorId, address owner);\\n event ProductCreated(IProduct indexed product, IProductProvider provider);\\n\\n error ControllerAlreadyInitializedError();\\n error ControllerNoZeroCoordinatorError();\\n error ControllerNotPauserError(uint256 coordinatorId);\\n error ControllerNotOwnerError(uint256 controllerId);\\n error ControllerNotPendingOwnerError(uint256 controllerId);\\n error ControllerInvalidProtocolFeeError();\\n error ControllerInvalidMinFundingFeeError();\\n error ControllerInvalidLiquidationFeeError();\\n error ControllerInvalidIncentivizationFeeError();\\n\\n function collateral() external view returns (ICollateral);\\n function incentivizer() external view returns (IIncentivizer);\\n function productBeacon() external view returns (IBeacon);\\n function coordinators(uint256 collateralId) external view returns (Coordinator memory);\\n function coordinatorFor(IProduct product) external view returns (uint256);\\n function protocolFee() external view returns (UFixed18);\\n function minFundingFee() external view returns (UFixed18);\\n function liquidationFee() external view returns (UFixed18);\\n function incentivizationFee() external view returns (UFixed18);\\n function minCollateral() external view returns (UFixed18);\\n function programsPerProduct() external view returns (uint256);\\n function initialize(ICollateral collateral_, IIncentivizer incentivizer_, IBeacon productBeacon_) external;\\n function createCoordinator(address coordinatorOwner) 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 updateCoordinatorPauser(uint256 coordinatorId, address newPauser) external;\\n function updateCoordinatorPaused(uint256 coordinatorId, bool newPaused) external;\\n function createProduct(uint256 coordinatorId, IProductProvider provider) external returns (IProduct);\\n function updateCollateral(ICollateral newCollateral) external;\\n function updateIncentivizer(IIncentivizer newIncentivizer) external;\\n function updateProductBeacon(IBeacon newProductBeacon) external;\\n function updateProtocolFee(UFixed18 newProtocolFee) external;\\n function updateMinFundingFee(UFixed18 newMinFundingFee) external;\\n function updateLiquidationFee(UFixed18 newLiquidationFee) external;\\n function updateIncentivizationFee(UFixed18 newIncentivizationFee) external;\\n function updateMinCollateral(UFixed18 newMinCollateral) external;\\n function updateProgramsPerProduct(uint256 newProductsPerProduct) external;\\n function 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 function pauser() external view returns (address);\\n function pauser(uint256 coordinatorId) external view returns (address);\\n function pauser(IProduct product) external view returns (address);\\n function paused() external view returns (bool);\\n function paused(uint256 coordinatorId) external view returns (bool);\\n function paused(IProduct product) external view returns (bool);\\n}\",\"keccak256\":\"0xe3e848c947097c36ac1ac1ee408c035aa5888a30112e99394a863a28fcfaf146\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IForwarder.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity 0.8.14;\\n\\nimport \\\"@equilibria/root/token/types/Token18.sol\\\";\\nimport \\\"@equilibria/root/token/types/Token6.sol\\\";\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\\\";\\nimport \\\"./ICollateral.sol\\\";\\n\\ninterface IForwarder {\\n event WrapAndDeposit(address indexed account, IProduct indexed product, UFixed18 amount);\\n\\n function USDC() external view returns (Token6); // solhint-disable-line func-name-mixedcase\\n function DSU() external view returns (Token18); // solhint-disable-line func-name-mixedcase\\n function batcher() external view returns (IBatcher);\\n function collateral() external view returns (ICollateral);\\n function wrapAndDeposit(address account, IProduct product, UFixed18 amount) external;\\n}\\n\",\"keccak256\":\"0x75e8884c05cb4382db715c7dce824dcd0bbb416db4267b6494ec5a0b6e1b68aa\",\"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 \\\"./types/ProgramInfo.sol\\\";\\nimport \\\"./IOracleProvider.sol\\\";\\nimport \\\"./IController.sol\\\";\\nimport \\\"./IProduct.sol\\\";\\n\\ninterface IIncentivizer {\\n event ProgramCreated(IProduct indexed product, uint256 indexed programId, uint256 coordinatorId, Token18 token, UFixed18 amountMaker, UFixed18 amountTaker, uint256 start, uint256 duration, 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\\n function programInfos(IProduct product, uint256 programId) external view returns (ProgramInfo memory);\\n function fees(Token18 token) external view returns (UFixed18);\\n function initialize(IController controller_) external;\\n function create(IProduct product, ProgramInfo calldata info) external returns (uint256);\\n function complete(IProduct product, uint256 programId) external;\\n function sync(IOracleProvider.OracleVersion memory currentOracleVersion) external;\\n function syncAccount(address account, IOracleProvider.OracleVersion memory currentOracleVersion) external;\\n function claim(IProduct product, uint256[] calldata programIds) external;\\n function claim(IProduct[] calldata products, uint256[][] calldata programIds) external;\\n function claimFee(Token18[] calldata tokens) external;\\n function active(IProduct product) external view returns (uint256);\\n function count(IProduct product) external view returns (uint256);\\n function unclaimed(IProduct product, address account, uint256 programId) external view returns (UFixed18);\\n function available(IProduct product, uint256 programId) external view returns (UFixed18);\\n function versionStarted(IProduct product, uint256 programId) external view returns (uint256);\\n function versionComplete(IProduct product, uint256 programId) external view returns (uint256);\\n function owner(IProduct product, uint256 programId) external view returns (address);\\n function treasury(IProduct product, uint256 programId) external view returns (address);\\n}\\n\",\"keccak256\":\"0x46f3cbdb6ff3214609d88069a18dae1d607833bcc92d67304955017cbd9f3f67\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IOracleProvider.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/Fixed18.sol\\\";\\n\\ninterface IOracleProvider {\\n /// @dev A singular oracle version with its corresponding data\\n struct OracleVersion {\\n /// @dev The iterative version\\n uint256 version;\\n\\n /// @dev the timestamp of the oracle update\\n uint256 timestamp;\\n\\n /// @dev The oracle price of the corresponding version\\n Fixed18 price;\\n }\\n\\n function sync() external returns (OracleVersion memory);\\n function currentVersion() external view returns (OracleVersion memory);\\n function atVersion(uint256 oracleVersion) external view returns (OracleVersion memory);\\n}\\n\",\"keccak256\":\"0xde0f20d468ba8b91addfc356e13f2c74a4dc8abe68be323942217c723775d9c1\",\"license\":\"Apache-2.0\"},\"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 \\\"./types/Position.sol\\\";\\nimport \\\"./types/PrePosition.sol\\\";\\nimport \\\"./types/Accumulator.sol\\\";\\nimport \\\"./IProductProvider.sol\\\";\\n\\ninterface IProduct {\\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\\n error ProductInsufficientLiquidityError(UFixed18 socializationFactor);\\n error ProductDoubleSidedError();\\n error ProductOverClosedError();\\n error ProductInsufficientCollateralError();\\n error ProductInLiquidationError();\\n error ProductMakerOverLimitError();\\n error ProductOracleBootstrappingError();\\n\\n function productProvider() external view returns (IProductProvider);\\n function initialize(IProductProvider productProvider_) external;\\n function settle() external;\\n function settleAccount(address account) external;\\n function openTake(UFixed18 amount) external;\\n function closeTake(UFixed18 amount) external;\\n function openMake(UFixed18 amount) external;\\n function closeMake(UFixed18 amount) external;\\n function closeAll(address account) external;\\n function maintenance(address account) external view returns (UFixed18);\\n function maintenanceNext(address account) external view returns (UFixed18);\\n function isClosed(address account) external view returns (bool);\\n function isLiquidating(address account) external view returns (bool);\\n function position(address account) external view returns (Position memory);\\n function pre(address account) external view returns (PrePosition memory);\\n function latestVersion() external view returns (uint256);\\n function positionAtVersion(uint256 oracleVersion) external view returns (Position memory);\\n function pre() external view returns (PrePosition memory);\\n function valueAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\\n function shareAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\\n function latestVersion(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x6daf998516f069ace15047ba59f3a3fe00394e82e01638a937e1bcaff16cd63e\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IProductProvider.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 \\\"./types/Position.sol\\\";\\nimport \\\"./IOracleProvider.sol\\\";\\n\\ninterface IProductProvider is IOracleProvider {\\n function oracle() external view returns (IOracleProvider);\\n function name() external view returns (string memory);\\n function symbol() external view returns (string memory);\\n function rate(Position memory position) external view returns (Fixed18);\\n function maintenance() external view returns (UFixed18);\\n function fundingFee() external view returns (UFixed18);\\n function makerFee() external view returns (UFixed18);\\n function takerFee() external view returns (UFixed18);\\n function makerLimit() external view returns (UFixed18);\\n}\\n\",\"keccak256\":\"0xeed08e4335ca553a639e6a77274df69c01413dd652e4d764f36ad7ae50016a8b\",\"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/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 \\\"./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 provider The parameter provider of the product\\n * @param toOracleVersion The oracle version to settle to\\n * @return Settled position at oracle version\\n * @return Fee accrued from opening or closing the position\\n * @return Whether a new position was settled\\n */\\n function settled(\\n Position memory self,\\n PrePosition memory pre,\\n IProductProvider provider,\\n IOracleProvider.OracleVersion memory toOracleVersion\\n ) internal view returns (Position memory, UFixed18, bool) {\\n return pre.canSettle(toOracleVersion) ? (next(self, pre), pre.computeFee(provider, toOracleVersion), true) : (self, UFixed18Lib.ZERO, false);\\n }\\n\\n /**\\n * @notice Returns the socialization factor for the current position\\n * @dev Socialization account for the case where `taker` > `maker` temporarily due to a liquidation\\n * on the maker side. This dampens the taker's exposure pro-rata to ensure that the maker side\\n * is never exposed over 1 x short.\\n * @param self The Position to operate on\\n * @return Socialization factor\\n */\\n function socializationFactor(Position memory self) internal pure returns (UFixed18) {\\n return self.taker.isZero() ? UFixed18Lib.ONE : UFixed18Lib.min(UFixed18Lib.ONE, self.maker.div(self.taker));\\n }\\n}\\n\",\"keccak256\":\"0x238013d5792bcca49c815845fbd815ccd4ae97f8994ab33359827bdcc769c16b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/PrePosition.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"./Position.sol\\\";\\nimport \\\"./ProductProvider.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 using ProductProviderLib for IProductProvider;\\n\\n /**\\n * @notice Returns whether there is no pending-settlement position delta\\n * @dev Can be \\\"empty\\\" even with a non-zero oracleVersion if a position is opened and\\n * closed in the same version netting out to a zero position delta\\n * @param self The struct to operate on\\n * @return Whether the pending-settlement position delta is empty\\n */\\n function isEmpty(PrePosition memory self) internal pure returns (bool) {\\n return self.openPosition.isEmpty() && self.closePosition.isEmpty();\\n }\\n\\n /**\\n * @notice Increments the maker side of the open position delta\\n * @dev Nets out open and close deltas to minimize the size of each\\n * @param self The struct to operate on\\n * @param currentVersion The current oracle version index\\n * @param amount The position amount to open\\n */\\n function openMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n self.openPosition.maker = self.openPosition.maker.add(amount);\\n self.oracleVersion = currentVersion;\\n _netMake(self);\\n }\\n\\n /**\\n * @notice Increments the maker side of the close position delta\\n * @dev Nets out open and close deltas to minimize the size of each\\n * @param self The struct to operate on\\n * @param currentVersion The current oracle version index\\n * @param amount The maker position amount to close\\n */\\n function closeMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n self.closePosition.maker = self.closePosition.maker.add(amount);\\n self.oracleVersion = currentVersion;\\n _netMake(self);\\n }\\n\\n /**\\n * @notice Increments the taker side of the open position delta\\n * @dev Nets out open and close deltas to minimize the size of each\\n * @param self The struct to operate on\\n * @param currentVersion The current oracle version index\\n * @param amount The taker position amount to open\\n */\\n function openTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n self.openPosition.taker = self.openPosition.taker.add(amount);\\n self.oracleVersion = currentVersion;\\n _netTake(self);\\n }\\n\\n /**\\n * @notice Increments the taker side of the close position delta\\n * @dev Nets out open and close deltas to minimize the size of each\\n * @param self The struct to operate on\\n * @param currentVersion The current oracle version index\\n * @param amount The taker position amount to close\\n */\\n function closeTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\\n self.closePosition.taker = self.closePosition.taker.add(amount);\\n self.oracleVersion = currentVersion;\\n _netTake(self);\\n }\\n\\n /**\\n * @notice Nets out the open and close on the maker side of the position delta\\n * @param self The struct to operate on\\n */\\n function _netMake(PrePosition storage self) private {\\n if (self.openPosition.maker.gt(self.closePosition.maker)) {\\n self.openPosition.maker = self.openPosition.maker.sub(self.closePosition.maker);\\n self.closePosition.maker = UFixed18Lib.ZERO;\\n } else {\\n self.closePosition.maker = self.closePosition.maker.sub(self.openPosition.maker);\\n self.openPosition.maker = UFixed18Lib.ZERO;\\n }\\n }\\n\\n /**\\n * @notice Nets out the open and close on the taker side of the position delta\\n * @param self The struct to operate on\\n */\\n function _netTake(PrePosition storage self) private {\\n if (self.openPosition.taker.gt(self.closePosition.taker)) {\\n self.openPosition.taker = self.openPosition.taker.sub(self.closePosition.taker);\\n self.closePosition.taker = UFixed18Lib.ZERO;\\n } else {\\n self.closePosition.taker = self.closePosition.taker.sub(self.openPosition.taker);\\n self.openPosition.taker = UFixed18Lib.ZERO;\\n }\\n }\\n\\n /**\\n * @notice Returns whether the the pending position delta can be settled at version `toOracleVersion`\\n * @dev Pending-settlement positions deltas can be settled (1) oracle version after they are recorded\\n * @param self The struct to operate on\\n * @param toOracleVersion The potential oracle version to settle\\n * @return Whether the position delta can be settled\\n */\\n function canSettle(\\n PrePosition memory self,\\n IOracleProvider.OracleVersion memory toOracleVersion\\n ) internal pure returns (bool) {\\n return !isEmpty(self) && toOracleVersion.version > self.oracleVersion;\\n }\\n\\n /**\\n * @notice Computes the fee incurred for opening or closing the pending-settlement position\\n * @param self The struct to operate on\\n * @param provider The parameter provider of the product\\n * @param toOracleVersion The oracle version at which settlement takes place\\n * @return positionFee The maker / taker fee incurred\\n */\\n function computeFee(\\n PrePosition memory self,\\n IProductProvider provider,\\n IOracleProvider.OracleVersion memory toOracleVersion\\n ) internal view returns (UFixed18) {\\n Position memory positionDelta = self.openPosition.add(self.closePosition);\\n\\n (UFixed18 makerNotional, UFixed18 takerNotional) = (\\n Fixed18Lib.from(positionDelta.maker).mul(toOracleVersion.price).abs(),\\n Fixed18Lib.from(positionDelta.taker).mul(toOracleVersion.price).abs()\\n );\\n\\n return makerNotional.mul(provider.safeMakerFee()).add(takerNotional.mul(provider.safeTakerFee()));\\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\":\"0xdf84172a254686f8cd721cd0c25f56e24a6f423f7ab780e7aa19bbf27352b392\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/ProductProvider.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.13;\\n\\nimport \\\"@equilibria/root/number/types/UFixed18.sol\\\";\\nimport \\\"../IProductProvider.sol\\\";\\nimport \\\"../IController.sol\\\";\\n\\n/**\\n * @title ProductProviderLib\\n * @notice Library that adds a safeguard wrapper to certain product parameters.\\n * @dev Product providers are semi-untrusted as they contain custom code from the product owners. Owners\\n * have full control over this parameter-setting code, however there are some \\\"known ranges\\\" that\\n * a parameter cannot be outside of (i.e. a fee being over 100%).\\n */\\nlibrary ProductProviderLib {\\n /**\\n * @notice Returns the minimum funding fee parameter with a capped range for safety\\n * @dev Caps controller.minFundingFee() <= self.minFundingFee() <= 1\\n * @param self The parameter provider to operate on\\n * @param controller The protocol Factory contract\\n * @return Safe minimum funding fee parameter\\n */\\n function safeFundingFee(IProductProvider self, IController controller) internal view returns (UFixed18) {\\n return self.fundingFee().max(controller.minFundingFee()).min(UFixed18Lib.ONE);\\n }\\n\\n /**\\n * @notice Returns the maker fee parameter with a capped range for safety\\n * @dev Caps self.makerFee() <= 1\\n * @param self The parameter provider to operate on\\n * @return Safe maker fee parameter\\n */\\n function safeMakerFee(IProductProvider self) internal view returns (UFixed18) {\\n return self.makerFee().min(UFixed18Lib.ONE);\\n }\\n\\n /**\\n * @notice Returns the taker fee parameter with a capped range for safety\\n * @dev Caps self.takerFee() <= 1\\n * @param self The parameter provider to operate on\\n * @return Safe taker fee parameter\\n */\\n function safeTakerFee(IProductProvider self) internal view returns (UFixed18) {\\n return self.takerFee().min(UFixed18Lib.ONE);\\n }\\n}\\n\",\"keccak256\":\"0x70f535ebe9b53f5ad94761e6e3da2b96ec261dce1c6c318e1f70b4e9e12b92b7\",\"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 /// @dev Reward ERC20 token contract\\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\":\"0x33b20b5688a58a81dad95dedd1743ff346c5724abd711150c9b33ab9addafb3c\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x6101006040523480156200001257600080fd5b5060405162001ee538038062001ee583398181016040528101906200003891906200075e565b8373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508273ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff16815250506200013c60c05160805173ffffffffffffffffffffffffffffffffffffffff166200017a60201b620003641790919060201c565b6200017060e05160a05173ffffffffffffffffffffffffffffffffffffffff16620001d060201b620003b31790919060201c565b5050505062000c90565b620001cc817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff166200022660201b62000402179092919060201c565b5050565b62000222817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff166200022660201b62000402179092919060201c565b5050565b6000811480620002b6575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b815260040162000270929190620007e1565b602060405180830381865afa1580156200028e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002b4919062000849565b145b620002f8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002ef9062000902565b60405180910390fd5b620003838363095ea7b360e01b84846040516024016200031a92919062000935565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506200038860201b60201c565b505050565b6000620003f1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200045c60201b62000551179092919060201c565b90506000815111156200045757808060200190518101906200041491906200099f565b62000456576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200044d9062000a47565b60405180910390fd5b5b505050565b60606200047384846000856200047c60201b60201c565b90509392505050565b606082471015620004c4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004bb9062000adf565b60405180910390fd5b620004d585620005aa60201b60201c565b62000517576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200050e9062000b51565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405162000542919062000bf6565b60006040518083038185875af1925050503d806000811462000581576040519150601f19603f3d011682016040523d82523d6000602084013e62000586565b606091505b50915091506200059e828286620005cd60201b60201c565b92505050949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608315620005df5782905062000632565b600083511115620005f35782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000629919062000c6c565b60405180910390fd5b9392505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200066b826200063e565b9050919050565b6200067d816200065e565b81146200068957600080fd5b50565b6000815190506200069d8162000672565b92915050565b620006ae816200065e565b8114620006ba57600080fd5b50565b600081519050620006ce81620006a3565b92915050565b6000620006e1826200065e565b9050919050565b620006f381620006d4565b8114620006ff57600080fd5b50565b6000815190506200071381620006e8565b92915050565b600062000726826200065e565b9050919050565b620007388162000719565b81146200074457600080fd5b50565b60008151905062000758816200072d565b92915050565b600080600080608085870312156200077b576200077a62000639565b5b60006200078b878288016200068c565b94505060206200079e87828801620006bd565b9350506040620007b18782880162000702565b9250506060620007c48782880162000747565b91505092959194509250565b620007db816200065e565b82525050565b6000604082019050620007f86000830185620007d0565b620008076020830184620007d0565b9392505050565b6000819050919050565b62000823816200080e565b81146200082f57600080fd5b50565b600081519050620008438162000818565b92915050565b60006020828403121562000862576200086162000639565b5b6000620008728482850162000832565b91505092915050565b600082825260208201905092915050565b7f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60008201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000602082015250565b6000620008ea6036836200087b565b9150620008f7826200088c565b604082019050919050565b600060208201905081810360008301526200091d81620008db565b9050919050565b6200092f816200080e565b82525050565b60006040820190506200094c6000830185620007d0565b6200095b602083018462000924565b9392505050565b60008115159050919050565b620009798162000962565b81146200098557600080fd5b50565b60008151905062000999816200096e565b92915050565b600060208284031215620009b857620009b762000639565b5b6000620009c88482850162000988565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b600062000a2f602a836200087b565b915062000a3c82620009d1565b604082019050919050565b6000602082019050818103600083015262000a628162000a20565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600062000ac76026836200087b565b915062000ad48262000a69565b604082019050919050565b6000602082019050818103600083015262000afa8162000ab8565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600062000b39601d836200087b565b915062000b468262000b01565b602082019050919050565b6000602082019050818103600083015262000b6c8162000b2a565b9050919050565b600081519050919050565b600081905092915050565b60005b8381101562000ba957808201518184015260208101905062000b8c565b8381111562000bb9576000848401525b50505050565b600062000bcc8262000b73565b62000bd8818562000b7e565b935062000bea81856020860162000b89565b80840191505092915050565b600062000c04828462000bbf565b915081905092915050565b600081519050919050565b6000601f19601f8301169050919050565b600062000c388262000c0f565b62000c4481856200087b565b935062000c5681856020860162000b89565b62000c618162000c1a565b840191505092915050565b6000602082019050818103600083015262000c88818462000c2b565b905092915050565b60805160a05160c05160e05161120662000cdf60003960008181610201015261034201526000818161010201526101740152600061031e01526000818161012d01526102fa01526112066000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806389a302711161005057806389a30271146100a6578063a2060bcf146100c4578063d8dfeb45146100e257610067565b8063025a3a291461006c57806344bc170a1461008a575b600080fd5b610074610100565b6040516100819190610986565b60405180910390f35b6100a4600480360381019061009f9190610a58565b610124565b005b6100ae6102f8565b6040516100bb9190610acc565b60405180910390f35b6100cc61031c565b6040516100d99190610af6565b60405180910390f35b6100ea610340565b6040516100f79190610b32565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b610172338260017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610569909392919063ffffffff16565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166313bac82082306040518363ffffffff1660e01b81526004016101cd929190610b8d565b600060405180830381600087803b1580156101e757600080fd5b505af11580156101fb573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f213159c8484846040518463ffffffff1660e01b815260040161025c93929190610bd7565b600060405180830381600087803b15801561027657600080fd5b505af115801561028a573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8e7ce60e353ab1a4cc59ca4782bdc69e0565713d1824dce27e0de2e362147ed0836040516102eb9190610c0e565b60405180910390a3505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6103af817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff166104029092919063ffffffff16565b5050565b6103fe817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff166104029092919063ffffffff16565b5050565b600081148061048c575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401610449929190610c29565b602060405180830381865afa158015610466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048a9190610c7e565b145b6104cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104c290610d2e565b60405180910390fd5b61054c8363095ea7b360e01b84846040516024016104ea929190610d5d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506105a5565b505050565b6060610560848460008561066c565b90509392505050565b61059f83306105788585610780565b8773ffffffffffffffffffffffffffffffffffffffff166107b5909392919063ffffffff16565b50505050565b6000610607826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166105519092919063ffffffff16565b905060008151111561066757808060200190518101906106279190610dbe565b610666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065d90610e5d565b60405180910390fd5b5b505050565b6060824710156106b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a890610eef565b60405180910390fd5b6106ba8561083e565b6106f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106f090610f5b565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516107229190610ff5565b60006040518083038185875af1925050503d806000811461075f576040519150601f19603f3d011682016040523d82523d6000602084013e610764565b606091505b5091509150610774828286610861565b92505050949350505050565b60008161079d5764e8d4a5100083610798919061106a565b6107ad565b6107ac8364e8d4a510006108c8565b5b905092915050565b610838846323b872dd60e01b8585856040516024016107d69392919061109b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506105a5565b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608315610871578290506108c1565b6000835111156108845782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b89190611127565b60405180910390fd5b9392505050565b60008082846108d79190611149565b146108e35760016108e6565b60005b60ff1682846108f5919061106a565b6108ff919061117a565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061094c61094761094284610907565b610927565b610907565b9050919050565b600061095e82610931565b9050919050565b600061097082610953565b9050919050565b61098081610965565b82525050565b600060208201905061099b6000830184610977565b92915050565b600080fd5b60006109b182610907565b9050919050565b6109c1816109a6565b81146109cc57600080fd5b50565b6000813590506109de816109b8565b92915050565b60006109ef826109a6565b9050919050565b6109ff816109e4565b8114610a0a57600080fd5b50565b600081359050610a1c816109f6565b92915050565b6000819050919050565b610a3581610a22565b8114610a4057600080fd5b50565b600081359050610a5281610a2c565b92915050565b600080600060608486031215610a7157610a706109a1565b5b6000610a7f868287016109cf565b9350506020610a9086828701610a0d565b9250506040610aa186828701610a43565b9150509250925092565b6000610ab682610953565b9050919050565b610ac681610aab565b82525050565b6000602082019050610ae16000830184610abd565b92915050565b610af081610aab565b82525050565b6000602082019050610b0b6000830184610ae7565b92915050565b6000610b1c82610953565b9050919050565b610b2c81610b11565b82525050565b6000602082019050610b476000830184610b23565b92915050565b6000610b68610b63610b5e84610a22565b610927565b610a22565b9050919050565b610b7881610b4d565b82525050565b610b87816109a6565b82525050565b6000604082019050610ba26000830185610b6f565b610baf6020830184610b7e565b9392505050565b6000610bc182610953565b9050919050565b610bd181610bb6565b82525050565b6000606082019050610bec6000830186610b7e565b610bf96020830185610bc8565b610c066040830184610b6f565b949350505050565b6000602082019050610c236000830184610b6f565b92915050565b6000604082019050610c3e6000830185610b7e565b610c4b6020830184610b7e565b9392505050565b610c5b81610a22565b8114610c6657600080fd5b50565b600081519050610c7881610c52565b92915050565b600060208284031215610c9457610c936109a1565b5b6000610ca284828501610c69565b91505092915050565b600082825260208201905092915050565b7f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60008201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000602082015250565b6000610d18603683610cab565b9150610d2382610cbc565b604082019050919050565b60006020820190508181036000830152610d4781610d0b565b9050919050565b610d5781610a22565b82525050565b6000604082019050610d726000830185610b7e565b610d7f6020830184610d4e565b9392505050565b60008115159050919050565b610d9b81610d86565b8114610da657600080fd5b50565b600081519050610db881610d92565b92915050565b600060208284031215610dd457610dd36109a1565b5b6000610de284828501610da9565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000610e47602a83610cab565b9150610e5282610deb565b604082019050919050565b60006020820190508181036000830152610e7681610e3a565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000610ed9602683610cab565b9150610ee482610e7d565b604082019050919050565b60006020820190508181036000830152610f0881610ecc565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000610f45601d83610cab565b9150610f5082610f0f565b602082019050919050565b60006020820190508181036000830152610f7481610f38565b9050919050565b600081519050919050565b600081905092915050565b60005b83811015610faf578082015181840152602081019050610f94565b83811115610fbe576000848401525b50505050565b6000610fcf82610f7b565b610fd98185610f86565b9350610fe9818560208601610f91565b80840191505092915050565b60006110018284610fc4565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061107582610a22565b915061108083610a22565b9250826110905761108f61100c565b5b828204905092915050565b60006060820190506110b06000830186610b7e565b6110bd6020830185610b7e565b6110ca6040830184610d4e565b949350505050565b600081519050919050565b6000601f19601f8301169050919050565b60006110f9826110d2565b6111038185610cab565b9350611113818560208601610f91565b61111c816110dd565b840191505092915050565b6000602082019050818103600083015261114181846110ee565b905092915050565b600061115482610a22565b915061115f83610a22565b92508261116f5761116e61100c565b5b828206905092915050565b600061118582610a22565b915061119083610a22565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156111c5576111c461103b565b5b82820190509291505056fea264697066735822122043b005e58cdede1a486b87b634a8466f836da6a95ea3757299b29fbde406180c64736f6c634300080e0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c806389a302711161005057806389a30271146100a6578063a2060bcf146100c4578063d8dfeb45146100e257610067565b8063025a3a291461006c57806344bc170a1461008a575b600080fd5b610074610100565b6040516100819190610986565b60405180910390f35b6100a4600480360381019061009f9190610a58565b610124565b005b6100ae6102f8565b6040516100bb9190610acc565b60405180910390f35b6100cc61031c565b6040516100d99190610af6565b60405180910390f35b6100ea610340565b6040516100f79190610b32565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b610172338260017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610569909392919063ffffffff16565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166313bac82082306040518363ffffffff1660e01b81526004016101cd929190610b8d565b600060405180830381600087803b1580156101e757600080fd5b505af11580156101fb573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f213159c8484846040518463ffffffff1660e01b815260040161025c93929190610bd7565b600060405180830381600087803b15801561027657600080fd5b505af115801561028a573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8e7ce60e353ab1a4cc59ca4782bdc69e0565713d1824dce27e0de2e362147ed0836040516102eb9190610c0e565b60405180910390a3505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6103af817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff166104029092919063ffffffff16565b5050565b6103fe817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff166104029092919063ffffffff16565b5050565b600081148061048c575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401610449929190610c29565b602060405180830381865afa158015610466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048a9190610c7e565b145b6104cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104c290610d2e565b60405180910390fd5b61054c8363095ea7b360e01b84846040516024016104ea929190610d5d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506105a5565b505050565b6060610560848460008561066c565b90509392505050565b61059f83306105788585610780565b8773ffffffffffffffffffffffffffffffffffffffff166107b5909392919063ffffffff16565b50505050565b6000610607826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166105519092919063ffffffff16565b905060008151111561066757808060200190518101906106279190610dbe565b610666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065d90610e5d565b60405180910390fd5b5b505050565b6060824710156106b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a890610eef565b60405180910390fd5b6106ba8561083e565b6106f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106f090610f5b565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516107229190610ff5565b60006040518083038185875af1925050503d806000811461075f576040519150601f19603f3d011682016040523d82523d6000602084013e610764565b606091505b5091509150610774828286610861565b92505050949350505050565b60008161079d5764e8d4a5100083610798919061106a565b6107ad565b6107ac8364e8d4a510006108c8565b5b905092915050565b610838846323b872dd60e01b8585856040516024016107d69392919061109b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506105a5565b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608315610871578290506108c1565b6000835111156108845782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b89190611127565b60405180910390fd5b9392505050565b60008082846108d79190611149565b146108e35760016108e6565b60005b60ff1682846108f5919061106a565b6108ff919061117a565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061094c61094761094284610907565b610927565b610907565b9050919050565b600061095e82610931565b9050919050565b600061097082610953565b9050919050565b61098081610965565b82525050565b600060208201905061099b6000830184610977565b92915050565b600080fd5b60006109b182610907565b9050919050565b6109c1816109a6565b81146109cc57600080fd5b50565b6000813590506109de816109b8565b92915050565b60006109ef826109a6565b9050919050565b6109ff816109e4565b8114610a0a57600080fd5b50565b600081359050610a1c816109f6565b92915050565b6000819050919050565b610a3581610a22565b8114610a4057600080fd5b50565b600081359050610a5281610a2c565b92915050565b600080600060608486031215610a7157610a706109a1565b5b6000610a7f868287016109cf565b9350506020610a9086828701610a0d565b9250506040610aa186828701610a43565b9150509250925092565b6000610ab682610953565b9050919050565b610ac681610aab565b82525050565b6000602082019050610ae16000830184610abd565b92915050565b610af081610aab565b82525050565b6000602082019050610b0b6000830184610ae7565b92915050565b6000610b1c82610953565b9050919050565b610b2c81610b11565b82525050565b6000602082019050610b476000830184610b23565b92915050565b6000610b68610b63610b5e84610a22565b610927565b610a22565b9050919050565b610b7881610b4d565b82525050565b610b87816109a6565b82525050565b6000604082019050610ba26000830185610b6f565b610baf6020830184610b7e565b9392505050565b6000610bc182610953565b9050919050565b610bd181610bb6565b82525050565b6000606082019050610bec6000830186610b7e565b610bf96020830185610bc8565b610c066040830184610b6f565b949350505050565b6000602082019050610c236000830184610b6f565b92915050565b6000604082019050610c3e6000830185610b7e565b610c4b6020830184610b7e565b9392505050565b610c5b81610a22565b8114610c6657600080fd5b50565b600081519050610c7881610c52565b92915050565b600060208284031215610c9457610c936109a1565b5b6000610ca284828501610c69565b91505092915050565b600082825260208201905092915050565b7f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60008201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000602082015250565b6000610d18603683610cab565b9150610d2382610cbc565b604082019050919050565b60006020820190508181036000830152610d4781610d0b565b9050919050565b610d5781610a22565b82525050565b6000604082019050610d726000830185610b7e565b610d7f6020830184610d4e565b9392505050565b60008115159050919050565b610d9b81610d86565b8114610da657600080fd5b50565b600081519050610db881610d92565b92915050565b600060208284031215610dd457610dd36109a1565b5b6000610de284828501610da9565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000610e47602a83610cab565b9150610e5282610deb565b604082019050919050565b60006020820190508181036000830152610e7681610e3a565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000610ed9602683610cab565b9150610ee482610e7d565b604082019050919050565b60006020820190508181036000830152610f0881610ecc565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000610f45601d83610cab565b9150610f5082610f0f565b602082019050919050565b60006020820190508181036000830152610f7481610f38565b9050919050565b600081519050919050565b600081905092915050565b60005b83811015610faf578082015181840152602081019050610f94565b83811115610fbe576000848401525b50505050565b6000610fcf82610f7b565b610fd98185610f86565b9350610fe9818560208601610f91565b80840191505092915050565b60006110018284610fc4565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061107582610a22565b915061108083610a22565b9250826110905761108f61100c565b5b828204905092915050565b60006060820190506110b06000830186610b7e565b6110bd6020830185610b7e565b6110ca6040830184610d4e565b949350505050565b600081519050919050565b6000601f19601f8301169050919050565b60006110f9826110d2565b6111038185610cab565b9350611113818560208601610f91565b61111c816110dd565b840191505092915050565b6000602082019050818103600083015261114181846110ee565b905092915050565b600061115482610a22565b915061115f83610a22565b92508261116f5761116e61100c565b5b828206905092915050565b600061118582610a22565b915061119083610a22565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156111c5576111c461103b565b5b82820190509291505056fea264697066735822122043b005e58cdede1a486b87b634a8466f836da6a95ea3757299b29fbde406180c64736f6c634300080e0033", "devdoc": { "kind": "dev", "methods": { + "constructor": { + "params": { + "batcher_": "The USDC-to-DSU batcher contract address", + "collateral_": "The perennial collateral contract address", + "dsu_": "The DSU token contract address", + "usdc_": "The USDC token contract address" + } + }, "wrapAndDeposit(address,address,uint256)": { "params": { "account": "Account to deposit the collateral for", @@ -209,8 +217,11 @@ "userdoc": { "kind": "user", "methods": { + "constructor": { + "notice": "Initializes the contract state" + }, "wrapAndDeposit(address,address,uint256)": { - "notice": "Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU, and deposits it as collateral to `account`'s `product` account " + "notice": "Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU, and deposits it as collateral to `account`'s `product` account" } }, "notice": "Facilitates collateral deposits to the protocol where the amount is supplied in USDC then wrapped as DSU before being deposited.", diff --git a/packages/perennial/deployments/kovan/solcInputs/b8274f6dd1d105c22962cd6c5ef4c924.json b/packages/perennial/deployments/kovan/solcInputs/b8274f6dd1d105c22962cd6c5ef4c924.json new file mode 100644 index 00000000..12689476 --- /dev/null +++ b/packages/perennial/deployments/kovan/solcInputs/b8274f6dd1d105c22962cd6c5ef4c924.json @@ -0,0 +1,303 @@ +{ + "language": "Solidity", + "sources": { + "contracts/collateral/Collateral.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"@equilibria/root/control/unstructured/UReentrancyGuard.sol\";\nimport \"../interfaces/ICollateral.sol\";\nimport \"./types/OptimisticLedger.sol\";\nimport \"../controller/UControllerProvider.sol\";\n\n/**\n * @title Collateral\n * @notice Manages logic and state for all collateral accounts in the protocol.\n */\ncontract Collateral is ICollateral, UInitializable, UControllerProvider, UReentrancyGuard {\n /// @dev ERC20 stablecoin for collateral\n Token18 public immutable token;\n\n /// @dev Per product collateral state\n mapping(IProduct => OptimisticLedger) private _products;\n\n /// @dev Protocol and product fees collected, but not yet claimed\n mapping(address => UFixed18) public fees;\n\n /**\n * @notice Initializes the immutable contract state\n * @dev Called at implementation instantiate and constant for that implementation.\n * @param token_ Collateral ERC20 stablecoin address\n */\n constructor(Token18 token_) {\n token = token_;\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 * @param controller_ Factory contract address\n */\n function initialize(IController controller_) external initializer(1) {\n __UControllerProvider__initialize(controller_);\n __UReentrancyGuard__initialize();\n }\n\n /**\n * @notice Deposits `amount` collateral from `msg.sender` to `account`'s `product`\n * account\n * @param account Account to deposit the collateral for\n * @param product Product to credit the collateral to\n * @param amount Amount of collateral to deposit\n */\n function depositTo(address account, IProduct product, UFixed18 amount)\n external\n nonReentrant\n notPausedProduct(product)\n notZeroAddress(account)\n isProduct(product)\n collateralInvariant(account, product)\n {\n _products[product].creditAccount(account, amount);\n token.pull(msg.sender, amount);\n\n emit Deposit(account, product, amount);\n }\n\n /**\n * @notice Withdraws `amount` collateral from `msg.sender`'s `product` account\n * and sends it to `account`\n * @param account Account to withdraw the collateral to\n * @param product Product to withdraw the collateral from\n * @param amount Amount of collateral to withdraw\n */\n function withdrawTo(address account, IProduct product, UFixed18 amount)\n external\n nonReentrant\n notPausedProduct(product)\n notZeroAddress(account)\n isProduct(product)\n settleForAccount(msg.sender, product)\n collateralInvariant(msg.sender, product)\n maintenanceInvariant(msg.sender, product)\n {\n _products[product].debitAccount(msg.sender, amount);\n token.push(account, amount);\n\n emit Withdrawal(msg.sender, product, amount);\n }\n\n /**\n * @notice Liquidates `account`'s `product` collateral account\n * @dev Account must be under-collateralized, fee returned immediately to `msg.sender`\n * @param account Account to liquidate\n * @param product Product to liquidate for\n */\n function liquidate(address account, IProduct product)\n external\n nonReentrant\n notPausedProduct(product)\n isProduct(product)\n settleForAccount(account, product)\n {\n UFixed18 totalMaintenance = product.maintenance(account);\n UFixed18 totalCollateral = collateral(account, product);\n\n if (!totalMaintenance.gt(totalCollateral))\n revert CollateralCantLiquidate(totalMaintenance, totalCollateral);\n\n product.closeAll(account);\n\n // claim fee\n UFixed18 liquidationFee = controller().liquidationFee();\n UFixed18 fee = UFixed18Lib.min(totalCollateral, totalMaintenance.mul(liquidationFee));\n\n _products[product].debitAccount(account, fee);\n token.push(msg.sender, fee);\n\n emit Liquidation(account, product, msg.sender, fee);\n }\n\n /**\n * @notice Credits `amount` to `account`'s collateral account\n * @dev Callable only by the corresponding product as part of the settlement flywheel.\n * Moves collateral within a product, any collateral leaving the product due to\n * fees has already been accounted for in the settleProduct flywheel.\n * Debits in excess of the account balance get recorded as shortfall, and can be\n * resolved by the product owner as needed.\n * @param account Account to credit\n * @param amount Amount to credit the account (can be negative)\n */\n function settleAccount(address account, Fixed18 amount) external onlyProduct {\n IProduct product = IProduct(msg.sender);\n\n UFixed18 newShortfall = _products[product].settleAccount(account, amount);\n\n emit AccountSettle(product, account, amount, newShortfall);\n }\n\n /**\n * @notice Debits `amount` from product's total collateral account\n * @dev Callable only by the corresponding product as part of the settlement flywheel\n * Removes collateral from the product as fees.\n * @param amount Amount to debit from the account\n */\n function settleProduct(UFixed18 amount) external onlyProduct {\n (IProduct product, IController controller) = (IProduct(msg.sender), controller());\n\n address protocolTreasury = controller.treasury();\n address productTreasury = controller.treasury(product);\n\n UFixed18 protocolFee = amount.mul(controller.protocolFee());\n UFixed18 productFee = amount.sub(protocolFee);\n\n _products[product].debit(amount);\n fees[protocolTreasury] = fees[protocolTreasury].add(protocolFee);\n fees[productTreasury] = fees[productTreasury].add(productFee);\n\n emit ProductSettle(product, protocolFee, productFee);\n }\n\n /**\n * @notice Returns the balance of `account`'s `product` collateral account\n * @param account Account to return for\n * @param product Product to return for\n * @return The balance of the collateral account\n */\n function collateral(address account, IProduct product) public view returns (UFixed18) {\n return _products[product].balances[account];\n }\n\n /**\n * @notice Returns the total balance of `product`'s collateral\n * @param product Product to return for\n * @return The total balance of collateral in the product\n */\n function collateral(IProduct product) external view returns (UFixed18) {\n return _products[product].total;\n }\n\n /**\n * @notice Returns the current shortfall of `product`'s collateral\n * @param product Product to return for\n * @return The current shortfall of the product\n */\n function shortfall(IProduct product) external view returns (UFixed18) {\n return _products[product].shortfall;\n }\n\n /**\n * @notice Returns whether `account`'s `product` collateral account can be liquidated\n * @param account Account to return for\n * @param product Product to return for\n * @return Whether the account can be liquidated\n */\n function liquidatable(address account, IProduct product) external view returns (bool) {\n return product.maintenance(account).gt(collateral(account, product));\n }\n\n /**\n * @notice Returns whether `account`'s `product` collateral account can be liquidated\n * after the next oracle version settlement\n * @dev Takes into account the current pre-position on the account\n * @param account Account to return for\n * @param product Product to return for\n * @return Whether the account can be liquidated\n */\n function liquidatableNext(address account, IProduct product) external view returns (bool) {\n return product.maintenanceNext(account).gt(collateral(account, product));\n }\n\n /**\n * @notice Injects additional collateral into a product to resolve shortfall\n * @dev Shortfall is a measure of settled insolvency in the market\n * This hook can be used by the product owner or an insurance fund to re-capitalize an insolvent market\n * @param product Product to resolve shortfall for\n * @param amount Amount of shortfall to resolve\n */\n function resolveShortfall(IProduct product, UFixed18 amount) external notPausedProduct(product) {\n _products[product].resolve(amount);\n token.pull(msg.sender, amount);\n\n emit ShortfallResolution(product, amount);\n }\n\n /**\n * @notice Claims all of `msg.sender`'s fees\n */\n function claimFee() external notPaused {\n UFixed18 amount = fees[msg.sender];\n\n fees[msg.sender] = UFixed18Lib.ZERO;\n token.push(msg.sender, amount);\n\n emit FeeClaim(msg.sender, amount);\n }\n\n /// @dev Ensure that the address is non-zero\n modifier notZeroAddress(address account) {\n if (account == address(0)) revert CollateralZeroAddressError();\n\n _;\n }\n\n /// @dev Ensure that the user has sufficient margin for both current and next maintenance\n modifier maintenanceInvariant(address account, IProduct product) {\n _;\n\n UFixed18 maintenance = product.maintenance(account);\n UFixed18 maintenanceNext = product.maintenanceNext(account);\n\n if (UFixed18Lib.max(maintenance, maintenanceNext).gt(collateral(account, product)))\n revert CollateralInsufficientCollateralError();\n }\n\n /// @dev Ensure that the account is either empty or above the collateral minimum\n modifier collateralInvariant(address account, IProduct product) {\n _;\n\n UFixed18 accountCollateral = collateral(account, product);\n if (!accountCollateral.isZero() && accountCollateral.lt(controller().minCollateral()))\n revert CollateralUnderLimitError();\n }\n\n /// @dev Helper to fully settle an account's state\n modifier settleForAccount(address account, IProduct product) {\n product.settleAccount(account);\n\n _;\n }\n}\n" + }, + "@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 /// @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 }\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" + }, + "@equilibria/root/control/unstructured/UReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"./UInitializable.sol\";\nimport \"../../storage/UStorage.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n *\n * NOTE: This contract has been extended from the Open Zeppelin library to include an\n * unstructured storage pattern, so that it can be safely mixed in with upgradeable\n * contracts without affecting their storage patterns through inheritance.\n */\nabstract contract UReentrancyGuard is UInitializable {\n error UReentrancyGuardReentrantCallError();\n\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n /**\n * @dev unstructured storage slot for the reentrancy status\n */\n Uint256Storage private constant _status = Uint256Storage.wrap(keccak256(\"equilibria.root.UReentrancyGuard.status\"));\n\n /**\n * @dev Initializes the contract setting the status to _NOT_ENTERED.\n */\n function __UReentrancyGuard__initialize() internal onlyInitializer {\n _status.store(_NOT_ENTERED);\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n if (_status.read() == _ENTERED) revert UReentrancyGuardReentrantCallError();\n\n // Any calls to nonReentrant after this point will fail\n _status.store(_ENTERED);\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status.store(_NOT_ENTERED);\n }\n}\n" + }, + "contracts/interfaces/ICollateral.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@equilibria/root/number/types/Fixed18.sol\";\nimport \"@equilibria/root/token/types/Token18.sol\";\nimport \"./IController.sol\";\nimport \"./IProduct.sol\";\n\ninterface ICollateral {\n event Deposit(address indexed user, IProduct indexed product, UFixed18 amount);\n event Withdrawal(address indexed user, IProduct indexed product, UFixed18 amount);\n event AccountSettle(IProduct indexed product, address indexed account, Fixed18 amount, UFixed18 newShortfall);\n event ProductSettle(IProduct indexed product, UFixed18 protocolFee, UFixed18 productFee);\n event Liquidation(address indexed user, IProduct indexed product, address liquidator, UFixed18 fee);\n event ShortfallResolution(IProduct indexed product, UFixed18 amount);\n event FeeClaim(address indexed account, UFixed18 amount);\n\n error CollateralCantLiquidate(UFixed18 totalMaintenance, UFixed18 totalCollateral);\n error CollateralInsufficientCollateralError();\n error CollateralUnderLimitError();\n error CollateralZeroAddressError();\n\n function token() external view returns (Token18);\n function fees(address account) external view returns (UFixed18);\n function initialize(IController controller_) external;\n function depositTo(address account, IProduct product, UFixed18 amount) external;\n function withdrawTo(address account, IProduct product, UFixed18 amount) external;\n function liquidate(address account, IProduct product) external;\n function settleAccount(address account, Fixed18 amount) external;\n function settleProduct(UFixed18 amount) external;\n function collateral(address account, IProduct product) external view returns (UFixed18);\n function collateral(IProduct product) external view returns (UFixed18);\n function shortfall(IProduct product) external view returns (UFixed18);\n function liquidatable(address account, IProduct product) external view returns (bool);\n function liquidatableNext(address account, IProduct product) external view returns (bool);\n function resolveShortfall(IProduct product, UFixed18 amount) external;\n function claimFee() external;\n}\n" + }, + "contracts/collateral/types/OptimisticLedger.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\n\n/// @dev OptimisticLedger type\nstruct OptimisticLedger {\n /// @dev Individual account collateral balances\n mapping(address => UFixed18) balances;\n\n /// @dev Total ledger collateral balance\n UFixed18 total;\n\n /// @dev Total ledger collateral shortfall\n UFixed18 shortfall;\n}\nusing OptimisticLedgerLib for OptimisticLedger global;\n\n/**\n * @title OptimisticLedgerLib\n * @notice Library that manages a global vs account ledger where the global ledger is settled separately,\n * and ahead of, the user-level accounts.\n * @dev Ensures that no more collateral leaves the ledger than goes it, while allowing user-level accounts\n * to settle as a follow up step. Overdrafts on the user-level are accounted as \"shortall\". Shortfall\n * in the system is the quantity of insolvency that can be optionally resolved by the ledger owner.\n * Until the shortfall is resolved, collateral may be withdrawn from the ledger on a FCFS basis. However\n * once the ledger total has been depleted, users will not be able to withdraw even if they have non-zero\n * user level balances until the shortfall is resolved, recapitalizing the ledger.\n */\nlibrary OptimisticLedgerLib {\n /**\n * @notice Credits `account` with `amount` collateral\n * @param self The struct to operate on\n * @param account Account to credit collateral to\n * @param amount Amount of collateral to credit\n */\n function creditAccount(OptimisticLedger storage self, address account, UFixed18 amount) internal {\n self.balances[account] = self.balances[account].add(amount);\n self.total = self.total.add(amount);\n }\n\n /**\n * @notice Debits `account` `amount` collateral\n * @param self The struct to operate on\n * @param account Account to debit collateral from\n * @param amount Amount of collateral to debit\n */\n function debitAccount(OptimisticLedger storage self, address account, UFixed18 amount) internal {\n self.balances[account] = self.balances[account].sub(amount);\n self.total = self.total.sub(amount);\n }\n\n /**\n * @notice Credits `account` with `amount` collateral\n * @dev Funds come from inside the product, not totals are updated\n * Shortfall is created if more funds are debited from an account than exist\n * @param self The struct to operate on\n * @param account Account to credit collateral to\n * @param amount Amount of collateral to credit\n * @return newShortfall Any new shortfall incurred during this settlement\n */\n function settleAccount(OptimisticLedger storage self, address account, Fixed18 amount)\n internal returns (UFixed18 newShortfall) {\n Fixed18 newBalance = Fixed18Lib.from(self.balances[account]).add(amount);\n\n if (newBalance.sign() == -1) {\n newShortfall = newBalance.abs();\n newBalance = Fixed18Lib.ZERO;\n }\n\n self.balances[account] = newBalance.abs();\n self.shortfall = self.shortfall.add(newShortfall);\n }\n\n /**\n * @notice Debits ledger globally `amount` collateral\n * @dev Removes balance from total that is accounted for elsewhere (e.g. product-level accumulators)\n * @param self The struct to operate on\n * @param amount Amount of collateral to debit\n */\n function debit(OptimisticLedger storage self, UFixed18 amount) internal {\n self.total = self.total.sub(amount);\n }\n\n /**\n * @notice Reduces the amount of collateral shortfall in the ledger\n * @param self The struct to operate on\n * @param amount Amount of shortfall to resolve\n */\n function resolve(OptimisticLedger storage self, UFixed18 amount) internal {\n self.shortfall = self.shortfall.sub(amount);\n self.total = self.total.add(amount);\n }\n}\n" + }, + "contracts/controller/UControllerProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"@equilibria/root/storage/UStorage.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"../interfaces/IController.sol\";\nimport \"../interfaces/IProduct.sol\";\n\n/**\n * @title UControllerProvider\n * @notice Mix-in that manages a controller pointer and associated permissioning modifiers.\n * @dev Uses unstructured storage so that it is safe to mix-in to upgreadable contracts without modifying\n * their storage layout.\n */\nabstract contract UControllerProvider is UInitializable {\n error AlreadyInitializedError();\n error NotOwnerError(uint256 coordinatorId);\n error NotProductError(IProduct product);\n error NotCollateralError();\n error NotProductOwnerError(IProduct product);\n error PausedError();\n error InvalidControllerError();\n\n /// @dev The controller contract address\n AddressStorage private constant _controller = AddressStorage.wrap(keccak256(\"equilibria.perennial.UControllerProvider.controller\"));\n function controller() public view returns (IController) { return IController(_controller.read()); }\n\n /**\n * @notice Initializes the contract state\n * @param controller_ Protocol Controller contract address\n */\n // solhint-disable-next-line func-name-mixedcase\n function __UControllerProvider__initialize(IController controller_) internal onlyInitializer {\n if (!Address.isContract(address(controller_))) revert InvalidControllerError();\n _controller.store(address(controller_));\n }\n\n /// @dev Only allow a valid product contract to call\n modifier onlyProduct {\n if (!controller().isProduct(IProduct(msg.sender))) revert NotProductError(IProduct(msg.sender));\n\n _;\n }\n\n /// @dev Verify that `product` is a valid product contract\n modifier isProduct(IProduct product) {\n if (!controller().isProduct(product)) revert NotProductError(product);\n\n _;\n }\n\n /// @dev Only allow the Collateral contract to call\n modifier onlyCollateral {\n if (msg.sender != address(controller().collateral())) revert NotCollateralError();\n\n _;\n }\n\n /// @dev Only allow the protocol owner to call\n modifier onlyOwner(uint256 coordinatorId) {\n if (msg.sender != controller().owner(coordinatorId)) revert NotOwnerError(coordinatorId);\n\n _;\n }\n\n /// @dev Only allow if the protocol is currently unpaused\n modifier notPaused() {\n if (controller().paused()) revert PausedError();\n\n _;\n }\n\n /// @dev Only allow if both the protocol and the product are currently unpaused\n modifier notPausedProduct(IProduct product) {\n if (controller().paused(product)) revert PausedError();\n\n _;\n }\n}\n" + }, + "@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" + }, + "@equilibria/root/storage/UStorage.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"../number/types/UFixed18.sol\";\n\ntype BoolStorage is bytes32;\nusing BoolStorageLib for BoolStorage global;\ntype Uint256Storage is bytes32;\nusing Uint256StorageLib for Uint256Storage global;\ntype Int256Storage is bytes32;\nusing Int256StorageLib for Int256Storage global;\ntype AddressStorage is bytes32;\nusing AddressStorageLib for AddressStorage global;\ntype Bytes32Storage is bytes32;\nusing Bytes32StorageLib for Bytes32Storage global;\n\nlibrary BoolStorageLib {\n function read(BoolStorage self) internal view returns (bool value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(BoolStorage self, bool value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n\nlibrary Uint256StorageLib {\n function read(Uint256Storage self) internal view returns (uint256 value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(Uint256Storage self, uint256 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n\nlibrary Int256StorageLib {\n function read(Int256Storage self) internal view returns (int256 value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(Int256Storage self, int256 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n\nlibrary AddressStorageLib {\n function read(AddressStorage self) internal view returns (address value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(AddressStorage self, address value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n\nlibrary Bytes32StorageLib {\n function read(Bytes32Storage self) internal view returns (bytes32 value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(Bytes32Storage self, bytes32 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n" + }, + "@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" + }, + "@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" + }, + "@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" + }, + "@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 a signed fixed-decimal from a sign and an unsigned fixed-decimal\n * @param self Sign\n * @return New signed fixed-decimal\n */\n function unpack(PackedUFixed18 self) internal pure returns (UFixed18) {\n return UFixed18.wrap(uint256(PackedUFixed18.unwrap(self)));\n }\n}\n" + }, + "@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" + }, + "@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 a signed fixed-decimal from a sign and an unsigned fixed-decimal\n * @param self Sign\n * @return New signed fixed-decimal\n */\n function unpack(PackedFixed18 self) internal pure returns (Fixed18) {\n return Fixed18.wrap(int256(PackedFixed18.unwrap(self)));\n }\n}\n" + }, + "@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 * @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" + }, + "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 \"./IProductProvider.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 /// @dev the address that is allowed to pause the coordinated products (0-address defaults to owner)\n address pauser;\n\n /// @dev Whether the coordinated products are paused\n bool paused;\n }\n\n event CollateralUpdated(ICollateral newCollateral);\n event IncentivizerUpdated(IIncentivizer newIncentivizer);\n event ProductBeaconUpdated(IBeacon newProductBeacon);\n event ProtocolFeeUpdated(UFixed18 newProtocolFee);\n event MinFundingFeeUpdated(UFixed18 newMinFundingFee);\n event LiquidationFeeUpdated(UFixed18 newLiquidationFee);\n event IncentivizationFeeUpdated(UFixed18 newIncentivizationFee);\n event MinCollateralUpdated(UFixed18 newMinCollateral);\n event ProgramsPerProductUpdated(uint256 newProgramsPerProduct);\n event CoordinatorPendingOwnerUpdated(uint256 indexed coordinatorId, address newPendingOwner);\n event CoordinatorOwnerUpdated(uint256 indexed coordinatorId, address newOwner);\n event CoordinatorTreasuryUpdated(uint256 indexed coordinatorId, address newTreasury);\n event CoordinatorPauserUpdated(uint256 indexed coordinatorId, address pauser);\n event CoordinatorPausedUpdated(uint256 indexed coordinatorId, bool paused);\n event CoordinatorCreated(uint256 indexed coordinatorId, address owner);\n event ProductCreated(IProduct indexed product, IProductProvider provider);\n\n error ControllerAlreadyInitializedError();\n error ControllerNoZeroCoordinatorError();\n error ControllerNotPauserError(uint256 coordinatorId);\n error ControllerNotOwnerError(uint256 controllerId);\n error ControllerNotPendingOwnerError(uint256 controllerId);\n error ControllerInvalidProtocolFeeError();\n error ControllerInvalidMinFundingFeeError();\n error ControllerInvalidLiquidationFeeError();\n error ControllerInvalidIncentivizationFeeError();\n\n function collateral() external view returns (ICollateral);\n function incentivizer() external view returns (IIncentivizer);\n function productBeacon() external view returns (IBeacon);\n function coordinators(uint256 collateralId) external view returns (Coordinator memory);\n function coordinatorFor(IProduct product) external view returns (uint256);\n function protocolFee() external view returns (UFixed18);\n function minFundingFee() external view returns (UFixed18);\n function liquidationFee() external view returns (UFixed18);\n function incentivizationFee() external view returns (UFixed18);\n function minCollateral() external view returns (UFixed18);\n function programsPerProduct() external view returns (uint256);\n function initialize(ICollateral collateral_, IIncentivizer incentivizer_, IBeacon productBeacon_) external;\n function createCoordinator(address coordinatorOwner) 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 updateCoordinatorPauser(uint256 coordinatorId, address newPauser) external;\n function updateCoordinatorPaused(uint256 coordinatorId, bool newPaused) external;\n function createProduct(uint256 coordinatorId, IProductProvider provider) external returns (IProduct);\n function updateCollateral(ICollateral newCollateral) external;\n function updateIncentivizer(IIncentivizer newIncentivizer) external;\n function updateProductBeacon(IBeacon newProductBeacon) external;\n function updateProtocolFee(UFixed18 newProtocolFee) external;\n function updateMinFundingFee(UFixed18 newMinFundingFee) external;\n function updateLiquidationFee(UFixed18 newLiquidationFee) external;\n function updateIncentivizationFee(UFixed18 newIncentivizationFee) external;\n function updateMinCollateral(UFixed18 newMinCollateral) external;\n function updateProgramsPerProduct(uint256 newProductsPerProduct) external;\n function 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 function pauser() external view returns (address);\n function pauser(uint256 coordinatorId) external view returns (address);\n function pauser(IProduct product) external view returns (address);\n function paused() external view returns (bool);\n function paused(uint256 coordinatorId) external view returns (bool);\n function paused(IProduct product) external view returns (bool);\n}" + }, + "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 \"./types/Position.sol\";\nimport \"./types/PrePosition.sol\";\nimport \"./types/Accumulator.sol\";\nimport \"./IProductProvider.sol\";\n\ninterface IProduct {\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\n error ProductInsufficientLiquidityError(UFixed18 socializationFactor);\n error ProductDoubleSidedError();\n error ProductOverClosedError();\n error ProductInsufficientCollateralError();\n error ProductInLiquidationError();\n error ProductMakerOverLimitError();\n error ProductOracleBootstrappingError();\n\n function productProvider() external view returns (IProductProvider);\n function initialize(IProductProvider productProvider_) external;\n function settle() external;\n function settleAccount(address account) external;\n function openTake(UFixed18 amount) external;\n function closeTake(UFixed18 amount) external;\n function openMake(UFixed18 amount) external;\n function closeMake(UFixed18 amount) external;\n function closeAll(address account) external;\n function maintenance(address account) external view returns (UFixed18);\n function maintenanceNext(address account) external view returns (UFixed18);\n function isClosed(address account) external view returns (bool);\n function isLiquidating(address account) external view returns (bool);\n function position(address account) external view returns (Position memory);\n function pre(address account) external view returns (PrePosition memory);\n function latestVersion() external view returns (uint256);\n function positionAtVersion(uint256 oracleVersion) external view returns (Position memory);\n function pre() external view returns (PrePosition memory);\n function valueAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\n function shareAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\n function latestVersion(address account) external view returns (uint256);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.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 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 /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/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" + }, + "@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" + }, + "@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" + }, + "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 \"./types/ProgramInfo.sol\";\nimport \"./IOracleProvider.sol\";\nimport \"./IController.sol\";\nimport \"./IProduct.sol\";\n\ninterface IIncentivizer {\n event ProgramCreated(IProduct indexed product, uint256 indexed programId, uint256 coordinatorId, Token18 token, UFixed18 amountMaker, UFixed18 amountTaker, uint256 start, uint256 duration, 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\n function programInfos(IProduct product, uint256 programId) external view returns (ProgramInfo memory);\n function fees(Token18 token) external view returns (UFixed18);\n function initialize(IController controller_) external;\n function create(IProduct product, ProgramInfo calldata info) external returns (uint256);\n function complete(IProduct product, uint256 programId) external;\n function sync(IOracleProvider.OracleVersion memory currentOracleVersion) external;\n function syncAccount(address account, IOracleProvider.OracleVersion memory currentOracleVersion) external;\n function claim(IProduct product, uint256[] calldata programIds) external;\n function claim(IProduct[] calldata products, uint256[][] calldata programIds) external;\n function claimFee(Token18[] calldata tokens) external;\n function active(IProduct product) external view returns (uint256);\n function count(IProduct product) external view returns (uint256);\n function unclaimed(IProduct product, address account, uint256 programId) external view returns (UFixed18);\n function available(IProduct product, uint256 programId) external view returns (UFixed18);\n function versionStarted(IProduct product, uint256 programId) external view returns (uint256);\n function versionComplete(IProduct product, uint256 programId) external view returns (uint256);\n function owner(IProduct product, uint256 programId) external view returns (address);\n function treasury(IProduct product, uint256 programId) external view returns (address);\n}\n" + }, + "contracts/interfaces/IProductProvider.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 \"./types/Position.sol\";\nimport \"./IOracleProvider.sol\";\n\ninterface IProductProvider is IOracleProvider {\n function oracle() external view returns (IOracleProvider);\n function name() external view returns (string memory);\n function symbol() external view returns (string memory);\n function rate(Position memory position) external view returns (Fixed18);\n function maintenance() external view returns (UFixed18);\n function fundingFee() external view returns (UFixed18);\n function makerFee() external view returns (UFixed18);\n function takerFee() external view returns (UFixed18);\n function makerLimit() external view returns (UFixed18);\n}\n" + }, + "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 \"./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 provider The parameter provider of the product\n * @param toOracleVersion The oracle version to settle to\n * @return Settled position at oracle version\n * @return Fee accrued from opening or closing the position\n * @return Whether a new position was settled\n */\n function settled(\n Position memory self,\n PrePosition memory pre,\n IProductProvider provider,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal view returns (Position memory, UFixed18, bool) {\n return pre.canSettle(toOracleVersion) ? (next(self, pre), pre.computeFee(provider, toOracleVersion), true) : (self, UFixed18Lib.ZERO, false);\n }\n\n /**\n * @notice Returns the socialization factor for the current position\n * @dev Socialization account for the case where `taker` > `maker` temporarily due to a liquidation\n * on the maker side. This dampens the taker's exposure pro-rata to ensure that the maker side\n * is never exposed over 1 x short.\n * @param self The Position to operate on\n * @return Socialization factor\n */\n function socializationFactor(Position memory self) internal pure returns (UFixed18) {\n return self.taker.isZero() ? UFixed18Lib.ONE : UFixed18Lib.min(UFixed18Lib.ONE, self.maker.div(self.taker));\n }\n}\n" + }, + "contracts/interfaces/types/PrePosition.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"./Position.sol\";\nimport \"./ProductProvider.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 using ProductProviderLib for IProductProvider;\n\n /**\n * @notice Returns whether there is no pending-settlement position delta\n * @dev Can be \"empty\" even with a non-zero oracleVersion if a position is opened and\n * closed in the same version netting out to a zero position delta\n * @param self The struct to operate on\n * @return Whether the pending-settlement position delta is empty\n */\n function isEmpty(PrePosition memory self) internal pure returns (bool) {\n return self.openPosition.isEmpty() && self.closePosition.isEmpty();\n }\n\n /**\n * @notice Increments the maker side of the open position delta\n * @dev Nets out open and close deltas to minimize the size of each\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @param amount The position amount to open\n */\n function openMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\n self.openPosition.maker = self.openPosition.maker.add(amount);\n self.oracleVersion = currentVersion;\n _netMake(self);\n }\n\n /**\n * @notice Increments the maker side of the close position delta\n * @dev Nets out open and close deltas to minimize the size of each\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @param amount The maker position amount to close\n */\n function closeMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\n self.closePosition.maker = self.closePosition.maker.add(amount);\n self.oracleVersion = currentVersion;\n _netMake(self);\n }\n\n /**\n * @notice Increments the taker side of the open position delta\n * @dev Nets out open and close deltas to minimize the size of each\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @param amount The taker position amount to open\n */\n function openTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\n self.openPosition.taker = self.openPosition.taker.add(amount);\n self.oracleVersion = currentVersion;\n _netTake(self);\n }\n\n /**\n * @notice Increments the taker side of the close position delta\n * @dev Nets out open and close deltas to minimize the size of each\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @param amount The taker position amount to close\n */\n function closeTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\n self.closePosition.taker = self.closePosition.taker.add(amount);\n self.oracleVersion = currentVersion;\n _netTake(self);\n }\n\n /**\n * @notice Nets out the open and close on the maker side of the position delta\n * @param self The struct to operate on\n */\n function _netMake(PrePosition storage self) private {\n if (self.openPosition.maker.gt(self.closePosition.maker)) {\n self.openPosition.maker = self.openPosition.maker.sub(self.closePosition.maker);\n self.closePosition.maker = UFixed18Lib.ZERO;\n } else {\n self.closePosition.maker = self.closePosition.maker.sub(self.openPosition.maker);\n self.openPosition.maker = UFixed18Lib.ZERO;\n }\n }\n\n /**\n * @notice Nets out the open and close on the taker side of the position delta\n * @param self The struct to operate on\n */\n function _netTake(PrePosition storage self) private {\n if (self.openPosition.taker.gt(self.closePosition.taker)) {\n self.openPosition.taker = self.openPosition.taker.sub(self.closePosition.taker);\n self.closePosition.taker = UFixed18Lib.ZERO;\n } else {\n self.closePosition.taker = self.closePosition.taker.sub(self.openPosition.taker);\n self.openPosition.taker = UFixed18Lib.ZERO;\n }\n }\n\n /**\n * @notice Returns whether the the pending position delta can be settled at version `toOracleVersion`\n * @dev Pending-settlement positions deltas can be settled (1) oracle version after they are recorded\n * @param self The struct to operate on\n * @param toOracleVersion The potential oracle version to settle\n * @return Whether the position delta can be settled\n */\n function canSettle(\n PrePosition memory self,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal pure returns (bool) {\n return !isEmpty(self) && toOracleVersion.version > self.oracleVersion;\n }\n\n /**\n * @notice Computes the fee incurred for opening or closing the pending-settlement position\n * @param self The struct to operate on\n * @param provider The parameter provider of the product\n * @param toOracleVersion The oracle version at which settlement takes place\n * @return positionFee The maker / taker fee incurred\n */\n function computeFee(\n PrePosition memory self,\n IProductProvider provider,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal view returns (UFixed18) {\n Position memory positionDelta = self.openPosition.add(self.closePosition);\n\n (UFixed18 makerNotional, UFixed18 takerNotional) = (\n Fixed18Lib.from(positionDelta.maker).mul(toOracleVersion.price).abs(),\n Fixed18Lib.from(positionDelta.taker).mul(toOracleVersion.price).abs()\n );\n\n return makerNotional.mul(provider.safeMakerFee()).add(takerNotional.mul(provider.safeTakerFee()));\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" + }, + "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" + }, + "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" + }, + "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" + }, + "contracts/interfaces/types/ProductProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"../IProductProvider.sol\";\nimport \"../IController.sol\";\n\n/**\n * @title ProductProviderLib\n * @notice Library that adds a safeguard wrapper to certain product parameters.\n * @dev Product providers are semi-untrusted as they contain custom code from the product owners. Owners\n * have full control over this parameter-setting code, however there are some \"known ranges\" that\n * a parameter cannot be outside of (i.e. a fee being over 100%).\n */\nlibrary ProductProviderLib {\n /**\n * @notice Returns the minimum funding fee parameter with a capped range for safety\n * @dev Caps controller.minFundingFee() <= self.minFundingFee() <= 1\n * @param self The parameter provider to operate on\n * @param controller The protocol Factory contract\n * @return Safe minimum funding fee parameter\n */\n function safeFundingFee(IProductProvider self, IController controller) internal view returns (UFixed18) {\n return self.fundingFee().max(controller.minFundingFee()).min(UFixed18Lib.ONE);\n }\n\n /**\n * @notice Returns the maker fee parameter with a capped range for safety\n * @dev Caps self.makerFee() <= 1\n * @param self The parameter provider to operate on\n * @return Safe maker fee parameter\n */\n function safeMakerFee(IProductProvider self) internal view returns (UFixed18) {\n return self.makerFee().min(UFixed18Lib.ONE);\n }\n\n /**\n * @notice Returns the taker fee parameter with a capped range for safety\n * @dev Caps self.takerFee() <= 1\n * @param self The parameter provider to operate on\n * @return Safe taker fee parameter\n */\n function safeTakerFee(IProductProvider self) internal view returns (UFixed18) {\n return self.takerFee().min(UFixed18Lib.ONE);\n }\n}\n" + }, + "contracts/interfaces/IOracleProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/Fixed18.sol\";\n\ninterface IOracleProvider {\n /// @dev A singular oracle version with its corresponding data\n struct OracleVersion {\n /// @dev The iterative version\n uint256 version;\n\n /// @dev the timestamp of the oracle update\n uint256 timestamp;\n\n /// @dev The oracle price of the corresponding version\n Fixed18 price;\n }\n\n function sync() external returns (OracleVersion memory);\n function currentVersion() external view returns (OracleVersion memory);\n function atVersion(uint256 oracleVersion) external view returns (OracleVersion memory);\n}\n" + }, + "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 /// @dev Reward ERC20 token contract\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" + }, + "contracts/product/Product.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"@equilibria/root/control/unstructured/UReentrancyGuard.sol\";\nimport \"./types/position/AccountPosition.sol\";\nimport \"./types/accumulator/AccountAccumulator.sol\";\nimport \"../controller/UControllerProvider.sol\";\n\n/**\n * @title Product\n * @notice Manages logic and state for a single product market.\n * @dev Cloned by the Controller contract to launch new product markets.\n */\ncontract Product is IProduct, UInitializable, UControllerProvider, UReentrancyGuard {\n /// @dev The parameter provider of the product market\n IProductProvider public productProvider;\n\n /// @dev The individual position state for each account\n mapping(address => AccountPosition) private _positions;\n\n /// @dev The global position state for the product\n VersionedPosition private _position;\n\n /// @dev The individual accumulator state for each account\n mapping(address => AccountAccumulator) private _accumulators;\n\n /// @dev The global accumulator state for the product\n VersionedAccumulator private _accumulator;\n\n /**\n * @notice Initializes the contract state\n * @param productProvider_ Product provider contract address\n */\n function initialize(IProductProvider productProvider_) external initializer(1) {\n __UControllerProvider__initialize(IController(msg.sender));\n __UReentrancyGuard__initialize();\n\n productProvider = productProvider_;\n }\n\n /**\n * @notice Surfaces global settlement externally\n */\n function settle() external nonReentrant notPausedProduct(IProduct(this)) {\n settleInternal();\n }\n\n /**\n * @notice Core global settlement flywheel\n * @dev\n * a) last settle oracle version\n * b) latest pre position oracle version\n * c) current oracle version\n *\n * Settles from a->b then from b->c if either interval is non-zero to account for a change\n * in position quantity at (b).\n *\n * Syncs each to instantaneously after the oracle update.\n */\n function settleInternal() internal returns (IOracleProvider.OracleVersion memory currentOracleVersion) {\n (IProductProvider _provider, IController _controller) = (productProvider, controller());\n\n // Get current oracle version\n currentOracleVersion = _provider.sync();\n\n // Get latest oracle version\n uint256 _latestVersion = latestVersion();\n if (_latestVersion == currentOracleVersion.version) return currentOracleVersion; // short circuit entirely if a == c\n IOracleProvider.OracleVersion memory latestOracleVersion = _provider.atVersion(_latestVersion);\n\n // Get settle oracle version\n uint256 _settleVersion = _position.pre.settleVersion(currentOracleVersion.version);\n IOracleProvider.OracleVersion memory settleOracleVersion = _settleVersion == currentOracleVersion.version ?\n currentOracleVersion : // if b == c, don't re-call provider for oracle version\n _provider.atVersion(_settleVersion);\n\n // Initiate\n _controller.incentivizer().sync(currentOracleVersion);\n UFixed18 accumulatedFee;\n\n // value a->b\n accumulatedFee = accumulatedFee.add(_accumulator.accumulate(_controller, _provider, _position, latestOracleVersion, settleOracleVersion));\n\n // position a->b\n accumulatedFee = accumulatedFee.add(_position.settle(_provider, _latestVersion, settleOracleVersion));\n\n // short-circuit from a->c if b == c\n if (settleOracleVersion.version != currentOracleVersion.version) {\n\n // value b->c\n accumulatedFee = accumulatedFee.add(_accumulator.accumulate(_controller, _provider, _position, settleOracleVersion, currentOracleVersion));\n\n // position b->c (every accumulator version needs a position stamp)\n _position.settle(_provider, settleOracleVersion.version, currentOracleVersion);\n }\n\n // settle collateral\n _controller.collateral().settleProduct(accumulatedFee);\n\n emit Settle(settleOracleVersion.version, currentOracleVersion.version);\n }\n\n /**\n * @notice Surfaces account settlement externally\n * @param account Account to settle\n */\n function settleAccount(address account) external nonReentrant notPausedProduct(IProduct(this)) {\n IOracleProvider.OracleVersion memory currentOracleVersion = settleInternal();\n settleAccountInternal(account, currentOracleVersion);\n }\n\n /**\n * @notice Core account settlement flywheel\n * @param account Account to settle\n * @dev\n * a) last settle oracle version\n * b) latest pre position oracle version\n * c) current oracle version\n *\n * Settles from a->b then from b->c if either interval is non-zero to account for a change\n * in position quantity at (b).\n *\n * Syncs each to instantaneously after the oracle update.\n */\n function settleAccountInternal(address account, IOracleProvider.OracleVersion memory currentOracleVersion) internal {\n (IProductProvider _provider, IController _controller) = (productProvider, controller());\n\n // Get latest oracle version\n if (latestVersion(account) == currentOracleVersion.version) return; // short circuit entirely if a == c\n\n // Get settle oracle version\n uint256 _settleVersion = _positions[account].pre.settleVersion(currentOracleVersion.version);\n IOracleProvider.OracleVersion memory settleOracleVersion = _settleVersion == currentOracleVersion.version ?\n currentOracleVersion : // if b == c, don't re-call provider for oracle version\n _provider.atVersion(_settleVersion);\n\n // initialize\n Fixed18 accumulated;\n\n // sync incentivizer before accumulator\n _controller.incentivizer().syncAccount(account, settleOracleVersion);\n\n // value a->b\n accumulated = accumulated.add(\n _accumulators[account].syncTo(_accumulator, _positions[account], settleOracleVersion.version).sum());\n\n // position a->b\n accumulated = accumulated.sub(Fixed18Lib.from(_positions[account].settle(_provider, settleOracleVersion)));\n\n // short-circuit if a->c\n if (settleOracleVersion.version != currentOracleVersion.version) {\n // sync incentivizer before accumulator\n _controller.incentivizer().syncAccount(account, currentOracleVersion);\n\n // value b->c\n accumulated = accumulated.add(\n _accumulators[account].syncTo(_accumulator, _positions[account], currentOracleVersion.version).sum());\n }\n\n // settle collateral\n _controller.collateral().settleAccount(account, accumulated);\n\n emit AccountSettle(account, settleOracleVersion.version, currentOracleVersion.version);\n }\n\n /**\n * @notice Opens a taker position for `msg.sender`\n * @param amount Amount of the position to open\n */\n function openTake(UFixed18 amount)\n external\n nonReentrant\n notPausedProduct(IProduct(this))\n settleForAccount(msg.sender)\n takerInvariant\n positionInvariant\n liquidationInvariant\n maintenanceInvariant\n {\n uint256 _latestVersion = latestVersion();\n\n _positions[msg.sender].pre.openTake(_latestVersion, amount);\n _position.pre.openTake(_latestVersion, amount);\n\n emit TakeOpened(msg.sender, _latestVersion, amount);\n }\n\n /**\n * @notice Closes a taker position for `msg.sender`\n * @param amount Amount of the position to close\n */\n function closeTake(UFixed18 amount)\n external\n nonReentrant\n notPausedProduct(IProduct(this))\n settleForAccount(msg.sender)\n closeInvariant\n liquidationInvariant\n {\n closeTakeInternal(msg.sender, amount);\n }\n\n function closeTakeInternal(address account, UFixed18 amount) internal {\n uint256 _latestVersion = latestVersion();\n\n _positions[account].pre.closeTake(_latestVersion, amount);\n _position.pre.closeTake(_latestVersion, amount);\n\n emit TakeClosed(account, _latestVersion, amount);\n }\n\n /**\n * @notice Opens a maker position for `msg.sender`\n * @param amount Amount of the position to open\n */\n function openMake(UFixed18 amount)\n external\n nonReentrant\n notPausedProduct(IProduct(this))\n settleForAccount(msg.sender)\n nonZeroVersionInvariant\n makerInvariant\n positionInvariant\n liquidationInvariant\n maintenanceInvariant\n {\n uint256 _latestVersion = latestVersion();\n\n _positions[msg.sender].pre.openMake(_latestVersion, amount);\n _position.pre.openMake(_latestVersion, amount);\n\n emit MakeOpened(msg.sender, _latestVersion, amount);\n }\n\n /**\n * @notice Closes a maker position for `msg.sender`\n * @param amount Amount of the position to close\n */\n function closeMake(UFixed18 amount)\n external\n nonReentrant\n notPausedProduct(IProduct(this))\n settleForAccount(msg.sender)\n takerInvariant\n closeInvariant\n liquidationInvariant\n {\n closeMakeInternal(msg.sender, amount);\n }\n\n function closeMakeInternal(address account, UFixed18 amount) internal {\n uint256 _latestVersion = latestVersion();\n\n _positions[account].pre.closeMake(_latestVersion, amount);\n _position.pre.closeMake(_latestVersion, amount);\n\n emit MakeClosed(account, _latestVersion, amount);\n }\n\n /**\n * @notice Closes all open and pending positions, locking for liquidation\n * @dev Only callable by the Collateral contract as part of the liquidation flow\n * @param account Account to close out\n */\n function closeAll(address account) external onlyCollateral settleForAccount(account) {\n AccountPosition storage accountPosition = _positions[account];\n Position memory p = accountPosition.position.next(_positions[account].pre);\n\n // Close all positions\n closeMakeInternal(account, p.maker);\n closeTakeInternal(account, p.taker);\n\n // Mark liquidation to lock position\n accountPosition.liquidation = true;\n }\n\n /**\n * @notice Returns the maintenance requirement for `account`\n * @param account Account to return for\n * @return The current maintenance requirement\n */\n function maintenance(address account) external view returns (UFixed18) {\n return _positions[account].maintenance(productProvider);\n }\n\n /**\n * @notice Returns the maintenance requirement for `account` after next settlement\n * @dev Assumes no price change and no funding, used to protect user from over-opening\n * @param account Account to return for\n * @return The next maintenance requirement\n */\n function maintenanceNext(address account) external view returns (UFixed18) {\n return _positions[account].maintenanceNext(productProvider);\n }\n\n /**\n * @notice Returns whether `account` has a completely zero'd position\n * @param account Account to return for\n * @return The the account is closed\n */\n function isClosed(address account) external view returns (bool) {\n return _positions[account].isClosed();\n }\n\n /**\n * @notice Returns whether `account` is currently locked for an in-progress liquidation\n * @param account Account to return for\n * @return Whether the account is in liquidation\n */\n function isLiquidating(address account) external view returns (bool) {\n return _positions[account].liquidation;\n }\n\n /**\n * @notice Returns `account`'s current position\n * @param account Account to return for\n * @return Current position of the account\n */\n function position(address account) external view returns (Position memory) {\n return _positions[account].position;\n }\n\n /**\n * @notice Returns `account`'s current pending-settlement position\n * @param account Account to return for\n * @return Current pre-position of the account\n */\n function pre(address account) external view returns (PrePosition memory) {\n return _positions[account].pre;\n }\n\n /**\n * @notice Returns the global latest settled oracle version\n * @return Latest settled oracle version of the product\n */\n function latestVersion() public view returns (uint256) {\n return _accumulator.latestVersion;\n }\n\n /**\n * @notice Returns the global position at oracleVersion `oracleVersion`\n * @dev Only valid for the version at which a global settlement occurred\n * @param oracleVersion Oracle version to return for\n * @return Global position at oracle version\n */\n function positionAtVersion(uint256 oracleVersion) public view returns (Position memory) {\n return _position.positionAtVersion(oracleVersion);\n }\n\n /**\n * @notice Returns the current global pending-settlement position\n * @return Global pending-settlement position\n */\n function pre() external view returns (PrePosition memory) {\n return _position.pre;\n }\n\n /**\n * @notice Returns the global accumulator value at oracleVersion `oracleVersion`\n * @dev Only valid for the version at which a global settlement occurred\n * @param oracleVersion Oracle version to return for\n * @return Global accumulator value at oracle version\n */\n function valueAtVersion(uint256 oracleVersion) external view returns (Accumulator memory) {\n return _accumulator.valueAtVersion(oracleVersion);\n }\n\n /**\n * @notice Returns the global accumulator share at oracleVersion `oracleVersion`\n * @dev Only valid for the version at which a global settlement occurred\n * @param oracleVersion Oracle version to return for\n * @return Global accumulator share at oracle version\n */\n function shareAtVersion(uint256 oracleVersion) external view returns (Accumulator memory) {\n return _accumulator.shareAtVersion(oracleVersion);\n }\n\n /**\n * @notice Returns `account`'s latest settled oracle version\n * @param account Account to return for\n * @return Latest settled oracle version of the account\n */\n function latestVersion(address account) public view returns (uint256) {\n return _accumulators[account].latestVersion;\n }\n\n /// @dev Limit total maker for guarded rollouts\n modifier makerInvariant {\n _;\n\n Position memory next = positionAtVersion(latestVersion()).next(_position.pre);\n\n if (next.maker.gt(productProvider.makerLimit())) revert ProductMakerOverLimitError();\n }\n\n /// @dev Limit maker short exposure to the range 0.0-1.0x of their position\n modifier takerInvariant {\n _;\n\n Position memory next = positionAtVersion(latestVersion()).next(_position.pre);\n UFixed18 socializationFactor = next.socializationFactor();\n\n if (socializationFactor.lt(UFixed18Lib.ONE)) revert ProductInsufficientLiquidityError(socializationFactor);\n }\n\n /// @dev Ensure that the user has only taken a maker or taker position, but not both\n modifier positionInvariant {\n _;\n\n if (_positions[msg.sender].isDoubleSided()) revert ProductDoubleSidedError();\n }\n\n /// @dev Ensure that the user hasn't closed more than is open\n modifier closeInvariant {\n _;\n\n if (_positions[msg.sender].isOverClosed()) revert ProductOverClosedError();\n }\n\n /// @dev Ensure that the user will have sufficient margin for maintenance after next settlement\n modifier maintenanceInvariant {\n _;\n\n if (controller().collateral().liquidatableNext(msg.sender, IProduct(this)))\n revert ProductInsufficientCollateralError();\n }\n\n /// @dev Ensure that the user is not currently being liquidated\n modifier liquidationInvariant {\n if (_positions[msg.sender].liquidation) revert ProductInLiquidationError();\n\n _;\n }\n\n /// @dev Helper to fully settle an account's state\n modifier settleForAccount(address account) {\n IOracleProvider.OracleVersion memory currentVersion = settleInternal();\n settleAccountInternal(account, currentVersion);\n\n _;\n }\n\n /// @dev Ensure we have bootstraped the oracle before creating positions\n modifier nonZeroVersionInvariant {\n if (latestVersion() == 0) revert ProductOracleBootstrappingError();\n\n _;\n }\n}\n" + }, + "contracts/product/types/position/AccountPosition.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"../../../interfaces/types/PrePosition.sol\";\n\n/// @dev AccountPosition type\nstruct AccountPosition {\n /// @dev The current settled position of the account\n Position position;\n\n /// @dev The current position delta pending-settlement\n PrePosition pre;\n\n /// @dev Whether the account is currently locked for liquidation\n bool liquidation;\n}\nusing AccountPositionLib for AccountPosition global;\n\n/**\n * @title AccountPositionLib\n * @notice Library that manages an account-level position.\n */\nlibrary AccountPositionLib {\n /**\n * @notice Settled the account's position to oracle version `toOracleVersion`\n * @param self The struct to operate on\n * @param provider The parameter provider of the product\n * @param toOracleVersion The oracle version to accumulate to\n * @return positionFee The fee accrued from opening or closing a new position\n */\n function settle(\n AccountPosition storage self,\n IProductProvider provider,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal returns (UFixed18 positionFee) {\n bool settled;\n (self.position, positionFee, settled) = self.position.settled(self.pre, provider, toOracleVersion);\n if (settled) delete self.pre;\n }\n\n /**\n * @notice Returns the current maintenance requirement for the account\n * @param self The struct to operate on\n * @param provider The parameter provider of the product\n * @return Current maintenance requirement for the account\n */\n function maintenance(AccountPosition storage self, IProductProvider provider) internal view returns (UFixed18) {\n if (self.liquidation) return UFixed18Lib.ZERO;\n return _maintenance(self.position, provider);\n }\n\n /**\n * @notice Returns the maintenance requirement after the next oracle version settlement\n * @dev Includes the current pending-settlement position delta, assumes no price change\n * @param self The struct to operate on\n * @param provider The parameter provider of the product\n * @return Next maintenance requirement for the account\n */\n function maintenanceNext(AccountPosition storage self, IProductProvider provider) internal view returns (UFixed18) {\n return _maintenance(self.position.next(self.pre), provider);\n }\n\n /**\n * @notice Returns the maintenance requirement for a given `position`\n * @dev Internal helper\n * @param position The position to compete the maintenance requirement for\n * @param provider The parameter provider of the product\n * @return Next maintenance requirement for the account\n */\n function _maintenance(Position memory position, IProductProvider provider) private view returns (UFixed18) {\n Fixed18 oraclePrice = provider.currentVersion().price;\n UFixed18 notionalMax = Fixed18Lib.from(position.max()).mul(oraclePrice).abs();\n return notionalMax.mul(provider.maintenance());\n }\n\n /**\n * @notice Returns whether an account is completely closed, i.e. no position or pre-position\n * @param self The struct to operate on\n * @return Whether the account is closed\n */\n function isClosed(AccountPosition memory self) internal pure returns (bool) {\n return self.pre.isEmpty() && self.position.isEmpty();\n }\n\n /**\n * @notice Returns whether an account has opened position on both sides of the market (maker vs taker)\n * @dev Used to verify the invariant that a single account can only have a position on one side of the\n * market at a time\n * @param self The struct to operate on\n * @return Whether the account is currently doubled sided\n */\n function isDoubleSided(AccountPosition storage self) internal view returns (bool) {\n bool makerEmpty = self.position.maker.isZero() && self.pre.openPosition.maker.isZero() && self.pre.closePosition.maker.isZero();\n bool takerEmpty = self.position.taker.isZero() && self.pre.openPosition.taker.isZero() && self.pre.closePosition.taker.isZero();\n\n return !makerEmpty && !takerEmpty;\n }\n\n /**\n * @notice Returns whether the account's pending-settlement delta closes more position than is open\n * @dev Used to verify the invariant that an account cannot settle into having a negative position\n * @param self The struct to operate on\n * @return Whether the account is currently over closed\n */\n function isOverClosed(AccountPosition storage self) internal view returns (bool) {\n Position memory nextOpen = self.position.add(self.pre.openPosition);\n\n return self.pre.closePosition.maker.gt(nextOpen.maker) || self.pre.closePosition.taker.gt(nextOpen.taker);\n }\n}\n" + }, + "contracts/product/types/accumulator/AccountAccumulator.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"../../../interfaces/types/Accumulator.sol\";\nimport \"../position/AccountPosition.sol\";\nimport \"./VersionedAccumulator.sol\";\n\n/// @dev AccountAccumulator type\nstruct AccountAccumulator {\n /// @dev latest version that the account was synced too\n uint256 latestVersion;\n}\nusing AccountAccumulatorLib for AccountAccumulator global;\n\n/**\n * @title AccountAccumulatorLib\n * @notice Library that manages syncing an account-level accumulator.\n */\nlibrary AccountAccumulatorLib {\n /**\n * @notice Syncs the account to oracle version `versionTo`\n * @param self The struct to operate on\n * @param global Pointer to global accumulator\n * @param position Pointer to global position\n * @param versionTo Oracle version to sync account to\n * @return value The value accumulated sync last sync\n */\n function syncTo(\n AccountAccumulator storage self,\n VersionedAccumulator storage global,\n AccountPosition storage position,\n uint256 versionTo\n ) internal returns (Accumulator memory value) {\n Accumulator memory valueAccumulated = global.valueAtVersion(versionTo)\n .sub(global.valueAtVersion(self.latestVersion));\n value = position.position.mul(valueAccumulated);\n self.latestVersion = versionTo;\n }\n}\n" + }, + "contracts/product/types/accumulator/VersionedAccumulator.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"../../../interfaces/types/Accumulator.sol\";\nimport \"../../../interfaces/types/ProductProvider.sol\";\nimport \"../position/VersionedPosition.sol\";\n\n/// @dev VersionedAccumulator type\nstruct VersionedAccumulator {\n /// @dev Latest synced oracle version\n uint256 latestVersion;\n\n /// @dev Mapping of accumulator value at each settled oracle version\n mapping(uint256 => PackedAccumulator) _valueAtVersion;\n\n /// @dev Mapping of accumulator share at each settled oracle version\n mapping(uint256 => PackedAccumulator) _shareAtVersion;\n}\nusing VersionedAccumulatorLib for VersionedAccumulator global;\n\n/**\n * @title VersionedAccumulatorLib\n * @notice Library that manages global versioned accumulator state.\n * @dev Manages two accumulators: value and share. The value accumulator measures the change in position value\n * over time. The share accumulator measures the change in liquidity ownership over time (for tracking\n * incentivization rewards).\n *\n * Both accumulators are stamped for historical lookup anytime there is a global settlement, which services\n * the delayed-position accounting. It is not guaranteed that every version will have a value stamped, but\n * only versions when a settlement occurred are needed for this historical computation.\n */\nlibrary VersionedAccumulatorLib {\n using ProductProviderLib for IProductProvider;\n\n /**\n * @notice Returns the stamped value accumulator at `oracleVersion`\n * @param self The struct to operate on\n * @param oracleVersion The oracle version to retrieve the value at\n * @return The stamped value accumulator at the requested version\n */\n function valueAtVersion(VersionedAccumulator storage self, uint256 oracleVersion) internal view returns (Accumulator memory) {\n return self._valueAtVersion[oracleVersion].unpack();\n }\n\n /**\n * @notice Returns the stamped share accumulator at `oracleVersion`\n * @param self The struct to operate on\n * @param oracleVersion The oracle version to retrieve the share at\n * @return The stamped share accumulator at the requested version\n */\n function shareAtVersion(VersionedAccumulator storage self, uint256 oracleVersion) internal view returns (Accumulator memory) {\n return self._shareAtVersion[oracleVersion].unpack();\n }\n\n /**\n * @notice Globally accumulates all value (position + funding) and share since last oracle update\n * @param self The struct to operate on\n * @param controller The Controller contract of the protocol\n * @param provider The parameter provider of the product\n * @param position Pointer to global position\n * @param latestOracleVersion The oracle version to accumulate from\n * @param toOracleVersion The oracle version to accumulate to\n * @return accumulatedFee The total fee accrued from accumulation\n */\n function accumulate(\n VersionedAccumulator storage self,\n IController controller,\n IProductProvider provider,\n VersionedPosition storage position,\n IOracleProvider.OracleVersion memory latestOracleVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal returns (UFixed18 accumulatedFee) {\n Position memory latestPosition = position.positionAtVersion(latestOracleVersion.version);\n\n // accumulate funding\n Accumulator memory accumulatedPosition;\n (accumulatedPosition, accumulatedFee) =\n _accumulateFunding(controller, provider, latestPosition, latestOracleVersion, toOracleVersion);\n\n // accumulate position\n accumulatedPosition = accumulatedPosition.add(\n _accumulatePosition(latestPosition, latestOracleVersion, toOracleVersion));\n\n // accumulate share\n Accumulator memory accumulatedShare =\n _accumulateShare(latestPosition, latestOracleVersion, toOracleVersion);\n\n // save update\n self._valueAtVersion[toOracleVersion.version] = valueAtVersion(self, latestOracleVersion.version)\n .add(accumulatedPosition)\n .pack();\n self._shareAtVersion[toOracleVersion.version] = shareAtVersion(self, latestOracleVersion.version)\n .add(accumulatedShare)\n .pack();\n self.latestVersion = toOracleVersion.version;\n }\n\n /**\n * @notice Globally accumulates all funding since last oracle update\n * @dev If an oracle version is skipped due to no pre positions, funding will continue to be\n * pegged to the price of the last snapshotted oracleVersion until a new one is accumulated.\n * This is an acceptable approximation.\n * @param controller The Controller contract of the protocol\n * @param provider The parameter provider of the product\n * @param latestPosition The latest global position\n * @param latestOracleVersion The oracle version to accumulate from\n * @param toOracleVersion The oracle version to accumulate to\n * @return accumulatedFunding The total amount accumulated from funding\n * @return accumulatedFee The total fee accrued from funding accumulation\n */\n function _accumulateFunding(\n IController controller,\n IProductProvider provider,\n Position memory latestPosition,\n IOracleProvider.OracleVersion memory latestOracleVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) private view returns (Accumulator memory accumulatedFunding, UFixed18 accumulatedFee) {\n if (latestPosition.taker.isZero()) return (Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO), UFixed18Lib.ZERO);\n if (latestPosition.maker.isZero()) return (Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO), UFixed18Lib.ZERO);\n\n uint256 elapsed = toOracleVersion.timestamp - latestOracleVersion.timestamp;\n\n UFixed18 takerNotional = Fixed18Lib.from(latestPosition.taker).mul(latestOracleVersion.price).abs();\n UFixed18 socializedNotional = takerNotional.mul(latestPosition.socializationFactor());\n\n Fixed18 rateAccumulated = provider.rate(latestPosition).mul(Fixed18Lib.from(UFixed18Lib.from(elapsed)));\n Fixed18 fundingAccumulated = rateAccumulated.mul(Fixed18Lib.from(socializedNotional));\n accumulatedFee = fundingAccumulated.abs().mul(provider.safeFundingFee(controller));\n\n Fixed18 fundingIncludingFee = Fixed18Lib.from(\n fundingAccumulated.sign(),\n fundingAccumulated.abs().sub(accumulatedFee)\n );\n\n accumulatedFunding.maker = fundingIncludingFee.div(Fixed18Lib.from(latestPosition.maker));\n accumulatedFunding.taker = fundingIncludingFee.div(Fixed18Lib.from(latestPosition.taker)).mul(Fixed18Lib.NEG_ONE);\n }\n\n /**\n * @notice Globally accumulates position PNL since last oracle update\n * @param latestPosition The latest global position\n * @param latestOracleVersion The oracle version to accumulate from\n * @param toOracleVersion The oracle version to accumulate to\n * @return accumulatedPosition The total amount accumulated from position PNL\n */\n function _accumulatePosition(\n Position memory latestPosition,\n IOracleProvider.OracleVersion memory latestOracleVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) private pure returns (Accumulator memory accumulatedPosition) {\n if (latestPosition.taker.isZero()) return Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO);\n if (latestPosition.maker.isZero()) return Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO);\n\n Fixed18 oracleDelta = toOracleVersion.price.sub(latestOracleVersion.price);\n Fixed18 totalTakerDelta = oracleDelta.mul(Fixed18Lib.from(latestPosition.taker));\n Fixed18 socializedTakerDelta = totalTakerDelta.mul(Fixed18Lib.from(latestPosition.socializationFactor()));\n\n accumulatedPosition.maker = socializedTakerDelta.div(Fixed18Lib.from(latestPosition.maker)).mul(Fixed18Lib.NEG_ONE);\n accumulatedPosition.taker = socializedTakerDelta.div(Fixed18Lib.from(latestPosition.taker));\n }\n\n /**\n * @notice Globally accumulates position's share of the total market since last oracle update\n * @dev This is used to compute incentivization rewards based on market participation\n * @param latestPosition The latest global position\n * @param latestOracleVersion The oracle version to accumulate from\n * @param toOracleVersion The oracle version to accumulate to\n * @return accumulatedShare The total share amount accumulated per position\n */\n function _accumulateShare(\n Position memory latestPosition,\n IOracleProvider.OracleVersion memory latestOracleVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) private pure returns (Accumulator memory accumulatedShare) {\n uint256 elapsed = toOracleVersion.timestamp - latestOracleVersion.timestamp;\n\n accumulatedShare.maker = latestPosition.maker.isZero() ?\n Fixed18Lib.ZERO :\n Fixed18Lib.from(UFixed18Lib.from(elapsed).div(latestPosition.maker));\n accumulatedShare.taker = latestPosition.taker.isZero() ?\n Fixed18Lib.ZERO :\n Fixed18Lib.from(UFixed18Lib.from(elapsed).div(latestPosition.taker));\n }\n}\n" + }, + "contracts/product/types/position/VersionedPosition.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"../../../interfaces/types/PrePosition.sol\";\nimport \"../../../interfaces/types/PackedPosition.sol\";\n\n//// @dev VersionedPosition type\nstruct VersionedPosition {\n /// @dev Mapping of global position at each version\n mapping(uint256 => PackedPosition) _positionAtVersion;\n\n /// @dev Current global pending-settlement position delta\n PrePosition pre;\n}\nusing VersionedPositionLib for VersionedPosition global;\n\n/**\n * @title VersionedPositionLib\n * @notice Library that manages global position state.\n * @dev Global position state is used to compute utilization rate and socialization, and to account for and\n * distribute fees globally.\n *\n * Positions are stamped for historical lookup anytime there is a global settlement, which services\n * the delayed-position accounting. It is not guaranteed that every version will have a value stamped, but\n * only versions when a settlement occurred are needed for this historical computation.\n */\nlibrary VersionedPositionLib {\n /**\n * @notice Returns the current global position\n * @return Current global position\n */\n function positionAtVersion(VersionedPosition storage self, uint256 oracleVersion) internal view returns (Position memory) {\n return self._positionAtVersion[oracleVersion].unpack();\n }\n\n /**\n * @notice Settled the global position to oracle version `toOracleVersion`\n * @param self The struct to operate on\n * @param provider The parameter provider of the product\n * @param latestVersion The latest settled oracle version\n * @param toOracleVersion The oracle version to settle to\n * @return positionFee The fee accrued from opening or closing a new position\n */\n function settle(\n VersionedPosition storage self,\n IProductProvider provider,\n uint256 latestVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal returns (UFixed18) {\n (Position memory newPosition, UFixed18 positionFee, bool settled) =\n positionAtVersion(self, latestVersion).settled(self.pre, provider, toOracleVersion);\n\n self._positionAtVersion[toOracleVersion.version] = newPosition.pack();\n if (settled) delete self.pre;\n\n return positionFee;\n }\n}\n" + }, + "@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}" + }, + "@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" + }, + "@equilibria/emptyset-batcher/interfaces/IBatcher.sol": { + "content": "//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\n\ninterface IBatcher {\n event Wrap(address indexed to, UFixed18 amount);\n event Unwrap(address indexed to, UFixed18 amount);\n event Rebalance(UFixed18 newMinted, UFixed18 newRedeemed);\n event Close(UFixed18 amount);\n\n error BatcherNotImplementedError();\n error BatcherBalanceMismatchError(UFixed18 oldBalance, UFixed18 newBalance);\n\n function totalBalance() external view returns (UFixed18);\n function wrap(UFixed18 amount, address to) external;\n function unwrap(UFixed18 amount, address to) external;\n function rebalance() external;\n}\n" + }, + "contracts/interfaces/IForwarder.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@equilibria/root/token/types/Token18.sol\";\nimport \"@equilibria/root/token/types/Token6.sol\";\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\";\nimport \"./ICollateral.sol\";\n\ninterface IForwarder {\n event WrapAndDeposit(address indexed account, IProduct indexed product, UFixed18 amount);\n\n function USDC() external view returns (Token6); // solhint-disable-line func-name-mixedcase\n function DSU() external view returns (Token18); // solhint-disable-line func-name-mixedcase\n function batcher() external view returns (IBatcher);\n function collateral() external view returns (ICollateral);\n function wrapAndDeposit(address account, IProduct product, UFixed18 amount) external;\n}\n" + }, + "@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 * @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 * @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" + }, + "contracts/interfaces/IPerennialLens.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"./IProduct.sol\";\nimport \"./ICollateral.sol\";\nimport \"./IController.sol\";\nimport \"./IOracleProvider.sol\";\n\ninterface IPerennialLens {\n function controller() external view returns (IController);\n function name(IProduct product) external view returns (string memory);\n function symbol(IProduct product) external view returns (string memory);\n function collateral() external view returns (ICollateral);\n function collateral(address account, IProduct product) external returns (UFixed18);\n function collateral(IProduct product) external returns (UFixed18);\n function shortfall(IProduct product) external returns (UFixed18);\n function maintenance(address account, IProduct product) external returns (UFixed18);\n function liquidatable(address account, IProduct product) external returns (bool);\n function pre(address account, IProduct product) external returns (PrePosition memory);\n function pre(IProduct product) external returns (PrePosition memory);\n function position(address account, IProduct product) external returns (Position memory);\n function position(IProduct product) external returns (Position memory);\n function userPosition(address account, IProduct product) external returns (PrePosition memory, Position memory);\n function globalPosition(IProduct product) external returns (PrePosition memory, Position memory);\n function price(IProduct product) external returns (Fixed18);\n function fees(IProduct product) external returns (UFixed18 protocolFees, UFixed18 productFees);\n function fees(address account, IProduct[] memory products) external returns (UFixed18);\n function openInterest(address account, IProduct product) external returns (Position memory);\n function openInterest(IProduct product) external returns (Position memory);\n function rate(IProduct product) external returns (Fixed18);\n function dailyRate(IProduct product) external returns (Fixed18);\n function maintenanceRequired(\n address account,\n IProduct product,\n UFixed18 positionSize\n ) external returns (UFixed18);\n function unclaimedIncentiveRewards(address account, IProduct product)\n external\n returns (Token18[] memory tokens, UFixed18[] memory amounts);\n function unclaimedIncentiveRewards(\n address account,\n IProduct product,\n uint256[] calldata programIds\n ) external returns (Token18[] memory tokens, UFixed18[] memory amounts);\n}\n" + }, + "contracts/lens/PerennialLens.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"../interfaces/IPerennialLens.sol\";\n\n/**\n * @title Lens contract to conveniently pull protocol data\n * @notice All functions should be called using `callStatic`\n */\ncontract PerennialLens is IPerennialLens {\n /**\n * @notice Protocol controller\n * @return Protocol controller\n */\n IController public immutable controller;\n\n /// @param _controller Protocol controller address\n constructor(IController _controller) {\n controller = _controller;\n }\n\n /**\n * @notice Returns the name of the provided `product`\n * @param product Product address\n * @return Name of the product\n */\n function name(IProduct product) external view returns (string memory) {\n return product.productProvider().name();\n }\n\n /**\n * @notice Returns the symbol of the provided `product`\n * @param product Product address\n * @return Symbol of the product\n */\n function symbol(IProduct product) external view returns (string memory) {\n return product.productProvider().symbol();\n }\n\n /**\n * @notice Protocol collateral address\n * @return Protocol collateral address\n */\n function collateral() public view returns (ICollateral) {\n return controller.collateral();\n }\n\n /**\n * @notice User collateral amount for product after settle\n * @param account Account address\n * @param product Product address\n * @return User deposited collateral for product\n */\n function collateral(address account, IProduct product) external settleAccount(account, product) returns (UFixed18) {\n return collateral().collateral(account, product);\n }\n\n /**\n * @notice Product total collateral amount after settle\n * @param product Product address\n * @return Total collateral for product\n */\n function collateral(IProduct product) external settle(product) returns (UFixed18) {\n return collateral().collateral(product);\n }\n\n /**\n * @notice Product total shortfall amount after settle\n * @param product Product address\n * @return Total shortfall for product\n */\n function shortfall(IProduct product) external settle(product) returns (UFixed18) {\n return collateral().shortfall(product);\n }\n\n /**\n * @notice User maintenance amount for product after settle\n * @param account Account address\n * @param product Product address\n * @return Maximum of user maintenance, and maintenanceNext\n */\n function maintenance(address account, IProduct product)\n external\n settleAccount(account, product)\n returns (UFixed18)\n {\n return UFixed18Lib.max(product.maintenance(account), product.maintenanceNext(account));\n }\n\n /**\n * @notice User liquidatble status for product after settle\n * @param account Account address\n * @param product Product address\n * @return Whether or not the user's position eligible to be liquidated\n */\n function liquidatable(address account, IProduct product) external settleAccount(account, product) returns (bool) {\n return collateral().liquidatable(account, product);\n }\n\n /**\n * @notice User pre position for product after settle\n * @param account Account address\n * @param product Product address\n * @return User pre-position\n */\n function pre(address account, IProduct product)\n external\n settleAccount(account, product)\n returns (PrePosition memory)\n {\n return product.pre(account);\n }\n\n /**\n * @notice Product pre position after settle\n * @param product Product address\n * @return Product pre-position\n */\n function pre(IProduct product) external settle(product) returns (PrePosition memory) {\n return product.pre();\n }\n\n /**\n * @notice User position for product after settle\n * @param account Account address\n * @param product Product address\n * @return User position\n */\n function position(address account, IProduct product)\n external\n settleAccount(account, product)\n returns (Position memory)\n {\n return product.position(account);\n }\n\n /**\n * @notice Product position after settle\n * @param product Product address\n * @return product position\n */\n function position(IProduct product) external settle(product) returns (Position memory) {\n return latestPosition(product);\n }\n\n /**\n * @notice User pre-position and position for product after settle\n * @param account Account address\n * @param product Product address\n * @return User pre-position\n * @return User position\n */\n function userPosition(address account, IProduct product)\n external\n settleAccount(account, product)\n returns (PrePosition memory, Position memory)\n {\n return (product.pre(account), product.position(account));\n }\n\n /**\n * @notice Product pre-position and position after settle\n * @param product Product address\n * @return Product pre-position\n * @return Product position\n */\n function globalPosition(IProduct product) external settle(product) returns (PrePosition memory, Position memory) {\n return (product.pre(), latestPosition(product));\n }\n\n /**\n * @notice Current price of product after settle\n * @param product Product address\n * @return Product latest price\n */\n function price(IProduct product) external settle(product) returns (Fixed18) {\n return latestVersion(product).price;\n }\n\n /**\n * @notice Fees accumulated by product and protocol treasuries after settle\n * @param product Product address\n * @return protocolFees fees accrued by the protocol\n * @return productFees fees accrued by the product owner\n */\n function fees(IProduct product) external settle(product) returns (UFixed18 protocolFees, UFixed18 productFees) {\n address protocolTreasury = controller.treasury();\n address productTreasury = controller.treasury(product);\n\n protocolFees = collateral().fees(protocolTreasury);\n productFees = collateral().fees(productTreasury);\n }\n\n /**\n * @notice Fees accumulated by treasury after settle\n * @param account Account address\n * @param products Product addresses\n * @return sum of all fees accrued by the account\n */\n function fees(address account, IProduct[] memory products) external returns (UFixed18) {\n for (uint256 i = 0; i < products.length; i++) {\n products[i].settle();\n }\n\n return collateral().fees(account);\n }\n\n /**\n * @notice User's open interest in product after settle\n * @param account Account address\n * @param product Product address\n * @return User's maker or taker position multiplied by latest price after settle\n */\n function openInterest(address account, IProduct product)\n external\n settleAccount(account, product)\n returns (Position memory)\n {\n return product.position(account).mul(latestVersion(product).price.abs());\n }\n\n /**\n * @notice Product total open interest after settle\n * @param product Product address\n * @return Product maker and taker position multiplied by latest price after settle\n */\n function openInterest(IProduct product) external settle(product) returns (Position memory) {\n return latestPosition(product).mul(latestVersion(product).price.abs());\n }\n\n /**\n * @notice Product funding rate after settle\n * @param product Product address\n * @return Product current funding rate\n */\n function rate(IProduct product) external settle(product) returns (Fixed18) {\n Position memory position_ = latestPosition(product);\n return product.productProvider().rate(position_);\n }\n\n /**\n * @notice Product funding extrapolated to a daily rate after settle\n * @param product Product address\n * @return Product current funding extrapolated to a daily rate\n */\n function dailyRate(IProduct product) external settle(product) returns (Fixed18) {\n Position memory position_ = latestPosition(product);\n return product.productProvider().rate(position_).mul(Fixed18Lib.from(60 * 60 * 24));\n }\n\n /**\n * @notice User's maintenance required for position size in product after settle\n * @param account Account address\n * @param product Product address\n * @param positionSize size of position for maintenance calculation\n * @return Maintenance required for position in product\n */\n function maintenanceRequired(\n address account,\n IProduct product,\n UFixed18 positionSize\n ) external settleAccount(account, product) returns (UFixed18) {\n UFixed18 notional = positionSize.mul(latestVersion(product).price.abs());\n return notional.mul(product.productProvider().maintenance());\n }\n\n /**\n * @notice User's unclaimed rewards for all programs for product after settle\n * @param account Account address\n * @param product Product address\n * @return tokens Token addresses of unclaimed incentive rewards for given product\n * @return amounts Token amounts of unclaimed incentive rewards for given product\n */\n function unclaimedIncentiveRewards(address account, IProduct product)\n external\n settleAccount(account, product)\n returns (Token18[] memory tokens, UFixed18[] memory amounts)\n {\n IIncentivizer incentivizer = controller.incentivizer();\n\n uint256 programsLength = incentivizer.count(product);\n tokens = new Token18[](programsLength);\n amounts = new UFixed18[](programsLength);\n for (uint256 i = 0; i < programsLength; i++) {\n ProgramInfo memory programInfo = incentivizer.programInfos(product, i);\n tokens[i] = programInfo.token;\n amounts[i] = incentivizer.unclaimed(product, account, i);\n }\n }\n\n /**\n * @notice User's unclaimed rewards for provided programs for product after settle\n * @param account Account address\n * @param product Product address\n * @param programIds Program IDs to query\n * @return tokens Token addresses of unclaimed incentive rewards for given program IDs\n * @return amounts Token amounts of unclaimed incentive rewards for given program IDs\n */\n function unclaimedIncentiveRewards(\n address account,\n IProduct product,\n uint256[] calldata programIds\n ) external settleAccount(account, product) returns (Token18[] memory tokens, UFixed18[] memory amounts) {\n IIncentivizer incentivizer = controller.incentivizer();\n tokens = new Token18[](programIds.length);\n amounts = new UFixed18[](programIds.length);\n for (uint256 i = 0; i < programIds.length; i++) {\n ProgramInfo memory programInfo = incentivizer.programInfos(product, programIds[i]);\n tokens[i] = programInfo.token;\n amounts[i] = incentivizer.unclaimed(product, account, programIds[i]);\n }\n }\n\n // TODO: all data for Product, all data for User, batching\n\n /**\n * @notice Returns the Product's latest position\n * @dev Internal function, does not call settle itself\n * @param product Product address\n * @return Latest position for the product\n */\n function latestPosition(IProduct product) internal view returns (Position memory) {\n return product.positionAtVersion(product.latestVersion());\n }\n\n /**\n * @notice Returns the Product's latest version\n * @dev Internal function, does not call settle itself\n * @param product Product address\n * @return Latest version for the product\n */\n function latestVersion(IProduct product) internal view returns (IOracleProvider.OracleVersion memory) {\n return product.productProvider().currentVersion();\n }\n\n /// @dev Settles the product\n modifier settle(IProduct product) {\n product.settle();\n _;\n }\n\n /// @dev Settles the product. product.settleAccount also settles the product\n modifier settleAccount(address account, IProduct product) {\n product.settleAccount(account);\n _;\n }\n}\n" + }, + "contracts/oracle/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol\";\nimport \"@equilibria/root/control/unstructured/UOwnable.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport \"../interfaces/IOracleProvider.sol\";\nimport \"./types/ChainlinkRegistry.sol\";\n\n/**\n * @title ChainlinkOracle\n * @notice Chainlink implementation of the IOracle interface.\n * @dev One instance per Chainlink price feed should be deployed. Multiple products may use the same\n * ChainlinkOracle instance if their payoff functions are based on the same underlying oracle.\n * This implementation only support non-negative prices.\n */\ncontract ChainlinkOracle is IOracleProvider, UOwnable {\n /// @dev Chainlink registry feed address\n ChainlinkRegistry public immutable registry;\n\n /// @dev Base token address for the Chainlink oracle\n address public immutable base;\n\n /// @dev Quote token address for the Chainlink oracle\n address public immutable quote;\n\n /// @dev Decimal offset used to normalize chainlink price to 18 decimals\n int256 private immutable _decimalOffset;\n\n /// @dev Mapping of the first oracle version for each underlying phase ID\n uint256[] private _startingVersionForPhaseId;\n\n /**\n * @notice Initializes the contract state\n * @param registry_ Chainlink price feed registry\n * @param base_ base currency for feed\n * @param quote_ quote currency for feed\n */\n constructor(ChainlinkRegistry registry_, address base_, address quote_) {\n registry = registry_;\n base = base_;\n quote = quote_;\n\n _startingVersionForPhaseId.push(0); // phaseId is 1-indexed, skip index 0\n _startingVersionForPhaseId.push(0); // phaseId is 1-indexed, first phase starts as version 0\n _decimalOffset = SafeCast.toInt256(10 ** registry_.decimals(base, quote));\n }\n\n /**\n * @notice Checks for a new price and updates the internal phase annotation state accordingly\n * @return The current oracle version after sync\n */\n function sync() external returns (OracleVersion memory) {\n // Fetch latest round\n ChainlinkRound memory round = registry.getLatestRound(base, quote);\n\n // Update phase annotation when new phase detected\n while (round.phaseId() > _latestPhaseId()) {\n uint256 roundCount = registry.getRoundCount(base, quote, _latestPhaseId());\n _startingVersionForPhaseId.push(roundCount);\n }\n\n // Return packaged oracle version\n return _buildOracleVersion(round);\n }\n\n /**\n * @notice Returns the current oracle version\n * @return oracleVersion Current oracle version\n */\n function currentVersion() public view returns (OracleVersion memory oracleVersion) {\n return _buildOracleVersion(registry.getLatestRound(base, quote));\n }\n\n /**\n * @notice Returns the current oracle version\n * @param version The version of which to lookup\n * @return oracleVersion Oracle version at version `version`\n */\n function atVersion(uint256 version) public view returns (OracleVersion memory oracleVersion) {\n return _buildOracleVersion(registry.getRound(base, quote, _versionToRoundId(version)), version);\n }\n\n /**\n * @notice Builds an oracle version object from a Chainlink round object\n * @dev Computes the version for the round\n * @param round Chainlink round to build from\n * @return Built oracle version\n */\n function _buildOracleVersion(ChainlinkRound memory round) private view returns (OracleVersion memory) {\n uint256 version = _startingVersionForPhaseId[round.phaseId()] +\n uint256(round.roundId - registry.getStartingRoundId(base, quote, round.phaseId()));\n return _buildOracleVersion(round, version);\n }\n\n /**\n * @notice Builds an oracle version object from a Chainlink round object\n * @param round Chainlink round to build from\n * @param version Determined version for the round\n * @return Built oracle version\n */\n function _buildOracleVersion(ChainlinkRound memory round, uint256 version)\n private view returns (OracleVersion memory) {\n Fixed18 price = Fixed18Lib.ratio(round.answer, _decimalOffset);\n return OracleVersion({ version: version, timestamp: round.timestamp, price: price });\n }\n\n /**\n * @notice Computes the chainlink round ID from a version\n * @notice version Version to compute from\n * @return Chainlink round ID\n */\n function _versionToRoundId(uint256 version) private view returns (uint80) {\n uint16 phaseId = _versionToPhaseId(version);\n return registry.getStartingRoundId(base, quote, phaseId) +\n uint80(version - _startingVersionForPhaseId[phaseId]);\n }\n\n /**\n * @notice Computes the chainlink phase ID from a version\n * @param version Version to compute from\n * @return phaseId Chainlink phase ID\n */\n function _versionToPhaseId(uint256 version) private view returns (uint16 phaseId) {\n phaseId = _latestPhaseId();\n while (_startingVersionForPhaseId[phaseId] > version) {\n phaseId--;\n }\n }\n\n /**\n * @notice Returns the latest phase ID that this contract has seen via `sync()`\n * @return Latest seen phase ID\n */\n function _latestPhaseId() private view returns (uint16) {\n return uint16(_startingVersionForPhaseId.length - 1);\n }\n}\n" + }, + "@chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\npragma abicoder v2;\n\nimport \"./AggregatorV2V3Interface.sol\";\n\ninterface FeedRegistryInterface {\n struct Phase {\n uint16 phaseId;\n uint80 startingAggregatorRoundId;\n uint80 endingAggregatorRoundId;\n }\n\n event FeedProposed(\n address indexed asset,\n address indexed denomination,\n address indexed proposedAggregator,\n address currentAggregator,\n address sender\n );\n event FeedConfirmed(\n address indexed asset,\n address indexed denomination,\n address indexed latestAggregator,\n address previousAggregator,\n uint16 nextPhaseId,\n address sender\n );\n\n // V3 AggregatorV3Interface\n\n function decimals(address base, address quote) external view returns (uint8);\n\n function description(address base, address quote) external view returns (string memory);\n\n function version(address base, address quote) external view returns (uint256);\n\n function latestRoundData(address base, address quote)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function getRoundData(\n address base,\n address quote,\n uint80 _roundId\n )\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n // V2 AggregatorInterface\n\n function latestAnswer(address base, address quote) external view returns (int256 answer);\n\n function latestTimestamp(address base, address quote) external view returns (uint256 timestamp);\n\n function latestRound(address base, address quote) external view returns (uint256 roundId);\n\n function getAnswer(\n address base,\n address quote,\n uint256 roundId\n ) external view returns (int256 answer);\n\n function getTimestamp(\n address base,\n address quote,\n uint256 roundId\n ) external view returns (uint256 timestamp);\n\n // Registry getters\n\n function getFeed(address base, address quote) external view returns (AggregatorV2V3Interface aggregator);\n\n function getPhaseFeed(\n address base,\n address quote,\n uint16 phaseId\n ) external view returns (AggregatorV2V3Interface aggregator);\n\n function isFeedEnabled(address aggregator) external view returns (bool);\n\n function getPhase(\n address base,\n address quote,\n uint16 phaseId\n ) external view returns (Phase memory phase);\n\n // Round helpers\n\n function getRoundFeed(\n address base,\n address quote,\n uint80 roundId\n ) external view returns (AggregatorV2V3Interface aggregator);\n\n function getPhaseRange(\n address base,\n address quote,\n uint16 phaseId\n ) external view returns (uint80 startingRoundId, uint80 endingRoundId);\n\n function getPreviousRoundId(\n address base,\n address quote,\n uint80 roundId\n ) external view returns (uint80 previousRoundId);\n\n function getNextRoundId(\n address base,\n address quote,\n uint80 roundId\n ) external view returns (uint80 nextRoundId);\n\n // Feed management\n\n function proposeFeed(\n address base,\n address quote,\n address aggregator\n ) external;\n\n function confirmFeed(\n address base,\n address quote,\n address aggregator\n ) external;\n\n // Proposed aggregator\n\n function getProposedFeed(address base, address quote)\n external\n view\n returns (AggregatorV2V3Interface proposedAggregator);\n\n function proposedGetRoundData(\n address base,\n address quote,\n uint80 roundId\n )\n external\n view\n returns (\n uint80 id,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function proposedLatestRoundData(address base, address quote)\n external\n view\n returns (\n uint80 id,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n // Phases\n function getCurrentPhaseId(address base, address quote) external view returns (uint16 currentPhaseId);\n}\n" + }, + "@equilibria/root/control/unstructured/UOwnable.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"./UInitializable.sol\";\nimport \"../../storage/UStorage.sol\";\n\n/**\n * @title UOwnable\n * @notice Library to manage the ownership lifecycle of upgradeable contracts.\n * @dev This contract has been extended from the Open Zeppelin library to include an\n * unstructured storage pattern so that it can be safely mixed in with upgradeable\n * contracts without affecting their storage patterns through inheritance.\n */\nabstract contract UOwnable is UInitializable {\n event OwnerUpdated(address indexed newOwner);\n event PendingOwnerUpdated(address indexed newPendingOwner);\n\n error UOwnableNotOwnerError(address sender);\n error UOwnableNotPendingOwnerError(address sender);\n\n /// @dev The owner address\n AddressStorage private constant _owner = AddressStorage.wrap(keccak256(\"equilibria.root.UOwnable.owner\"));\n function owner() public view returns (address) { return _owner.read(); }\n\n /// @dev The pending owner address\n AddressStorage private constant _pendingOwner = AddressStorage.wrap(keccak256(\"equilibria.root.UOwnable.pendingOwner\"));\n function pendingOwner() public view returns (address) { return _pendingOwner.read(); }\n\n /**\n * @notice Initializes the contract setting `msg.sender` as the initial owner\n */\n function __UOwnable__initialize() internal onlyInitializer {\n _updateOwner(msg.sender);\n }\n\n /**\n * @notice Updates the new pending owner\n * @dev Can only be called by the current owner\n * New owner does not take affect until that address calls `acceptOwner()`\n * @param newPendingOwner New pending owner address\n */\n function updatePendingOwner(address newPendingOwner) public onlyOwner {\n _pendingOwner.store(newPendingOwner);\n emit PendingOwnerUpdated(newPendingOwner);\n }\n\n /**\n * @notice Accepts and transfers the ownership of the contract to the pending owner\n * @dev Can only be called by the pending owner to ensure correctness\n */\n function acceptOwner() external {\n if (msg.sender != pendingOwner()) revert UOwnableNotPendingOwnerError(msg.sender);\n\n _updateOwner(pendingOwner());\n updatePendingOwner(address(0));\n }\n\n /**\n * @notice Updates the owner address\n * @param newOwner New owner address\n */\n function _updateOwner(address newOwner) private {\n _owner.store(newOwner);\n emit OwnerUpdated(newOwner);\n }\n\n /// @dev Throws if called by any account other than the owner\n modifier onlyOwner() {\n if (owner() != msg.sender) revert UOwnableNotOwnerError(msg.sender);\n _;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128) {\n require(value >= type(int128).min && value <= type(int128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return int128(value);\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64) {\n require(value >= type(int64).min && value <= type(int64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return int64(value);\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32) {\n require(value >= type(int32).min && value <= type(int32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return int32(value);\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16) {\n require(value >= type(int16).min && value <= type(int16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return int16(value);\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8) {\n require(value >= type(int8).min && value <= type(int8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return int8(value);\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "contracts/oracle/types/ChainlinkRegistry.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol\";\nimport \"./ChainlinkRound.sol\";\n\n/// @dev ChainlinkRegistry type\ntype ChainlinkRegistry is address;\nusing ChainlinkRegistryLib for ChainlinkRegistry global;\n\n/**\n * @title ChainlinkRegistryLib\n * @notice Library that manages interfacing with the Chainlink Feed Registry.\n */\nlibrary ChainlinkRegistryLib {\n /**\n * @notice Returns the decimal amount for a specific feed\n * @param self Chainlink Feed Registry to operate on\n * @param base Base currency token address\n * @param quote Quote currency token address\n * @return Decimal amount\n */\n function decimals(ChainlinkRegistry self, address base, address quote) internal view returns (uint8) {\n return FeedRegistryInterface(ChainlinkRegistry.unwrap(self)).decimals(base, quote);\n }\n\n /**\n * @notice Returns the latest round data for a specific feed\n * @param self Chainlink Feed Registry to operate on\n * @param base Base currency token address\n * @param quote Quote currency token address\n * @return Latest round data\n */\n function getLatestRound(ChainlinkRegistry self, address base, address quote) internal view returns (ChainlinkRound memory) {\n (uint80 roundId, int256 answer, , uint256 updatedAt, ) =\n FeedRegistryInterface(ChainlinkRegistry.unwrap(self)).latestRoundData(base, quote);\n return ChainlinkRound({roundId: roundId, timestamp: updatedAt, answer: answer});\n }\n\n /**\n * @notice Returns a specific round's data for a specific feed\n * @param self Chainlink Feed Registry to operate on\n * @param base Base currency token address\n * @param quote Quote currency token address\n * @param roundId The specific round to fetch data for\n * @return Specific round's data\n */\n function getRound(ChainlinkRegistry self, address base, address quote, uint80 roundId) internal view returns (ChainlinkRound memory) {\n (, int256 answer, , uint256 updatedAt, ) =\n FeedRegistryInterface(ChainlinkRegistry.unwrap(self)).getRoundData(base, quote, roundId);\n return ChainlinkRound({roundId: roundId, timestamp: updatedAt, answer: answer});\n }\n\n\n /**\n * @notice Returns the first round ID for a specific phase ID\n * @param self Chainlink Feed Registry to operate on\n * @param base Base currency token address\n * @param quote Quote currency token address\n * @param phaseId The specific phase to fetch data for\n * @return startingRoundId The starting round ID for the phase\n */\n function getStartingRoundId(ChainlinkRegistry self, address base, address quote, uint16 phaseId)\n internal view returns (uint80 startingRoundId) {\n (startingRoundId, ) =\n FeedRegistryInterface(ChainlinkRegistry.unwrap(self)).getPhaseRange(base, quote, phaseId);\n }\n\n /**\n * @notice Returns the quantity of rounds for a specific phase ID\n * @param self Chainlink Feed Registry to operate on\n * @param base Base currency token address\n * @param quote Quote currency token address\n * @param phaseId The specific phase to fetch data for\n * @return The quantity of rounds for the phase\n */\n function getRoundCount(ChainlinkRegistry self, address base, address quote, uint16 phaseId)\n internal view returns (uint80) {\n (uint80 startingRoundId, uint80 endingRoundId) =\n FeedRegistryInterface(ChainlinkRegistry.unwrap(self)).getPhaseRange(base, quote, phaseId);\n return endingRoundId - startingRoundId + 1;\n }\n}" + }, + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./AggregatorInterface.sol\";\nimport \"./AggregatorV3Interface.sol\";\n\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}\n" + }, + "@chainlink/contracts/src/v0.8/interfaces/AggregatorInterface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorInterface {\n function latestAnswer() external view returns (int256);\n\n function latestTimestamp() external view returns (uint256);\n\n function latestRound() external view returns (uint256);\n\n function getAnswer(uint256 roundId) external view returns (int256);\n\n function getTimestamp(uint256 roundId) external view returns (uint256);\n\n event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\n\n event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\n}\n" + }, + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "contracts/oracle/types/ChainlinkRound.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\n/// @dev ChainlinkRound type\nstruct ChainlinkRound {\n uint256 timestamp;\n int256 answer;\n uint80 roundId;\n}\nusing ChainlinkRoundLib for ChainlinkRound global;\n\n/**\n * @title ChainlinkRoundLib\n * @notice Library that manages Chainlink round parsing.\n */\nlibrary ChainlinkRoundLib {\n /// @dev Phase ID offset location in the round ID\n uint256 constant private PHASE_OFFSET = 64;\n\n /**\n * @notice Computes the chainlink phase ID from a round\n * @param self Round to compute from\n * @return Chainlink phase ID\n */\n function phaseId(ChainlinkRound memory self) internal pure returns (uint16) {\n return uint16(self.roundId >> PHASE_OFFSET);\n }\n}" + }, + "contracts/test/PassthroughChainlinkFeed.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol\";\n\ncontract PassthroughChainlinkFeed {\n FeedRegistryInterface private _underlying;\n\n constructor(FeedRegistryInterface underlying_) {\n _underlying = underlying_;\n }\n\n function decimals(address base, address quote) external view returns (uint8) {\n return _underlying.decimals(base, quote);\n }\n\n function getRoundData(address base, address quote, uint80 roundId) external view returns (uint80, int256, uint256, uint256, uint80) {\n return _underlying.getRoundData(base, quote, roundId);\n }\n\n function getPhaseRange(address base, address quote, uint16 phaseId) external view returns (uint80, uint80) {\n return _underlying.getPhaseRange(base, quote, phaseId);\n }\n\n function latestRoundData(address base, address quote) external view returns (uint80, int256, uint256, uint256, uint80) {\n return _underlying.latestRoundData(base, quote);\n }\n}\n" + }, + "contracts/incentivizer/Incentivizer.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"@equilibria/root/control/unstructured/UReentrancyGuard.sol\";\nimport \"../interfaces/IIncentivizer.sol\";\nimport \"../interfaces/IController.sol\";\nimport \"../controller/UControllerProvider.sol\";\nimport \"./types/ProductManager.sol\";\n\n/**\n * @title Incentivizer\n * @notice Manages logic and state for all incentive programs in the protocol.\n */\ncontract Incentivizer is IIncentivizer, UInitializable, UControllerProvider, UReentrancyGuard {\n /// @dev Product management state\n mapping(IProduct => ProductManager) private _products;\n\n /// @dev Fees that have been collected, but remain unclaimed\n mapping(Token18 => UFixed18) public fees;\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 * @param controller_ Factory contract address\n */\n function initialize(IController controller_) external initializer(1) {\n __UControllerProvider__initialize(controller_);\n __UReentrancyGuard__initialize();\n }\n\n /**\n * @notice Creates a new incentive program\n * @dev Must be called as the product or protocol owner\n * @param product The product to create the new program on\n * @param programInfo Parameters for the new program\n * @return programId New program's ID\n */\n function create(IProduct product, ProgramInfo calldata programInfo)\n external\n nonReentrant\n isProduct(product)\n notPausedProduct(product)\n onlyOwner(programInfo.coordinatorId)\n returns (uint256 programId) {\n IController _controller = controller();\n\n // Validate\n if (programInfo.coordinatorId != 0 && programInfo.coordinatorId != _controller.coordinatorFor(product))\n revert IncentivizerNotAllowedError(product);\n if (active(product) >= _controller.programsPerProduct())\n revert IncentivizerTooManyProgramsError();\n ProgramInfoLib.validate(programInfo);\n\n // Take fee\n (ProgramInfo memory newProgramInfo, UFixed18 programFeeAmount) = ProgramInfoLib.deductFee(programInfo, _controller.incentivizationFee());\n fees[newProgramInfo.token] = fees[newProgramInfo.token].add(programFeeAmount);\n\n // Register program\n programId = _products[product].register(newProgramInfo);\n\n // Charge creator\n newProgramInfo.token.pull(msg.sender, programInfo.amount.sum());\n\n emit ProgramCreated(\n product,\n programId,\n newProgramInfo.coordinatorId,\n newProgramInfo.token,\n newProgramInfo.amount.maker,\n newProgramInfo.amount.taker,\n newProgramInfo.start,\n newProgramInfo.duration,\n programFeeAmount\n );\n }\n\n /**\n * @notice Completes an in-progress program early\n * @dev Must be called as the program owner\n * @param product Product that the program is running on\n * @param programId Program to complete early\n */\n function complete(IProduct product, uint256 programId)\n external\n nonReentrant\n isProgram(product, programId)\n notPausedProduct(product)\n onlyProgramOwner(product, programId)\n {\n ProductManagerLib.SyncResult memory syncResult = _products[product].complete(product, programId);\n _handleSyncResult(product, syncResult);\n }\n\n /**\n * @notice Starts and completes programs as they become available\n * @dev Called every settle() from each product\n * @param currentOracleVersion The preloaded current oracle version\n */\n function sync(IOracleProvider.OracleVersion memory currentOracleVersion) external onlyProduct {\n IProduct product = IProduct(msg.sender);\n\n ProductManagerLib.SyncResult[] memory syncResults = _products[product].sync(product, currentOracleVersion);\n for (uint256 i = 0; i < syncResults.length; i++) {\n _handleSyncResult(product, syncResults[i]);\n }\n }\n\n /**\n * @notice Handles refunding and event emitting on program start and completion\n * @param product Product that the program is running on\n * @param syncResult The data from the sync event to handle\n */\n function _handleSyncResult(IProduct product, ProductManagerLib.SyncResult memory syncResult) private {\n uint256 programId = syncResult.programId;\n if (!syncResult.refundAmount.isZero())\n _products[product].token(programId).push(treasury(product, programId), syncResult.refundAmount);\n if (syncResult.versionStarted != 0)\n emit ProgramStarted(product, programId, syncResult.versionStarted);\n if (syncResult.versionComplete != 0)\n emit ProgramComplete(product, programId, syncResult.versionComplete);\n }\n\n /**\n * @notice Settles unsettled balance for `account`\n * @dev Called immediately proceeding a position update in the corresponding product\n * @param account Account to sync\n * @param currentOracleVersion The preloaded current oracle version\n */\n function syncAccount(\n address account,\n IOracleProvider.OracleVersion memory currentOracleVersion\n ) external onlyProduct {\n IProduct product = IProduct(msg.sender);\n _products[product].syncAccount(product, account, currentOracleVersion);\n }\n\n /**\n * @notice Claims all of `msg.sender`'s rewards for `product` programs\n * @param product Product to claim rewards for\n * @param programIds Programs to claim rewards for\n */\n function claim(IProduct product, uint256[] calldata programIds)\n external\n nonReentrant\n {\n _claimProduct(product, programIds);\n }\n\n /**\n * @notice Claims all of `msg.sender`'s rewards for a specific program\n * @param products Products to claim rewards for\n * @param programIds Programs to claim rewards for\n */\n function claim(IProduct[] calldata products, uint256[][] calldata programIds)\n external\n nonReentrant\n {\n uint256 productCount = products.length;\n for (uint256 i; i < productCount; i++) {\n _claimProduct(products[i], programIds[i]);\n }\n }\n\n /**\n * @notice Claims all of `msg.sender`'s rewards for `product` programs\n * @dev Internal helper with validation checks\n * @param product Product to claim rewards for\n * @param programIds Programs to claim rewards for\n */\n function _claimProduct(IProduct product, uint256[] memory programIds)\n private\n isProduct(product)\n notPausedProduct(product)\n settleForAccount(msg.sender, product)\n {\n uint256 programCount = programIds.length;\n for (uint256 i; i < programCount; i++) {\n _claimProgram(product, programIds[i]);\n }\n }\n\n /**\n * @notice Claims all of `msg.sender`'s rewards for `programId` on `product`\n * @dev Internal helper with validation checks\n * @param product Product to claim rewards for\n * @param programId Program to claim rewards for\n */\n function _claimProgram(IProduct product, uint256 programId)\n private\n isProgram(product, programId)\n {\n ProductManager storage productManager = _products[product];\n UFixed18 claimAmount = productManager.claim(msg.sender, programId);\n productManager.token(programId).push(msg.sender, claimAmount);\n emit Claim(product, msg.sender, programId, claimAmount);\n }\n\n /**\n * @notice Claims all `tokens` fees to the protocol treasury\n * @param tokens Tokens to claim fees for\n */\n function claimFee(Token18[] calldata tokens) external notPaused {\n for(uint256 i; i < tokens.length; i++) {\n Token18 token = tokens[i];\n UFixed18 amount = fees[token];\n if (amount.isZero()) continue;\n\n fees[token] = UFixed18Lib.ZERO;\n token.push(controller().treasury(), amount);\n\n emit FeeClaim(token, amount);\n }\n }\n\n /**\n * @notice Returns the quantity of active programs for a given product\n * @param product Product to check for\n * @return Number of active programs\n */\n function active(IProduct product) public view returns (uint256) {\n return _products[product].active();\n }\n\n /**\n * @notice Returns the quantity of programs for a given product\n * @param product Product to check for\n * @return Number of programs (inactive or active)\n */\n function count(IProduct product) external view returns (uint256) {\n return _products[product].programInfos.length;\n }\n\n /**\n * @notice Returns program info for program `programId`\n * @param product Product to return for\n * @param programId Program to return for\n * @return Program info\n */\n function programInfos(IProduct product, uint256 programId) external view returns (ProgramInfo memory) {\n return _products[product].programInfos[programId];\n }\n\n /**\n * @notice Returns `account`'s total unclaimed rewards for a specific program\n * @param product Product to return for\n * @param account Account to return for\n * @param programId Program to return for\n * @return `account`'s total unclaimed rewards for `programId`\n */\n function unclaimed(IProduct product, address account, uint256 programId) external view returns (UFixed18) {\n return _products[product].unclaimed(account, programId);\n }\n\n /**\n * @notice Returns available rewards for a specific program\n * @param product Product to return for\n * @param programId Program to return for\n * @return Available rewards for `programId`\n */\n function available(IProduct product, uint256 programId) external view returns (UFixed18) {\n return _products[product].programs[programId].available;\n }\n\n /**\n * @notice Returns the version started for a specific program\n * @param product Product to return for\n * @param programId Program to return for\n * @return The version started for `programId`\n */\n function versionStarted(IProduct product, uint256 programId) external view returns (uint256) {\n return _products[product].programs[programId].versionStarted;\n }\n\n /**\n * @notice Returns the version completed for a specific program\n * @param product Product to return for\n * @param programId Program to return for\n * @return The version completed for `programId`\n */\n function versionComplete(IProduct product, uint256 programId) external view returns (uint256) {\n return _products[product].programs[programId].versionComplete;\n }\n\n /**\n * @notice Returns the owner of a specific program\n * @param product Product to return for\n * @param programId Program to return for\n * @return The owner of `programId`\n */\n function owner(IProduct product, uint256 programId) public view returns (address) {\n return controller().owner(_products[product].programInfos[programId].coordinatorId);\n }\n\n /**\n * @notice Returns the treasury of a specific program\n * @param product Product to return for\n * @param programId Program to return for\n * @return The treasury of `programId`\n */\n function treasury(IProduct product, uint256 programId) public view returns (address) {\n return controller().treasury(_products[product].programInfos[programId].coordinatorId);\n }\n\n /// @dev Helper to fully settle an account's state\n modifier settleForAccount(address account, IProduct product) {\n product.settleAccount(account);\n\n _;\n }\n\n /// @dev Only allow the owner of `programId` to call\n modifier onlyProgramOwner(IProduct product, uint256 programId) {\n if (msg.sender != owner(product, programId)) revert IncentivizerNotProgramOwnerError(product, programId);\n\n _;\n }\n\n /// @dev Only allow a valid `programId`\n modifier isProgram(IProduct product, uint256 programId) {\n if (!_products[product].valid(programId)) revert IncentivizerInvalidProgramError(product, programId);\n\n _;\n }\n}\n" + }, + "contracts/incentivizer/types/ProductManager.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"./Program.sol\";\n\n/// @dev ProductManager type\nstruct ProductManager {\n /// @dev Static program state\n ProgramInfo[] programInfos;\n\n /// @dev Dynamic program state\n mapping(uint256 => Program) programs;\n\n /// @dev Mapping of all active programs for each product\n EnumerableSet.UintSet activePrograms;\n\n /// @dev Mapping of all active programs for each user\n mapping(address => EnumerableSet.UintSet) activeProgramsFor;\n\n /// @dev Mapping of the next program to watch for for each user\n mapping(address => uint256) nextProgramFor;\n}\nusing ProductManagerLib for ProductManager global;\n\n/**\n * @title ProductManagerLib\n * @notice Library that manages each product's incentivization state and logic.\n */\nlibrary ProductManagerLib {\n using EnumerableSet for EnumerableSet.UintSet;\n\n /// @dev Result data for a sync event\n struct SyncResult {\n /// @dev The programId that was updated\n uint256 programId;\n\n /// @dev If non-zero, the new versionStart value of the program\n uint256 versionStarted;\n\n /// @dev If non-zero, the new versionComplete value of the program\n uint256 versionComplete;\n\n /// @dev If non-zero, the amount to refund due to completion\n UFixed18 refundAmount;\n }\n\n /**\n * @notice Registers a new program on this product\n * @param self The Program manager to operate on\n * @param programInfo The static program info\n * @return programId The new program's ID\n */\n function register(\n ProductManager storage self,\n ProgramInfo memory programInfo\n ) internal returns (uint256 programId) {\n programId = self.programInfos.length;\n self.programInfos.push(programInfo);\n self.programs[programId].initialize(programInfo);\n self.activePrograms.add(programId);\n }\n\n /**\n * @notice Syncs this product with the latest data\n * @param self The Program manager to operate on\n * @param product This Product\n * @param currentOracleVersion The preloaded current oracle version\n */\n function sync(\n ProductManager storage self,\n IProduct product,\n IOracleProvider.OracleVersion memory currentOracleVersion\n ) internal returns (SyncResult[] memory results) {\n\n uint256[] memory activeProgramIds = self.activePrograms.values();\n results = new SyncResult[](activeProgramIds.length);\n\n for (uint256 i; i < activeProgramIds.length; i++) {\n // Load program\n uint256 programId = activeProgramIds[i];\n ProgramInfo memory programInfo = self.programInfos[programId];\n Program storage program = self.programs[programId];\n\n // If timestamp-started, grab current version (first version after start)\n uint256 versionStarted;\n if (program.versionStarted == 0 && programInfo.isStarted(currentOracleVersion.timestamp)) {\n versionStarted = _start(self, programId, currentOracleVersion);\n }\n\n // If timestamp-completed, grab previous version (last version before completion)\n uint256 versionComplete;\n UFixed18 refundAmount;\n if (program.versionComplete == 0 && programInfo.isComplete(currentOracleVersion.timestamp)) {\n (versionComplete, refundAmount) = _complete(self, product, programId);\n }\n\n // Save result\n results[i] = SyncResult(programId, versionStarted, versionComplete, refundAmount);\n }\n }\n\n /**\n * @notice Syncs an account for this product with the latest data\n * @dev Assumes that sync() has already been called as part of the transaction flow\n * @param self The Program manager to operate on\n * @param product This Product\n * @param account The account to sync\n * @param currentOracleVersion The preloaded current oracle version\n */\n function syncAccount(\n ProductManager storage self,\n IProduct product,\n address account,\n IOracleProvider.OracleVersion memory currentOracleVersion\n ) internal {\n\n // Add any unseen programs\n uint256 fromProgramId = self.nextProgramFor[account];\n uint256 toProgramId = self.programInfos.length;\n for (uint256 programId = fromProgramId; programId < toProgramId; programId++) {\n self.activeProgramsFor[account].add(programId);\n }\n self.nextProgramFor[account] = toProgramId;\n\n // Settle programs\n uint256[] memory activeProgramIds = self.activeProgramsFor[account].values();\n for (uint256 i; i < activeProgramIds.length; i++) {\n uint256 programId = activeProgramIds[i];\n Program storage program = self.programs[programId];\n program.settle(product, self.programInfos[programId], account, currentOracleVersion);\n if (!self.activePrograms.contains(programId) && currentOracleVersion.version >= program.versionComplete) {\n self.activeProgramsFor[account].remove(programId);\n }\n }\n }\n\n /**\n * @notice Returns the quantity of active programs for this product\n * @param self The Program manager to operate on\n * @return The quantity of active programs\n */\n function active(ProductManager storage self) internal view returns (uint256) {\n return self.activePrograms.length();\n }\n\n /**\n * @notice Forces the specified program to complete if it hasn't already\n * @param self The Program manager to operate on\n * @param product The Product to operate on\n * @param programId The Program to complete\n * @return result The sync result data from completion\n */\n function complete(\n ProductManager storage self,\n IProduct product,\n uint256 programId\n ) internal returns (SyncResult memory result) {\n Program storage program = self.programs[programId];\n\n // If not started, start first\n if (program.versionStarted == 0) {\n result.versionStarted = _start(self, programId, product.productProvider().currentVersion());\n }\n\n // If not completed already, complete\n if (program.versionComplete == 0) {\n (result.versionComplete, result.refundAmount) = _complete(self, product, programId);\n }\n }\n\n /**\n * @notice Starts the program\n * @dev Rewards do not start accruing until the program has started\n * Internal helper, does not prevent incorrectly-timed starting\n * @param self The Program manager to operate on\n * @param programId The Program to start\n * @param currentOracleVersion The effective starting oracle version\n * @return versionStarted The version that the program started\n */\n function _start(\n ProductManager storage self,\n uint256 programId,\n IOracleProvider.OracleVersion memory currentOracleVersion\n ) internal returns (uint256 versionStarted) {\n versionStarted = currentOracleVersion.version;\n self.programs[programId].start(currentOracleVersion.version);\n }\n\n /**\n * @notice Completes the program\n * @dev Completion stops rewards from accruing\n * Internal helper, does not prevent incorrectly-timed completion\n * @param self The Program manager to operate on\n * @param product The Product to operate on\n * @param programId The Program to complete\n * @return versionComplete The version that the program complete\n * @return refundAmount The refunded token amount\n */\n function _complete(\n ProductManager storage self,\n IProduct product,\n uint256 programId\n ) internal returns (uint256 versionComplete, UFixed18 refundAmount) {\n (versionComplete, refundAmount) = self.programs[programId].complete(product, self.programInfos[programId]);\n self.activePrograms.remove(programId);\n }\n\n /**\n * @notice Claims all of `account`'s rewards for a specific program\n * @param self The Program manager to operate on\n * @param account Account to claim rewards for\n * @param programId Program to claim rewards for\n * @return Amount claimed\n */\n function claim(ProductManager storage self, address account, uint256 programId) internal returns (UFixed18) {\n return self.programs[programId].claim(account);\n }\n\n /**\n * @notice Returns the total amount of unclaimed rewards for account `account`\n * @param self The Program manager to operate on\n * @param account The account to check for\n * @param programId The Program to check for\n * @return Total amount of unclaimed rewards for account\n */\n function unclaimed(ProductManager storage self, address account, uint256 programId) internal view returns (UFixed18) {\n if (!valid(self, programId)) return (UFixed18Lib.ZERO);\n return self.programs[programId].settled[account];\n }\n\n /**\n * @notice Returns the token denominatino of the program's rewards\n * @param self The Program manager to operate on\n * @param programId The Program to check for\n * @return The token for the program\n */\n function token(ProductManager storage self, uint256 programId) internal view returns (Token18) {\n return self.programInfos[programId].token;\n }\n\n /**\n * @notice Returns whether the supplied programId is valid\n * @param self The Program manager to operate on\n * @param programId The Program to check for\n * @return Whether the supplied programId is valid\n */\n function valid(ProductManager storage self, uint256 programId) internal view returns (bool) {\n return programId < self.programInfos.length;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n return _values(set._inner);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "contracts/incentivizer/types/Program.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"../../interfaces/types/ProgramInfo.sol\";\n\n/// @dev Program type\nstruct Program {\n /// @dev Mapping of latest rewards settled for each account\n mapping(address => UFixed18) settled;\n\n /// @dev Total amount of rewards yet to be claimed\n UFixed18 available;\n\n /// @dev Oracle version that the program started, 0 when hasn't started\n uint256 versionStarted;\n\n /// @dev Oracle version that the program completed, 0 is still ongoing\n uint256 versionComplete;\n}\nusing ProgramLib for Program global;\n\n/**\n * @title ProgramLib\n * @notice Library that manages all of the mutable state for a single incentivization program.\n */\nlibrary ProgramLib {\n /**\n * @notice Initializes the program state\n * @param self The Program to operate on\n * @param programInfo Static program information\n */\n function initialize(Program storage self, ProgramInfo memory programInfo) internal {\n self.available = programInfo.amount.sum();\n }\n\n /**\n * @notice Starts the program\n * @dev Rewards do not start accruing until the program has started accruing\n * Does not stop double-starting\n * @param self The Program to operate on\n * @param oracleVersion The effective starting oracle version\n */\n function start(Program storage self, uint256 oracleVersion) internal {\n self.versionStarted = oracleVersion;\n }\n\n /**\n * @notice Completes the program\n * @dev Completion stops rewards from accruing\n * Does not prevent double-completion\n * @param self The Program to operate on\n * @param product The Product to operate on\n * @param programInfo Static program information\n * @return versionComplete The version that the program completed on\n * @return refundAmount The refund amount from the program\n */\n function complete(\n Program storage self,\n IProduct product,\n ProgramInfo memory programInfo\n ) internal returns (uint256 versionComplete, UFixed18 refundAmount) {\n uint256 versionStarted = self.versionStarted;\n versionComplete = Math.max(versionStarted, product.latestVersion());\n self.versionComplete = versionComplete;\n\n IProductProvider productProvider = product.productProvider();\n IOracleProvider.OracleVersion memory fromOracleVersion = productProvider.atVersion(versionStarted);\n IOracleProvider.OracleVersion memory toOracleVersion = productProvider.atVersion(versionComplete);\n\n uint256 inactiveDuration = programInfo.duration - (toOracleVersion.timestamp - fromOracleVersion.timestamp);\n refundAmount = programInfo.amount.sum().muldiv(inactiveDuration, programInfo.duration);\n self.available = self.available.sub(refundAmount);\n }\n\n /**\n * @notice Settles unclaimed rewards for account `account`\n * @param self The Program to operate on\n * @param product The Product to operate on\n * @param programInfo Static program information\n * @param account The account to settle for\n * @param currentOracleVersion The preloaded current oracle version\n */\n function settle(\n Program storage self,\n IProduct product,\n ProgramInfo memory programInfo,\n address account,\n IOracleProvider.OracleVersion memory currentOracleVersion\n ) internal {\n UFixed18 unsettledAmount = _unsettled(self, product, programInfo, account, currentOracleVersion);\n self.settled[account] = self.settled[account].add(unsettledAmount);\n self.available = self.available.sub(unsettledAmount);\n }\n\n /**\n * @notice Claims settled rewards for account `account`\n * @param self The Program to operate on\n * @param account The account to claim for\n */\n function claim(Program storage self, address account) internal returns (UFixed18 claimedAmount) {\n claimedAmount = self.settled[account];\n self.settled[account] = UFixed18Lib.ZERO;\n }\n\n /**\n * @notice Returns the unsettled amount of unclaimed rewards for account `account`\n * @dev Clears when a program is closed\n * Assumes that position is unchanged since last settlement, must be settled prior to user position update\n * @param self The Program to operate on\n * @param product The Product to operate on\n * @param programInfo Static program information\n * @param account The account to claim for\n * @param currentOracleVersion Current oracle version\n * @return amount Amount of unsettled rewards for account\n */\n function _unsettled(\n Program storage self,\n IProduct product,\n ProgramInfo memory programInfo,\n address account,\n IOracleProvider.OracleVersion memory currentOracleVersion\n ) private view returns (UFixed18 amount) {\n // program stage overview\n //\n // V = latest user settle version, V' = current user settle version\n // S = versionStarted, E = versionEnded\n //\n // (1) V V' S E program not yet started\n // (2) V S V' E use versionStarted -> V' for userShareDelta\n // (3) S V V' E use V -> V' for userShareDelta\n // (4) S V E V' use V -> versionComplete for userShareDelta\n // (5) S E V V' program already completed\n // (6) V S E V' use versionStarted -> versionComplete for userShareDelta\n //\n // NOTE: V == S and V' == E both default to the inner case\n\n (uint256 _versionStarted, uint256 _versionComplete) = (\n self.versionStarted == 0 ? currentOracleVersion.version : self.versionStarted, // start must be no earlier than current version\n self.versionComplete == 0 ? type(uint256).max : self.versionComplete // we don't know when completion occurs\n );\n\n // accruing must start between self.versionStarted and self.versionComplete\n uint256 fromVersion = Math.min(_versionComplete, Math.max(_versionStarted, product.latestVersion(account)));\n // accruing must complete between self.versionStarted and self.versionComplete, we know self.versionStarted must be no earlier than current version\n uint256 toVersion = Math.min(_versionComplete, currentOracleVersion.version);\n\n Accumulator memory globalShareDelta = product.shareAtVersion(toVersion).sub(product.shareAtVersion(fromVersion));\n Accumulator memory computedUserShareDelta = product.position(account).mul(globalShareDelta);\n amount = UFixed18Lib.from(programInfo.amountPerShare().mul(computedUserShareDelta).sum());\n }\n}\n" + }, + "contracts/test/TestnetProductProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@equilibria/root/curve/types/JumpRateUtilizationCurve.sol\";\nimport \"../interfaces/IProductProvider.sol\";\n\ncontract TestnetProductProvider is IProductProvider {\n string public constant name = \"Squeeth\";\n string public constant symbol = \"SQTH\";\n\n IOracleProvider public immutable oracle;\n JumpRateUtilizationCurveStorage private constant _utilizationCurve =\n JumpRateUtilizationCurveStorage.wrap(keccak256(\"equilibria.perennial.TestnetProductProvider.utilizationCurve\"));\n\n constructor(IOracleProvider oracle_, JumpRateUtilizationCurve memory utilizationCurve_) {\n oracle = oracle_;\n _utilizationCurve.store(utilizationCurve_);\n }\n\n function sync() external returns (OracleVersion memory) {\n return _transform(oracle.sync());\n }\n\n function currentVersion() external view returns (OracleVersion memory) {\n return _transform(oracle.currentVersion());\n }\n\n function atVersion(uint256 oracleVersion) external view returns (OracleVersion memory) {\n return _transform(oracle.atVersion(oracleVersion));\n }\n\n function rate(Position memory position) external view returns (Fixed18) {\n UFixed18 utilization = position.taker.unsafeDiv(position.maker);\n Fixed18 annualizedRate = _utilizationCurve.read().compute(utilization);\n return annualizedRate.div(Fixed18Lib.from(365 days));\n }\n\n function maintenance() external pure returns (UFixed18) {\n return UFixed18Lib.ratio(30, 100);\n }\n\n function fundingFee() external pure returns (UFixed18) {\n return UFixed18Lib.ratio(10, 100);\n }\n\n function makerFee() external pure returns (UFixed18) {\n return UFixed18Lib.ZERO;\n }\n\n function takerFee() external pure returns (UFixed18) {\n return UFixed18Lib.ZERO;\n }\n\n function makerLimit() external pure returns (UFixed18) {\n return UFixed18Lib.from(1);\n }\n\n function _transform(OracleVersion memory oracleVersion) internal pure returns (OracleVersion memory) {\n return OracleVersion({\n version: oracleVersion.version,\n timestamp: oracleVersion.timestamp,\n price: _payoff(oracleVersion.price)\n });\n }\n\n function _payoff(Fixed18 price) internal pure returns (Fixed18) {\n return price.mul(price);\n }\n}\n" + }, + "contracts/controller/Controller.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\";\nimport \"../interfaces/IController.sol\";\nimport \"../interfaces/ICollateral.sol\";\nimport \"../interfaces/IIncentivizer.sol\";\nimport \"../interfaces/IProduct.sol\";\n\n/**\n * @title Controller\n * @notice Manages creating new products and global protocol parameters.\n */\ncontract Controller is IController, UInitializable {\n /// @dev Collateral contract address for the protocol\n AddressStorage private constant _collateral = AddressStorage.wrap(keccak256(\"equilibria.perennial.Controller.collateral\"));\n function collateral() public view returns (ICollateral) { return ICollateral(_collateral.read()); }\n\n /// @dev Incentivizer contract address for the protocol\n AddressStorage private constant _incentivizer = AddressStorage.wrap(keccak256(\"equilibria.perennial.Controller.incentivizer\"));\n function incentivizer() public view returns (IIncentivizer) { return IIncentivizer(_incentivizer.read()); }\n\n /// @dev Product implementation beacon address for the protocol\n AddressStorage private constant _productBeacon = AddressStorage.wrap(keccak256(\"equilibria.perennial.Controller.productBeacon\"));\n function productBeacon() public view returns (IBeacon) { return IBeacon(_productBeacon.read()); }\n\n /// @dev Percent of collected fees that go to the protocol treasury vs the product treasury\n UFixed18Storage private constant _protocolFee = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.Controller.protocolFee\"));\n function protocolFee() public view returns (UFixed18) { return _protocolFee.read(); }\n\n /// @dev Minimum allowable funding fee for a product\n UFixed18Storage private constant _minFundingFee = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.Controller.minFundingFee\"));\n function minFundingFee() public view returns (UFixed18) { return _minFundingFee.read(); }\n\n /// @dev Fee on maintenance for liquidation\n UFixed18Storage private constant _liquidationFee = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.Controller.liquidationFee\"));\n function liquidationFee() public view returns (UFixed18) { return _liquidationFee.read(); }\n\n /// @dev Fee on incentivization programs\n UFixed18Storage private constant _incentivizationFee = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.Controller.incentivizationFee\"));\n function incentivizationFee() public view returns (UFixed18) { return _incentivizationFee.read(); }\n\n /// @dev Minimum allowable collateral amount per user account\n UFixed18Storage private constant _minCollateral = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.Controller.minCollateral\"));\n function minCollateral() public view returns (UFixed18) { return _minCollateral.read(); }\n\n /// @dev Maximum incentivization programs per product allowed\n Uint256Storage private constant _programsPerProduct = Uint256Storage.wrap(keccak256(\"equilibria.perennial.Controller.programsPerProduct\"));\n function programsPerProduct() public view returns (uint256) { return _programsPerProduct.read(); }\n\n /// @dev List of product coordinators\n Coordinator[] private _coordinators;\n\n /// @dev Mapping of the coordinator for each product\n mapping(IProduct => uint256) public coordinatorFor;\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 * @param collateral_ Collateral contract address\n * @param incentivizer_ Incentivizer contract address\n * @param productBeacon_ Product implementation beacon address\n */\n function initialize(\n ICollateral collateral_,\n IIncentivizer incentivizer_,\n IBeacon productBeacon_\n ) external initializer(1) {\n _createCoordinator(msg.sender);\n\n updateCollateral(collateral_);\n updateIncentivizer(incentivizer_);\n updateProductBeacon(productBeacon_);\n }\n\n /**\n * @notice Creates a new coordinator with `msg.sender` as the owner\n * @dev Can only be called by the protocol owner\n * @param coordinatorOwner The owner address of the new coordinator\n * @return New coordinator ID\n */\n function createCoordinator(address coordinatorOwner) external onlyOwner(0) returns (uint256) {\n return _createCoordinator(coordinatorOwner);\n }\n\n /**\n * @notice Creates a new coordinator with `msg.sender` as the owner\n * @dev `treasury` and `pauser` initialize as the 0-address, defaulting to the `owner`\n * @param coordinatorOwner The owner address of the new coordinator\n * @return New coordinator ID\n */\n function _createCoordinator(address coordinatorOwner) private returns (uint256) {\n uint256 coordinatorId = _coordinators.length;\n\n _coordinators.push(Coordinator({\n pendingOwner: address(0),\n owner: coordinatorOwner,\n treasury: address(0),\n pauser: address(0),\n paused: false\n }));\n\n emit CoordinatorCreated(coordinatorId, coordinatorOwner);\n\n return coordinatorId;\n }\n\n /**\n * @notice Updates the pending owner of an existing coordinator\n * @dev Must be called by the coordinator's current owner\n * @param coordinatorId Coordinator to update\n * @param newPendingOwner New pending owner address\n */\n function updateCoordinatorPendingOwner(uint256 coordinatorId, address newPendingOwner) external onlyOwner(coordinatorId) {\n _coordinators[coordinatorId].pendingOwner = newPendingOwner;\n emit CoordinatorPendingOwnerUpdated(coordinatorId, newPendingOwner);\n }\n\n /**\n * @notice Accepts ownership over an existing coordinator\n * @dev Must be called by the coordinator's pending owner\n * @param coordinatorId Coordinator to update\n */\n function acceptCoordinatorOwner(uint256 coordinatorId) external {\n Coordinator storage coordinator = _coordinators[coordinatorId];\n address newPendingOwner = coordinator.pendingOwner;\n\n if (msg.sender != newPendingOwner) revert ControllerNotPendingOwnerError(coordinatorId);\n\n coordinator.pendingOwner = address(0);\n coordinator.owner = newPendingOwner;\n emit CoordinatorOwnerUpdated(coordinatorId, newPendingOwner);\n }\n\n /**\n * @notice Updates the treasury of an existing coordinator\n * @dev Must be called by the coordinator's current owner\n * @param coordinatorId Coordinator to update\n * @param newTreasury New treasury address\n */\n function updateCoordinatorTreasury(uint256 coordinatorId, address newTreasury) external onlyOwner(coordinatorId) {\n _coordinators[coordinatorId].treasury = newTreasury;\n emit CoordinatorTreasuryUpdated(coordinatorId, newTreasury);\n }\n\n /**\n * @notice Updates the pauser of an existing coordinator\n * @dev Must be called by the coordinator's current owner\n * @param coordinatorId Coordinator to update\n * @param newPauser New pauser address\n */\n function updateCoordinatorPauser(uint256 coordinatorId, address newPauser) external onlyOwner(coordinatorId) {\n _coordinators[coordinatorId].pauser = newPauser;\n emit CoordinatorPauserUpdated(coordinatorId, newPauser);\n }\n\n /**\n * @notice Updates the paused status of an existing coordinator\n * @dev Must be called by the coordinator's current owner\n * @param coordinatorId Coordinator to update\n * @param newPaused New paused status\n */\n function updateCoordinatorPaused(uint256 coordinatorId, bool newPaused) external onlyPauser(coordinatorId) {\n _coordinators[coordinatorId].paused = newPaused;\n emit CoordinatorPausedUpdated(coordinatorId, newPaused);\n }\n\n /**\n * @notice Creates a new product market with `provider`\n * @dev Can only be called by the protocol owner\n * @param coordinatorId Coordinator that will own the product\n * @param provider Provider that will service the market\n * @return New product contract address\n */\n function createProduct(uint256 coordinatorId, IProductProvider provider) external onlyOwner(0) returns (IProduct) {\n if (coordinatorId == 0) revert ControllerNoZeroCoordinatorError();\n\n BeaconProxy newProductProxy = new BeaconProxy(address(productBeacon()), abi.encodeCall(IProduct.initialize, provider));\n IProduct newProduct = IProduct(address(newProductProxy));\n coordinatorFor[newProduct] = coordinatorId;\n emit ProductCreated(newProduct, provider);\n\n return newProduct;\n }\n\n /**\n * @notice Updates the Collateral contract address\n * @param newCollateral New Collateral contract address\n */\n function updateCollateral(ICollateral newCollateral) public onlyOwner(0) {\n _collateral.store(address(newCollateral));\n emit CollateralUpdated(newCollateral);\n }\n\n /**\n * @notice Updates the Incentivizer contract address\n * @param newIncentivizer New Incentivizer contract address\n */\n function updateIncentivizer(IIncentivizer newIncentivizer) public onlyOwner(0) {\n _incentivizer.store(address(newIncentivizer));\n emit IncentivizerUpdated(newIncentivizer);\n }\n\n /**\n * @notice Updates the Product implementation beacon address\n * @param newProductBeacon New Product implementation beacon address\n */\n function updateProductBeacon(IBeacon newProductBeacon) public onlyOwner(0) {\n _productBeacon.store(address(newProductBeacon));\n emit ProductBeaconUpdated(newProductBeacon);\n }\n\n /**\n * @notice Updates the protocol-product fee split\n * @param newProtocolFee New protocol-product fee split\n */\n function updateProtocolFee(UFixed18 newProtocolFee) public onlyOwner(0) {\n if (newProtocolFee.gt(UFixed18Lib.ONE)) revert ControllerInvalidProtocolFeeError();\n\n _protocolFee.store(newProtocolFee);\n emit ProtocolFeeUpdated(newProtocolFee);\n }\n\n /**\n * @notice Updates the minimum allowed funding fee\n * @param newMinFundingFee New minimum allowed funding fee\n */\n function updateMinFundingFee(UFixed18 newMinFundingFee) public onlyOwner(0) {\n if (newMinFundingFee.gt(UFixed18Lib.ONE)) revert ControllerInvalidMinFundingFeeError();\n\n _minFundingFee.store(newMinFundingFee);\n emit MinFundingFeeUpdated(newMinFundingFee);\n }\n\n /**\n * @notice Updates the liquidation fee\n * @param newLiquidationFee New liquidation fee\n */\n function updateLiquidationFee(UFixed18 newLiquidationFee) public onlyOwner(0) {\n if (newLiquidationFee.gt(UFixed18Lib.ONE)) revert ControllerInvalidLiquidationFeeError();\n\n _liquidationFee.store(newLiquidationFee);\n emit LiquidationFeeUpdated(newLiquidationFee);\n }\n\n /**\n * @notice Updates the incentivization fee\n * @param newIncentivizationFee New incentivization fee\n */\n function updateIncentivizationFee(UFixed18 newIncentivizationFee) public onlyOwner(0) {\n if (newIncentivizationFee.gt(UFixed18Lib.ONE)) revert ControllerInvalidIncentivizationFeeError();\n\n _incentivizationFee.store(newIncentivizationFee);\n emit IncentivizationFeeUpdated(newIncentivizationFee);\n }\n\n /**\n * @notice Updates the minimum allowed collateral amount per user account\n * @param newMinCollateral New minimum allowed collateral amount\n */\n function updateMinCollateral(UFixed18 newMinCollateral) public onlyOwner(0) {\n _minCollateral.store(newMinCollateral);\n emit MinCollateralUpdated(newMinCollateral);\n }\n\n /**\n * @notice Updates the maximum incentivization programs per product allowed\n * @param newProgramsPerProduct New maximum incentivization programs per product allowed\n */\n function updateProgramsPerProduct(uint256 newProgramsPerProduct) public onlyOwner(0) {\n _programsPerProduct.store(newProgramsPerProduct);\n emit ProgramsPerProductUpdated(newProgramsPerProduct);\n }\n\n /**\n * @notice Returns whether a contract is a product\n * @param product Contract address to check\n * @return Whether a contract is a product\n */\n function isProduct(IProduct product) external view returns (bool) {\n return coordinatorFor[product] != 0;\n }\n\n /**\n * @notice Returns coordinator state for coordinator `coordinatorId`\n * @param coordinatorId Coordinator to return for\n * @return Coordinator state\n */\n function coordinators(uint256 coordinatorId) external view returns (Coordinator memory) {\n return _coordinators[coordinatorId];\n }\n\n /**\n * @notice Returns the pending owner of the protocol\n * @return Owner of the protocol\n */\n function pendingOwner() public view returns (address) {\n return pendingOwner(0);\n }\n\n /**\n * @notice Returns the pending owner of the coordinator `coordinatorId`\n * @param coordinatorId Coordinator to return for\n * @return Pending owner of the coordinator\n */\n function pendingOwner(uint256 coordinatorId) public view returns (address) {\n return _coordinators[coordinatorId].pendingOwner;\n }\n\n /**\n * @notice Returns the owner of the protocol\n * @return Owner of the protocol\n */\n function owner() public view returns (address) {\n return owner(0);\n }\n\n /**\n * @notice Returns the owner of the coordinator `coordinatorId`\n * @param coordinatorId Coordinator to return for\n * @return Owner of the coordinator\n */\n function owner(uint256 coordinatorId) public view returns (address) {\n return _coordinators[coordinatorId].owner;\n }\n\n /**\n * @notice Returns the owner of the product `product`\n * @param product Product to return for\n * @return Owner of the product\n */\n function owner(IProduct product) external view returns (address) {\n return owner(coordinatorFor[product]);\n }\n\n /**\n * @notice Returns the treasury of the protocol\n * @dev Defaults to the `owner` when `treasury` is unset\n * @return Treasury of the protocol\n */\n function treasury() external view returns (address) {\n return treasury(0);\n }\n\n /**\n * @notice Returns the treasury of the coordinator `coordinatorId`\n * @dev Defaults to the `owner` when `treasury` is unset\n * @param coordinatorId Coordinator to return for\n * @return Treasury of the coordinator\n */\n function treasury(uint256 coordinatorId) public view returns (address) {\n address _treasury = _coordinators[coordinatorId].treasury;\n return _treasury == address(0) ? owner(coordinatorId) : _treasury;\n }\n\n /**\n * @notice Returns the treasury of the product `product`\n * @dev Defaults to the `owner` when `treasury` is unset\n * @param product Product to return for\n * @return Treasury of the product\n */\n function treasury(IProduct product) external view returns (address) {\n return treasury(coordinatorFor[product]);\n }\n\n /**\n * @notice Returns the pauser of the protocol\n * @dev Defaults to the `owner` when `pauser` is unset\n * @return Pauser of the protocol\n */\n function pauser() external view returns (address) {\n return pauser(0);\n }\n\n /**\n * @notice Returns the pauser of the coordinator `coordinatorId`\n * @dev Defaults to the `owner` when `pauser` is unset\n * @param coordinatorId Coordinator to return for\n * @return Pauser of the coordinator\n */\n function pauser(uint256 coordinatorId) public view returns (address) {\n address _pauser = _coordinators[coordinatorId].pauser;\n return _pauser == address(0) ? owner(coordinatorId) : _pauser;\n }\n\n /**\n * @notice Returns the pauser of the product `product`\n * @dev Defaults to the `owner` when `pauser` is unset\n * @param product Product to return for\n * @return Pauser of the product\n */\n function pauser(IProduct product) external view returns (address) {\n return pauser(coordinatorFor[product]);\n }\n\n /**\n * @notice Returns the paused status of the protocol\n * @return Paused status of the protocol\n */\n function paused() public view returns (bool) {\n return _coordinators[0].paused;\n }\n\n /**\n * @notice Returns the paused status of the coordinator `coordinatorId`\n * @param coordinatorId Coordinator to return for\n * @return Paused status of the coordinator\n */\n function paused(uint256 coordinatorId) public view returns (bool) {\n return paused() || _coordinators[coordinatorId].paused;\n }\n\n /**\n * @notice Returns the paused status of the product `product`\n * @param product Product to return for\n * @return Paused status of the product\n */\n function paused(IProduct product) external view returns (bool) {\n return paused(coordinatorFor[product]);\n }\n\n // @dev Only allow owner of `coordinatorId` to call\n modifier onlyOwner(uint256 coordinatorId) {\n if (msg.sender != owner(coordinatorId)) revert ControllerNotOwnerError(coordinatorId);\n\n _;\n }\n\n // @dev Only pauser owner of `coordinatorId` to call\n modifier onlyPauser(uint256 coordinatorId) {\n if (msg.sender != pauser(coordinatorId)) revert ControllerNotPauserError(coordinatorId);\n\n _;\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n assert(_BEACON_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.beacon\")) - 1));\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overriden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, _allowances[owner][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = _allowances[owner][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Spend `amount` form the allowance of `owner` toward `spender`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "contracts/test/TestnetDSU.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\n\ncontract TestnetDSU is ERC20, ERC20Burnable {\n uint256 private constant LIMIT = 1_000_000e18;\n\n error TestnetDSUOverLimitError();\n\n // solhint-disable-next-line no-empty-blocks\n constructor() ERC20(\"Digital Standard Unit\", \"DSU\") { }\n\n function mint(address account, uint256 amount) external {\n if (amount > LIMIT) revert TestnetDSUOverLimitError();\n\n _mint(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n */\nabstract contract ERC20Pausable is ERC20, Pausable {\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../extensions/ERC20Burnable.sol\";\nimport \"../extensions/ERC20Pausable.sol\";\nimport \"../../../access/AccessControlEnumerable.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev {ERC20} token, including:\n *\n * - ability for holders to burn (destroy) their tokens\n * - a minter role that allows for token minting (creation)\n * - a pauser role that allows to stop all token transfers\n *\n * This contract uses {AccessControl} to lock permissioned functions using the\n * different roles - head to its documentation for details.\n *\n * The account that deploys the contract will be granted the minter and pauser\n * roles, as well as the default admin role, which will let it grant both minter\n * and pauser roles to other accounts.\n *\n * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._\n */\ncontract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /**\n * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the\n * account that deploys the contract.\n *\n * See {ERC20-constructor}.\n */\n constructor(string memory name, string memory symbol) ERC20(name, symbol) {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`.\n *\n * See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(address to, uint256 amount) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have minter role to mint\");\n _mint(to, amount);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to pause\");\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to unpause\");\n _unpause();\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20, ERC20Pausable) {\n super._beforeTokenTransfer(from, to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerable.sol\";\nimport \"./AccessControl.sol\";\nimport \"../utils/structs/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override {\n super._grantRole(role, account);\n _roleMembers[role].add(account);\n }\n\n /**\n * @dev Overload {_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override {\n super._revokeRole(role, account);\n _roleMembers[role].remove(account);\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/governance/TimelockController.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (governance/TimelockController.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../access/AccessControl.sol\";\n\n/**\n * @dev Contract module which acts as a timelocked controller. When set as the\n * owner of an `Ownable` smart contract, it enforces a timelock on all\n * `onlyOwner` maintenance operations. This gives time for users of the\n * controlled contract to exit before a potentially dangerous maintenance\n * operation is applied.\n *\n * By default, this contract is self administered, meaning administration tasks\n * have to go through the timelock process. The proposer (resp executor) role\n * is in charge of proposing (resp executing) operations. A common use case is\n * to position this {TimelockController} as the owner of a smart contract, with\n * a multisig or a DAO as the sole proposer.\n *\n * _Available since v3.3._\n */\ncontract TimelockController is AccessControl {\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\"TIMELOCK_ADMIN_ROLE\");\n bytes32 public constant PROPOSER_ROLE = keccak256(\"PROPOSER_ROLE\");\n bytes32 public constant EXECUTOR_ROLE = keccak256(\"EXECUTOR_ROLE\");\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\n\n mapping(bytes32 => uint256) private _timestamps;\n uint256 private _minDelay;\n\n /**\n * @dev Emitted when a call is scheduled as part of operation `id`.\n */\n event CallScheduled(\n bytes32 indexed id,\n uint256 indexed index,\n address target,\n uint256 value,\n bytes data,\n bytes32 predecessor,\n uint256 delay\n );\n\n /**\n * @dev Emitted when a call is performed as part of operation `id`.\n */\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\n\n /**\n * @dev Emitted when operation `id` is cancelled.\n */\n event Cancelled(bytes32 indexed id);\n\n /**\n * @dev Emitted when the minimum delay for future operations is modified.\n */\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\n\n /**\n * @dev Initializes the contract with a given `minDelay`.\n */\n constructor(\n uint256 minDelay,\n address[] memory proposers,\n address[] memory executors\n ) {\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\n\n // deployer + self administration\n _setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\n\n // register proposers\n for (uint256 i = 0; i < proposers.length; ++i) {\n _setupRole(PROPOSER_ROLE, proposers[i]);\n }\n\n // register executors\n for (uint256 i = 0; i < executors.length; ++i) {\n _setupRole(EXECUTOR_ROLE, executors[i]);\n }\n\n _minDelay = minDelay;\n emit MinDelayChange(0, minDelay);\n }\n\n /**\n * @dev Modifier to make a function callable only by a certain role. In\n * addition to checking the sender's role, `address(0)` 's role is also\n * considered. Granting a role to `address(0)` is equivalent to enabling\n * this role for everyone.\n */\n modifier onlyRoleOrOpenRole(bytes32 role) {\n if (!hasRole(role, address(0))) {\n _checkRole(role, _msgSender());\n }\n _;\n }\n\n /**\n * @dev Contract might receive/hold ETH as part of the maintenance process.\n */\n receive() external payable {}\n\n /**\n * @dev Returns whether an id correspond to a registered operation. This\n * includes both Pending, Ready and Done operations.\n */\n function isOperation(bytes32 id) public view virtual returns (bool pending) {\n return getTimestamp(id) > 0;\n }\n\n /**\n * @dev Returns whether an operation is pending or not.\n */\n function isOperationPending(bytes32 id) public view virtual returns (bool pending) {\n return getTimestamp(id) > _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Returns whether an operation is ready or not.\n */\n function isOperationReady(bytes32 id) public view virtual returns (bool ready) {\n uint256 timestamp = getTimestamp(id);\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\n }\n\n /**\n * @dev Returns whether an operation is done or not.\n */\n function isOperationDone(bytes32 id) public view virtual returns (bool done) {\n return getTimestamp(id) == _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Returns the timestamp at with an operation becomes ready (0 for\n * unset operations, 1 for done operations).\n */\n function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp) {\n return _timestamps[id];\n }\n\n /**\n * @dev Returns the minimum delay for an operation to become valid.\n *\n * This value can be changed by executing an operation that calls `updateDelay`.\n */\n function getMinDelay() public view virtual returns (uint256 duration) {\n return _minDelay;\n }\n\n /**\n * @dev Returns the identifier of an operation containing a single\n * transaction.\n */\n function hashOperation(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt\n ) public pure virtual returns (bytes32 hash) {\n return keccak256(abi.encode(target, value, data, predecessor, salt));\n }\n\n /**\n * @dev Returns the identifier of an operation containing a batch of\n * transactions.\n */\n function hashOperationBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt\n ) public pure virtual returns (bytes32 hash) {\n return keccak256(abi.encode(targets, values, datas, predecessor, salt));\n }\n\n /**\n * @dev Schedule an operation containing a single transaction.\n *\n * Emits a {CallScheduled} event.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function schedule(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual onlyRole(PROPOSER_ROLE) {\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\n _schedule(id, delay);\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\n }\n\n /**\n * @dev Schedule an operation containing a batch of transactions.\n *\n * Emits one {CallScheduled} event per transaction in the batch.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function scheduleBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual onlyRole(PROPOSER_ROLE) {\n require(targets.length == values.length, \"TimelockController: length mismatch\");\n require(targets.length == datas.length, \"TimelockController: length mismatch\");\n\n bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);\n _schedule(id, delay);\n for (uint256 i = 0; i < targets.length; ++i) {\n emit CallScheduled(id, i, targets[i], values[i], datas[i], predecessor, delay);\n }\n }\n\n /**\n * @dev Schedule an operation that is to becomes valid after a given delay.\n */\n function _schedule(bytes32 id, uint256 delay) private {\n require(!isOperation(id), \"TimelockController: operation already scheduled\");\n require(delay >= getMinDelay(), \"TimelockController: insufficient delay\");\n _timestamps[id] = block.timestamp + delay;\n }\n\n /**\n * @dev Cancel an operation.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function cancel(bytes32 id) public virtual onlyRole(PROPOSER_ROLE) {\n require(isOperationPending(id), \"TimelockController: operation cannot be cancelled\");\n delete _timestamps[id];\n\n emit Cancelled(id);\n }\n\n /**\n * @dev Execute an (ready) operation containing a single transaction.\n *\n * Emits a {CallExecuted} event.\n *\n * Requirements:\n *\n * - the caller must have the 'executor' role.\n */\n function execute(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\n _beforeCall(id, predecessor);\n _call(id, 0, target, value, data);\n _afterCall(id);\n }\n\n /**\n * @dev Execute an (ready) operation containing a batch of transactions.\n *\n * Emits one {CallExecuted} event per transaction in the batch.\n *\n * Requirements:\n *\n * - the caller must have the 'executor' role.\n */\n function executeBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\n require(targets.length == values.length, \"TimelockController: length mismatch\");\n require(targets.length == datas.length, \"TimelockController: length mismatch\");\n\n bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);\n _beforeCall(id, predecessor);\n for (uint256 i = 0; i < targets.length; ++i) {\n _call(id, i, targets[i], values[i], datas[i]);\n }\n _afterCall(id);\n }\n\n /**\n * @dev Checks before execution of an operation's calls.\n */\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\n require(isOperationReady(id), \"TimelockController: operation is not ready\");\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \"TimelockController: missing dependency\");\n }\n\n /**\n * @dev Checks after execution of an operation's calls.\n */\n function _afterCall(bytes32 id) private {\n require(isOperationReady(id), \"TimelockController: operation is not ready\");\n _timestamps[id] = _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Execute an operation's call.\n *\n * Emits a {CallExecuted} event.\n */\n function _call(\n bytes32 id,\n uint256 index,\n address target,\n uint256 value,\n bytes calldata data\n ) private {\n (bool success, ) = target.call{value: value}(data);\n require(success, \"TimelockController: underlying transaction reverted\");\n\n emit CallExecuted(id, index, target, value, data);\n }\n\n /**\n * @dev Changes the minimum timelock duration for future operations.\n *\n * Emits a {MinDelayChange} event.\n *\n * Requirements:\n *\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\n */\n function updateDelay(uint256 newDelay) external virtual {\n require(msg.sender == address(this), \"TimelockController: caller must be timelock\");\n emit MinDelayChange(_minDelay, newDelay);\n _minDelay = newDelay;\n }\n}\n" + }, + "contracts/hardhat-dependency-compiler/@openzeppelin/contracts/governance/TimelockController.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport '@openzeppelin/contracts/governance/TimelockController.sol';\n" + }, + "contracts/hardhat-dependency-compiler/@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport '@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol';\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol';\n" + }, + "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../../access/Ownable.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\n * implementation contract, which is where they will delegate all function calls.\n *\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\n */\ncontract UpgradeableBeacon is IBeacon, Ownable {\n address private _implementation;\n\n /**\n * @dev Emitted when the implementation returned by the beacon is changed.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\n * beacon.\n */\n constructor(address implementation_) {\n _setImplementation(implementation_);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function implementation() public view virtual override returns (address) {\n return _implementation;\n }\n\n /**\n * @dev Upgrades the beacon to a new implementation.\n *\n * Emits an {Upgraded} event.\n *\n * Requirements:\n *\n * - msg.sender must be the owner of the contract.\n * - `newImplementation` must be a contract.\n */\n function upgradeTo(address newImplementation) public virtual onlyOwner {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation contract address for this beacon\n *\n * Requirements:\n *\n * - `newImplementation` must be a contract.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\n _implementation = newImplementation;\n }\n}\n" + }, + "contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport '@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol';\n" + }, + "contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol';\n" + }, + "contracts/forwarder/Forwarder.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\nimport \"../interfaces/IForwarder.sol\";\n\n/**\n * @title Forwarder\n * @notice Facilitates collateral deposits to the protocol where the amount is supplied\n * in USDC then wrapped as DSU before being deposited.\n */\ncontract Forwarder is IForwarder {\n // @dev USDC stablecoin\n Token6 public immutable USDC; // solhint-disable-line var-name-mixedcase\n\n // @dev DSU stablecoin\n Token18 public immutable DSU; // solhint-disable-line var-name-mixedcase\n\n /// @dev Contract that wraps USDC to DSU\n IBatcher public immutable batcher;\n\n /// @dev Contract managing state for collateral accounts in the protocol\n ICollateral public immutable collateral;\n\n /**\n * @notice Initializes the contract state\n * @param usdc_ The USDC token contract address\n * @param dsu_ The DSU token contract address\n * @param batcher_ The USDC-to-DSU batcher contract address\n * @param collateral_ The perennial collateral contract address\n */\n constructor(\n Token6 usdc_,\n Token18 dsu_,\n IBatcher batcher_,\n ICollateral collateral_\n ) {\n USDC = usdc_;\n DSU = dsu_;\n batcher = batcher_;\n collateral = collateral_;\n\n USDC.approve(address(batcher));\n DSU.approve(address(collateral));\n }\n\n /**\n * @notice Pulls `amount` of USDC from `msg.sender`'s balance, wraps it as DSU,\n and deposits it as collateral to `account`'s `product` account\n * @param account Account to deposit the collateral for\n * @param product Product to credit the collateral to\n * @param amount 18 decimals-normalized stablecoin (USDC, DSU) value of collateral to deposit\n */\n function wrapAndDeposit(\n address account,\n IProduct product,\n UFixed18 amount\n ) external {\n USDC.pull(msg.sender, amount, true);\n batcher.wrap(amount, address(this));\n collateral.depositTo(account, product, amount);\n emit WrapAndDeposit(account, product, amount);\n }\n}\n" + }, + "contracts/test/TestnetChainlinkFeedRegistry.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.14;\n\ncontract TestnetChainlinkFeedRegistry {\n mapping(address => mapping(address => uint8)) public decimals;\n\n function registerFeed(address base, address quote, uint8 newDecimals) external {\n decimals[base][quote] = newDecimals;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 1000 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/packages/perennial/test/unit/forwarder/Forwarder.test.ts b/packages/perennial/test/unit/forwarder/Forwarder.test.ts index 8cc48513..e406b518 100644 --- a/packages/perennial/test/unit/forwarder/Forwarder.test.ts +++ b/packages/perennial/test/unit/forwarder/Forwarder.test.ts @@ -81,5 +81,30 @@ describe('Forwarder', () => { expect(batcher.wrap).to.have.been.calledOnceWith(utils.parseEther('10'), forwarder.address) expect(collateral.depositTo).to.have.been.calledOnceWith(account.address, product.address, utils.parseEther('10')) }) + + it('rounds correctly', async () => { + usdc.transferFrom.whenCalledWith(user.address, forwarder.address, 1e6).returns(true) + batcher.wrap.whenCalledWith(utils.parseEther('0.999999999999'), forwarder.address).returns() + collateral.depositTo.whenCalledWith(account.address, product, utils.parseEther('10')).returns() + + await expect( + forwarder.connect(user).wrapAndDeposit( + account.address, + product.address, + utils.parseEther('0.999999999999'), + { gasLimit: 30e6 }, // https://github.com/defi-wonderland/smock/issues/99 + ), + ) + .to.emit(forwarder, 'WrapAndDeposit') + .withArgs(account.address, product.address, utils.parseEther('0.999999999999')) + + expect(usdc.transferFrom).to.have.been.calledOnceWith(user.address, forwarder.address, 1e6) + expect(batcher.wrap).to.have.been.calledOnceWith(utils.parseEther('0.999999999999'), forwarder.address) + expect(collateral.depositTo).to.have.been.calledOnceWith( + account.address, + product.address, + utils.parseEther('0.999999999999'), + ) + }) }) })