{"stdJsonOutput":{"sources":{"src/usd3/USD3.sol":{"id":32},"src/interfaces/IIrm.sol":{"id":20},"src/libraries/MathLib.sol":{"id":25},"src/interfaces/IMorpho.sol":{"id":21},"src/libraries/UtilsLib.sol":{"id":28},"src/libraries/ErrorsLib.sol":{"id":23},"src/libraries/SharesMathLib.sol":{"id":27},"src/libraries/MarketParamsLib.sol":{"id":24},"src/interfaces/IProtocolConfig.sol":{"id":22},"src/libraries/ProtocolConfigLib.sol":{"id":26},"src/libraries/periphery/MorphoLib.sol":{"id":30},"src/usd3/base/BaseHooksUpgradeable.sol":{"id":33},"src/usd3/base/BaseStrategyUpgradeable.sol":{"id":34},"lib/openzeppelin/contracts/utils/Panic.sol":{"id":5},"lib/openzeppelin/contracts/utils/Context.sol":{"id":4},"src/libraries/periphery/MorphoStorageLib.sol":{"id":31},"lib/openzeppelin/contracts/utils/Pausable.sol":{"id":6},"src/libraries/periphery/MorphoBalancesLib.sol":{"id":29},"lib/openzeppelin/contracts/utils/math/Math.sol":{"id":7},"lib/openzeppelin/contracts/token/ERC20/IERC20.sol":{"id":2},"lib/openzeppelin/contracts/interfaces/IERC4626.sol":{"id":0},"lib/openzeppelin/contracts/utils/math/SafeCast.sol":{"id":8},"lib/openzeppelin/contracts/proxy/utils/Initializable.sol":{"id":1},"lib/tokenized-strategy-periphery/src/Bases/Hooks/Hooks.sol":{"id":17},"lib/tokenized-strategy/src/interfaces/ITokenizedStrategy.sol":{"id":19},"lib/openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"id":3},"lib/tokenized-strategy-periphery/src/libraries/TokenizedStrategyStorageLib.sol":{"id":18},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/utils/Address.sol":{"id":15},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/utils/Context.sol":{"id":16},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol":{"id":10},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol":{"id":11},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol":{"id":9},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol":{"id":14},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol":{"id":13},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"id":12}},"contracts":{"src/usd3/USD3.sol":{"USD3":{"abi":[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"},{"name":"InvalidInitialization","type":"error","inputs":[]},{"name":"MaxUint128Exceeded","type":"error","inputs":[]},{"name":"NotInitializing","type":"error","inputs":[]},{"name":"Initialized","type":"event","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"name":"MinDepositUpdated","type":"event","inputs":[{"name":"newMinDeposit","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"RebalanceDeferred","type":"event","inputs":[{"name":"waUSDCAmount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"RingFenceConduitUpdated","type":"event","inputs":[{"name":"conduit","type":"address","indexed":true,"internalType":"address"},{"name":"enabled","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"name":"RingFenceReleased","type":"event","inputs":[{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newTotal","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"RingFencedLiquidityIncreased","type":"event","inputs":[{"name":"conduit","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newTotal","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"SUSD3StrategyUpdated","type":"event","inputs":[{"name":"oldStrategy","type":"address","indexed":false,"internalType":"address"},{"name":"newStrategy","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"name":"SupplyCapExemptUpdated","type":"event","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"exempt","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"name":"TrancheShareSynced","type":"event","inputs":[{"name":"trancheShare","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"Transfer","type":"event","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"fallback","stateMutability":"nonpayable"},{"name":"WAUSDC","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IWaUSDC"}],"stateMutability":"view"},{"name":"availableDepositLimit","type":"function","inputs":[{"name":"_owner","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"availableWithdrawLimit","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"balanceOfWaUSDC","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"deployFunds","type":"function","inputs":[{"name":"_amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"deposit","type":"function","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"freeFunds","type":"function","inputs":[{"name":"_amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"getMarketLiquidity","type":"function","inputs":[],"outputs":[{"name":"totalSupplyAssets","type":"uint256","internalType":"uint256"},{"name":"totalShares","type":"uint256","internalType":"uint256"},{"name":"totalBorrowAssets","type":"uint256","internalType":"uint256"},{"name":"waUSDCLiquidity","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"harvestAndReport","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"marketId","type":"function","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"Id"}],"stateMutability":"view"},{"name":"marketParams","type":"function","inputs":[],"outputs":[{"name":"","type":"tuple","components":[{"name":"loanToken","type":"address","internalType":"address"},{"name":"collateralToken","type":"address","internalType":"address"},{"name":"oracle","type":"address","internalType":"address"},{"name":"irm","type":"address","internalType":"address"},{"name":"lltv","type":"uint256","internalType":"uint256"},{"name":"creditLine","type":"address","internalType":"address"}],"internalType":"struct MarketParams"}],"stateMutability":"view"},{"name":"maxOnCredit","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"minDeposit","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"mint","type":"function","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"morphoCredit","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IMorpho"}],"stateMutability":"view"},{"name":"nav","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"redeem","type":"function","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"},{"name":"maxLoss","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"redeem","type":"function","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"releaseRingFence","type":"function","inputs":[{"name":"_assets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"report","type":"function","inputs":[],"outputs":[{"name":"profit","type":"uint256","internalType":"uint256"},{"name":"loss","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"ringFenceConduit","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"ringFencedLiquidity","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"sUSD3","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"setMinDeposit","type":"function","inputs":[{"name":"_minDeposit","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setProfitMaxUnlockTime","type":"function","inputs":[{"name":"_profitMaxUnlockTime","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setRingFenceConduit","type":"function","inputs":[{"name":"_conduit","type":"address","internalType":"address"},{"name":"_enabled","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setSUSD3","type":"function","inputs":[{"name":"_sUSD3","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setSupplyCapExempt","type":"function","inputs":[{"name":"_account","type":"address","internalType":"address"},{"name":"_exempt","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"shutdownWithdraw","type":"function","inputs":[{"name":"_amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"suppliedWaUSDC","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"supplyCapExempt","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"symbol","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"name":"syncTrancheShare","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"tendThis","type":"function","inputs":[{"name":"_totalIdle","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"tendTrigger","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"},{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"name":"tokenizedStrategyAddress","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"transfer","type":"function","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"name":"transferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"name":"withdraw","type":"function","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"},{"name":"maxLoss","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"withdraw","type":"function","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"}],"metadata":"{\"compiler\":{\"version\":\"0.8.22+commit.4fc1097e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxUint128Exceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinDeposit\",\"type\":\"uint256\"}],\"name\":\"MinDepositUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"waUSDCAmount\",\"type\":\"uint256\"}],\"name\":\"RebalanceDeferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"conduit\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"name\":\"RingFenceConduitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"assets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTotal\",\"type\":\"uint256\"}],\"name\":\"RingFenceReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"conduit\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"assets\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTotal\",\"type\":\"uint256\"}],\"name\":\"RingFencedLiquidityIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldStrategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newStrategy\",\"type\":\"address\"}],\"name\":\"SUSD3StrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"exempt\",\"type\":\"bool\"}],\"name\":\"SupplyCapExemptUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"trancheShare\",\"type\":\"uint256\"}],\"name\":\"TrancheShareSynced\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"WAUSDC\",\"outputs\":[{\"internalType\":\"contract IWaUSDC\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"availableDepositLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"availableWithdrawLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"balanceOfWaUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deployFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assets\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"deposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"freeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMarketLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"totalSupplyAssets\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalShares\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrowAssets\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"waUSDCLiquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"harvestAndReport\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"marketId\",\"outputs\":[{\"internalType\":\"Id\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"marketParams\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"loanToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"irm\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lltv\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"creditLine\",\"type\":\"address\"}],\"internalType\":\"struct MarketParams\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxOnCredit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minDeposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"assets\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"morphoCredit\",\"outputs\":[{\"internalType\":\"contract IMorpho\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nav\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxLoss\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"assets\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"redeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"assets\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_assets\",\"type\":\"uint256\"}],\"name\":\"releaseRingFence\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"report\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"profit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"loss\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"ringFenceConduit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ringFencedLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sUSD3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minDeposit\",\"type\":\"uint256\"}],\"name\":\"setMinDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_profitMaxUnlockTime\",\"type\":\"uint256\"}],\"name\":\"setProfitMaxUnlockTime\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_conduit\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_enabled\",\"type\":\"bool\"}],\"name\":\"setRingFenceConduit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sUSD3\",\"type\":\"address\"}],\"name\":\"setSUSD3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_exempt\",\"type\":\"bool\"}],\"name\":\"setSupplyCapExempt\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"shutdownWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"suppliedWaUSDC\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCapExempt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"syncTrancheShare\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_totalIdle\",\"type\":\"uint256\"}],\"name\":\"tendThis\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tendTrigger\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenizedStrategyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assets\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxLoss\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assets\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"3Jane Protocol\",\"details\":\"Implements Yearn V3 tokenized strategy pattern for unsecured lending via MorphoCredit. Deploys USDC capital to 3Jane's modified Morpho Blue markets that use credit-based underwriting instead of collateral. Its loss waterfall uses strategy-owned locked-profit shares before sUSD3 subordinate capital, then exposes USD3 holders to any residual loss. Key features: - Senior tranche whose current principal and PPS are buffered first by locked profit, then by sUSD3 holdings - Configurable deployment ratio to credit markets (maxOnCredit) - Automatic yield distribution to sUSD3 via performance fees - Loss absorption through direct share burning of sUSD3 holdings - Supply-cap exemptions for protocol-controlled deposit receivers - Dynamic fee adjustment via ProtocolConfig integration Yield Distribution Mechanism: - Tranche share distributed to sUSD3 holders via TokenizedStrategy's performance fee - Performance fee can be set from 0-100% through syncTrancheShare() - Direct storage manipulation bypasses TokenizedStrategy's 50% fee limit - Keeper-controlled updates ensure protocol-wide consistency Loss Absorption Mechanism: - TokenizedStrategy first burns strategy-owned locked-profit shares remaining from prior profitable reports - USD3 burns sUSD3-held USD3 shares only for the loss remaining after that locked-profit burn - Current USD3 principal and PPS remain protected while locked profit covers the loss, but cash-collected profit   that would otherwise unlock to USD3 holders is consumed before junior principal - Direct storage manipulation burns the required sUSD3-held shares without asset transfers, capped by its balance - Losses exceeding both outstanding locked profit and sUSD3's USD3 balance reduce USD3 holders proportionally - Both loss-to-share conversions round down; at high PPS, a loss worth less than one base share can burn nothing   from either buffer and still reduce senior PPS\",\"errors\":{\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}]},\"events\":{\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"availableDepositLimit(address)\":{\"details\":\"Returns available deposit limit, enforcing borrower restrictions and supply cap\",\"params\":{\"_owner\":\"Address to check limit for\"},\"returns\":{\"_0\":\"Maximum amount that can be deposited\"}},\"availableWithdrawLimit(address)\":{\"details\":\"The bps floor is a scaling/rate knob applied to then-current total assets, so repeated redemptions drain geometrically toward the nominal floor. The nominal floor is the hard ring-fence and should be set alongside the bps floor whenever a fixed asset amount must remain reserved.\",\"returns\":{\"_0\":\"Maximum amount that can be withdrawn\"}},\"balanceOfWaUSDC()\":{\"returns\":{\"_0\":\"Amount of waUSDC held in this contract\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"deployFunds(uint256)\":{\"details\":\"Callback for the TokenizedStrategy to call during a {deposit} or {mint} to tell the strategy it can deploy funds. Since this can only be called after a {deposit} or {mint} delegateCall to the TokenizedStrategy msg.sender == address(this). Unless a whitelist is implemented this will be entirely permissionless and thus can be sandwiched or otherwise manipulated.\",\"params\":{\"_amount\":\"The amount of 'asset' that the strategy can attempt to deposit in the yield source.\"}},\"deposit(uint256,address)\":{\"params\":{\"assets\":\"Amount of assets to deposit\",\"receiver\":\"Address to receive the shares\"},\"returns\":{\"shares\":\"Amount of shares minted\"}},\"freeFunds(uint256)\":{\"details\":\"Callback for the TokenizedStrategy to call during a withdraw or redeem to free the needed funds to service the withdraw. This can only be called after a 'withdraw' or 'redeem' delegateCall to the TokenizedStrategy so msg.sender == address(this).\",\"params\":{\"_amount\":\"The amount of 'asset' that the strategy should attempt to free up.\"}},\"getMarketLiquidity()\":{\"details\":\"Get current market liquidity information\",\"returns\":{\"totalBorrowAssets\":\"Total assets borrowed from the market\",\"totalShares\":\"Total supply shares in the market\",\"totalSupplyAssets\":\"Total assets supplied to the market\",\"waUSDCLiquidity\":\"Available liquidity in the market\"}},\"harvestAndReport()\":{\"details\":\"Callback for the TokenizedStrategy to call during a report to get an accurate accounting of assets the strategy controls. This can only be called after a report() delegateCall to the TokenizedStrategy so msg.sender == address(this).\",\"returns\":{\"_0\":\". A trusted and accurate account for the total amount of 'asset' the strategy currently holds including idle funds.\"}},\"marketParams()\":{\"returns\":{\"_0\":\"MarketParams struct containing lending market configuration\"}},\"maxOnCredit()\":{\"details\":\"Returns the value from ProtocolConfig directly. If not configured in ProtocolConfig,      it returns 0, effectively preventing deployment until explicitly configured.Below 100%, this is an honest-operation deployment and liquidity-buffer target, not an adversarially      enforceable exposure boundary. DEBT_CAP is the enforceable boundary: MorphoCredit borrow admission reads      debt but never supply, so a temporary deposit cannot increase the borrowable total by even one unit.\",\"returns\":{\"_0\":\"Maximum deployment ratio in basis points (10000 = 100%)\"}},\"mint(uint256,address)\":{\"params\":{\"receiver\":\"Address to receive the shares\",\"shares\":\"Amount of shares to mint\"},\"returns\":{\"assets\":\"Amount of assets deposited\"}},\"nav()\":{\"details\":\"Net asset value of the strategy in USDC terms\",\"returns\":{\"_0\":\"Sum of deployed and local waUSDC converted to assets, plus idle USDC held by the strategy\"}},\"redeem(uint256,address,address)\":{\"params\":{\"owner\":\"Address whose shares are burned\",\"receiver\":\"Address to receive the assets\",\"shares\":\"Amount of shares to redeem\"},\"returns\":{\"assets\":\"Amount of assets withdrawn\"}},\"redeem(uint256,address,address,uint256)\":{\"params\":{\"maxLoss\":\"Maximum acceptable loss in basis points\",\"owner\":\"Address whose shares are burned\",\"receiver\":\"Address to receive the assets\",\"shares\":\"Amount of shares to redeem\"},\"returns\":{\"assets\":\"Amount of assets withdrawn\"}},\"releaseRingFence(uint256)\":{\"params\":{\"_assets\":\"Amount of fenced liquidity to release, in USDC asset units.\"}},\"report()\":{\"returns\":{\"loss\":\"Amount of loss incurred\",\"profit\":\"Amount of profit generated\"}},\"setMinDeposit(uint256)\":{\"params\":{\"_minDeposit\":\"Minimum amount required for deposits\"}},\"setProfitMaxUnlockTime(uint256)\":{\"details\":\"Nonzero updates retain the TokenizedStrategy implementation's behavior.\"},\"setRingFenceConduit(address,bool)\":{\"details\":\"Pair this flag operationally with `supplyCapExempt`. When both flags are set, every accepted deposit is a self-deposit and receives ring-fence credit. Revoking the exemption while leaving this conduit flag set permits third-party deposits that receive no ring-fence credit. LCC deployment grants both flags atomically; revoke them atomically as well.\",\"params\":{\"_conduit\":\"Receiver address to update.\",\"_enabled\":\"True to accumulate self-deposits into the ring fence, false to disable accumulation.\"}},\"setSUSD3(address)\":{\"details\":\"Only callable by management. After calling, also set performance fee recipient.\",\"params\":{\"_sUSD3\":\"Address of the sUSD3 strategy\"}},\"setSupplyCapExempt(address,bool)\":{\"details\":\"An exempt receiver may only be deposited to by itself. A third party depositing directly to that exempt receiver reverts. Helper is the USD3 receiver only on its hop path, and its user-level limit check still applies the supply cap and borrower restriction before the deposit. Exempting Helper therefore bypasses only the receiver-level first-time minimum for that path; it does not affect the non-hop path, whose receiver is the user.Pair this flag operationally with `ringFenceConduit`. When both flags are set, every accepted deposit is a self-deposit and receives ring-fence credit. Revoking this exemption while leaving the conduit flag set permits third-party deposits that receive no ring-fence credit. LCC deployment grants both flags atomically; revoke them atomically as well.\",\"params\":{\"_account\":\"Receiver address to update.\",\"_exempt\":\"True to require self-deposits that bypass supply-cap headroom and first-time minimum-deposit checks; false to allow third-party deposits and apply the ordinary checks.\"}},\"shutdownWithdraw(uint256)\":{\"details\":\"Callback for the TokenizedStrategy during an emergency withdraw. This can only be called after a emergencyWithdraw() delegateCall to the TokenizedStrategy so msg.sender == address(this). We name the function `shutdownWithdraw` so that `emergencyWithdraw` calls are forwarded to the TokenizedStrategy.\",\"params\":{\"_amount\":\"The amount of asset to attempt to free.\"}},\"suppliedWaUSDC()\":{\"returns\":{\"_0\":\"Amount of waUSDC deployed to the lending market\"}},\"symbol()\":{\"returns\":{\"_0\":\"Symbol string \\\"USD3\\\"\"}},\"syncTrancheShare()\":{\"details\":\"Reads TRANCHE_SHARE_VARIANT from ProtocolConfig and updates local storage IMPORTANT: Direct storage manipulation is necessary here because TokenizedStrategy's setPerformanceFee() function has a hardcoded MAX_FEE limit of 5000 (50%). Since we need to support higher fee distributions to sUSD3 (potentially up to 100% for full subordination scenarios), we must bypass this restriction by directly modifying the storage slot. Storage layout in TokenizedStrategy (slot 9): - Bits 0-31: profitMaxUnlockTime (uint32) - Bits 32-47: performanceFee (uint16) <- We modify this - Bits 48-207: performanceFeeRecipient (address)Only callable by keepers to ensure controlled updates\"},\"tendThis(uint256)\":{\"details\":\"Callback for the TokenizedStrategy to initiate a _tend call in the strategy. This can only be called after a tend() delegateCall to the TokenizedStrategy so msg.sender == address(this). We name the function `tendThis` so that `tend` calls are forwarded to the TokenizedStrategy.\",\"params\":{\"_totalIdle\":\"The amount of current idle funds that can be deployed during the tend\"}},\"tendTrigger()\":{\"returns\":{\"_0\":\". Should return true if tend() should be called by keeper or false if not.\",\"_1\":\". Calldata for the tend call.\"}},\"transfer(address,uint256)\":{\"params\":{\"amount\":\"Amount of shares to transfer\",\"to\":\"Address to receive the shares\"},\"returns\":{\"_0\":\"success Whether the transfer succeeded\"}},\"transferFrom(address,address,uint256)\":{\"params\":{\"amount\":\"Amount of shares to transfer\",\"from\":\"Address to transfer from\",\"to\":\"Address to transfer to\"},\"returns\":{\"_0\":\"success Whether the transfer succeeded\"}},\"withdraw(uint256,address,address)\":{\"params\":{\"assets\":\"Amount of assets to withdraw\",\"owner\":\"Address whose shares are burned\",\"receiver\":\"Address to receive the assets\"},\"returns\":{\"shares\":\"Amount of shares burned\"}},\"withdraw(uint256,address,address,uint256)\":{\"params\":{\"assets\":\"Amount of assets to withdraw\",\"maxLoss\":\"Maximum acceptable loss in basis points\",\"owner\":\"Address whose shares are burned\",\"receiver\":\"Address to receive the assets\"},\"returns\":{\"shares\":\"Amount of shares burned\"}}},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"},\"sUSD3\":{\"details\":\"Used for loss absorption and yield distribution\"}},\"title\":\"USD3\",\"version\":1},\"userdoc\":{\"errors\":{\"MaxUint128Exceeded()\":[{\"notice\":\"Thrown when the maximum uint128 is exceeded.\"}]},\"kind\":\"user\",\"methods\":{\"availableWithdrawLimit(address)\":{\"notice\":\"Returns the withdrawable assets for an owner after liquidity and floor checks.\"},\"balanceOfWaUSDC()\":{\"notice\":\"Get the balance of waUSDC held locally (not deployed to MorphoCredit)\"},\"deployFunds(uint256)\":{\"notice\":\"Can deploy up to '_amount' of 'asset' in yield source.\"},\"deposit(uint256,address)\":{\"notice\":\"Deposit assets and receive shares\"},\"freeFunds(uint256)\":{\"notice\":\"Should attempt to free the '_amount' of 'asset'.\"},\"harvestAndReport()\":{\"notice\":\"Returns the accurate amount of all funds currently held by the Strategy.\"},\"marketId()\":{\"notice\":\"Market ID for the lending market this strategy uses\"},\"marketParams()\":{\"notice\":\"Get the market parameters for this strategy\"},\"maxOnCredit()\":{\"notice\":\"Get the maximum percentage of funds to deploy to credit markets from ProtocolConfig\"},\"minDeposit()\":{\"notice\":\"Minimum deposit amount required\"},\"mint(uint256,address)\":{\"notice\":\"Mint shares by depositing assets\"},\"morphoCredit()\":{\"notice\":\"MorphoCredit contract for lending operations\"},\"redeem(uint256,address,address)\":{\"notice\":\"Redeem shares for assets\"},\"redeem(uint256,address,address,uint256)\":{\"notice\":\"Redeem shares with custom max loss\"},\"releaseRingFence(uint256)\":{\"notice\":\"Release ring-fenced liquidity back into the withdrawable liquidity calculation.\"},\"report()\":{\"notice\":\"Report profit and loss with pre-report context for accurate loss absorption\"},\"ringFenceConduit(address)\":{\"notice\":\"Conduits whose self-deposits add to the ring-fenced liquidity accumulator.\"},\"ringFencedLiquidity()\":{\"notice\":\"Fenced capital-call cash in USDC asset units.\"},\"sUSD3()\":{\"notice\":\"Address of the subordinate sUSD3 strategy\"},\"setMinDeposit(uint256)\":{\"notice\":\"Set minimum deposit amount\"},\"setProfitMaxUnlockTime(uint256)\":{\"notice\":\"Set the profit unlock time without releasing locked profit ahead of an unreported loss.\"},\"setRingFenceConduit(address,bool)\":{\"notice\":\"Update whether a conduit self-deposit adds to ring-fenced liquidity.\"},\"setSUSD3(address)\":{\"notice\":\"Set the sUSD3 subordinate strategy address\"},\"setSupplyCapExempt(address,bool)\":{\"notice\":\"Update supply-cap and first-time minimum-deposit exemption status for a receiver.\"},\"shutdownWithdraw(uint256)\":{\"notice\":\"Will call the internal '_emergencyWithdraw' function.\"},\"suppliedWaUSDC()\":{\"notice\":\"Get the amount of waUSDC supplied to MorphoCredit\"},\"supplyCapExempt(address)\":{\"notice\":\"Receivers whose self-deposits bypass USD3 supply-cap headroom and first-time minimum-deposit checks.\"},\"symbol()\":{\"notice\":\"Get the symbol for the USD3 token\"},\"syncTrancheShare()\":{\"notice\":\"Sync the tranche share (performance fee) from ProtocolConfig\"},\"tendThis(uint256)\":{\"notice\":\"Will call the internal '_tend' when a keeper tends the strategy.\"},\"tendTrigger()\":{\"notice\":\"Returns if tend() should be called by a keeper.\"},\"transfer(address,uint256)\":{\"notice\":\"Transfer shares to another address\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"Transfer shares from one address to another\"},\"withdraw(uint256,address,address)\":{\"notice\":\"Withdraw assets by burning shares\"},\"withdraw(uint256,address,address,uint256)\":{\"notice\":\"Withdraw assets with custom max loss\"}},\"notice\":\"Senior tranche strategy for USDC-based lending on 3Jane's credit markets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/usd3/USD3.sol\":\"USD3\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/\",\":@periphery/=lib/tokenized-strategy-periphery/src/\",\":@tokenized-strategy/=lib/tokenized-strategy/src/\",\":@yearn-vaults/=lib/tokenized-strategy-periphery/lib/yearn-vaults-v3/contracts/\",\":ds-test/=lib/tokenized-strategy-periphery/lib/forge-std/lib/ds-test/src/\",\":erc4626-tests/=lib/tokenized-strategy/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts/=lib/tokenized-strategy/lib/openzeppelin-contracts/\",\":openzeppelin/=lib/openzeppelin/\",\":tokenized-strategy-periphery/=lib/tokenized-strategy-periphery/\",\":tokenized-strategy/=lib/tokenized-strategy/\",\":yearn-vaults-v3/=lib/tokenized-strategy-periphery/lib/yearn-vaults-v3/\"],\"viaIR\":true},\"sources\":{\"lib/openzeppelin/contracts/interfaces/IERC4626.sol\":{\"keccak256\":\"0x7b6690c21e94a45b825631a12581b40a753ea827de5ac9127a6b5833411317f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://00045f2c18d7866618c65819fe180a9a9dab25c1974fab35069bdac9cf624b6b\",\"dweb:/ipfs/QmYk62QRqGHJ3rjqfEtbfEGFHWsenv5tNMbeMfq5HkTP44\"]},\"lib/openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0xdb4d24ee2c087c391d587cd17adfe5b3f9d93b3110b1388c2ab6c7c0ad1dcd05\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ab7b6d5b9e2b88176312967fe0f0e78f3d9a1422fa5e4b64e2440c35869b5d08\",\"dweb:/ipfs/QmXKYWWyzcLg1B2k7Sb1qkEXgLCYfXecR9wYW5obRzWP1Q\"]},\"lib/openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"lib/openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c13d13304ac79a83ab1c30168967d19e2203342ebbd6a9bbce4db7550522dcbf\",\"dweb:/ipfs/QmeN5jKMN2vw5bhacr6tkg78afbTTZUeaacNHqjWt4Ew1r\"]},\"lib/openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin/contracts/utils/Pausable.sol\":{\"keccak256\":\"0xdb484371dfbb848cb6f5d70464e9ac9b2900e4164ead76bbce4fef0b44bcc68f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f9d6f6f6600a2bec622f699081b58350873b5e63ce05464d17d674a290bb8a7c\",\"dweb:/ipfs/QmQKVzSQY1PM3Bid4QhgVVZyx6B4Jx7XgaQzLKHj38vJz8\"]},\"lib/openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"lib/openzeppelin/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol\":{\"keccak256\":\"0x5a173dcd1c1f0074e4df6a9cdab3257e17f2e64f7b8f30ca9e17a8c5ea250e1c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7883819ce2b72264a756063ae578661f62b23f4104b08e9565ac075e619f6ce3\",\"dweb:/ipfs/QmcSZdFiEQkWRmZQhnCdfH9ychooV81pBjr7hfaiYiNZT2\"]},\"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cac938788bc4be12101e59d45588b4e059579f4e61062e1cda8d6b06c0191b15\",\"dweb:/ipfs/QmV2JKCyjTVH3rkWNrfdJRhAT7tZ3usAN2XcnD4h53Mvih\"]},\"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bd39944e8fc06be6dbe2dd1d8449b5336e23c6a7ba3e8e9ae5ae0f37f35283f5\",\"dweb:/ipfs/QmPV3FGYjVwvKSgAXKUN3r9T9GwniZz83CxBpM7vyj2G53\"]},\"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"keccak256\":\"0xb264c03a3442eb37a68ad620cefd1182766b58bee6cec40343480392d6b14d69\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://28879d01fd22c07b44f006612775f8577defbe459cb01685c5e25cd518c91a71\",\"dweb:/ipfs/QmVgfkwv2Fxw6hhTcDUZhE7NkoSKjab3ipM7UaRbt6uXb5\"]},\"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9d213d3befca47da33f6db0310826bcdb148299805c10d77175ecfe1d06a9a68\",\"dweb:/ipfs/QmRgCn6SP1hbBkExUADFuDo8xkT4UU47yjNF5FhCeRbQmS\"]},\"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2455248c8ddd9cc6a7af76a13973cddf222072427e7b0e2a7d1aff345145e931\",\"dweb:/ipfs/QmfYjnjRbWqYpuxurqveE6HtzsY1Xx323J428AKQgtBJZm\"]},\"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xa92e4fa126feb6907daa0513ddd816b2eb91f30a808de54f63c17d0e162c3439\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a367861093b74443b137564d3f3c472f70bcf114739e62059c939f25e315706c\",\"dweb:/ipfs/Qmd7JMpcxD9RuQjK3uM3EzJUgSqdN8vzp8eytEiuwxQJ6h\"]},\"lib/tokenized-strategy-periphery/src/Bases/Hooks/Hooks.sol\":{\"keccak256\":\"0x3b611667af39fd21be0fc69069457fac83abf404cb7401e3e301b04281809f28\",\"license\":\"AGPL-3.0\",\"urls\":[\"bzz-raw://7cdff6153696873e7ce7af51c457d04f7b05835d1657d6ed11594fb3cee6a3d9\",\"dweb:/ipfs/QmPFSKbwy4U8ERCbvndLAQqeGGMXYhMTTXNXvr5xMYM18g\"]},\"lib/tokenized-strategy-periphery/src/libraries/TokenizedStrategyStorageLib.sol\":{\"keccak256\":\"0xb1ca7c99e4ba28e12f4f308b5363504f98bc44e4e020b725b88705e17616ee9e\",\"license\":\"AGPL-3.0\",\"urls\":[\"bzz-raw://d873d44a02b91d0f255a779123dedba07e5f1fb448261d1f9f2f7f1da447d763\",\"dweb:/ipfs/Qme8nb5vzNEtNXokrTJfpsdqnGuKUwVt6iixwUExvpGmsK\"]},\"lib/tokenized-strategy/src/interfaces/ITokenizedStrategy.sol\":{\"keccak256\":\"0xceba04701cccd08fef83be6c5f049c39e908fef768586c9592a94aa86b8eb9e4\",\"license\":\"AGPL-3.0\",\"urls\":[\"bzz-raw://cfdcb655ed96090596b941f2b699ffc4fa67439285e1f6a94a613f124dbd6df7\",\"dweb:/ipfs/QmP12UCxT1gjCDVBa9C8cPsJMMR3wesxoUr2tFFgFfvzay\"]},\"src/interfaces/IIrm.sol\":{\"keccak256\":\"0xc0dffce7fe0bf80acd625eb56e511feffe49b2888d9f50af0a3f1588d956b091\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://b1090c929ae623d0e63a4c6f4ecec6c22097f0d081b25c1c66e7f3eb0b053f0d\",\"dweb:/ipfs/QmWHsR5B4ujTmFeVkEp5poohSA2HJ7i8kwEweek2AxRAo7\"]},\"src/interfaces/IMorpho.sol\":{\"keccak256\":\"0x2541ea114ad687cdc68a8de6743cdfb5f39fd14812b2380e18422dcdf8914d08\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://f44564fccb42d0842ee5047aec83120312e960a716edf9bec2c81eefc284af9f\",\"dweb:/ipfs/QmZbr9MJJCXmMs57y19TLtsuwWEeZvgibkEJoRiRY2i78H\"]},\"src/interfaces/IProtocolConfig.sol\":{\"keccak256\":\"0xf93e6e40a784bf8c8f99a509d1601e94c7773f8c1a2a99d2f5124c9c80a0b94c\",\"license\":\"GPL-20later\",\"urls\":[\"bzz-raw://214a26f0b8cde504000631ecf99c658a19f27a4cc746b86a9dd6a70187d7d67d\",\"dweb:/ipfs/QmYdxiGVznjydQdaN4SaKhe2xr6fkSRPjce9pB7EjEjKHb\"]},\"src/libraries/ErrorsLib.sol\":{\"keccak256\":\"0x05c507e8017abd6aad0538f00b190cc762f3c0c1aa7150633289d904284cdec5\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://5e226fd82496bede5584b41ff81e793de56c2d0fead28bcf98d3048a4e5ca0cd\",\"dweb:/ipfs/QmRu2v3d4YtsfvkZGthw23bo4Y6X6bQU4xnZs6Q7A1Ut9U\"]},\"src/libraries/MarketParamsLib.sol\":{\"keccak256\":\"0xbff6ed7721fa07bc6e779406f7dc7b82147a33a304cc007d9adfb944d9986594\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://6ed48a6b1ea3f45f45f8db8eb7c877c69cf3f1b85225db1641ce770cc7ce9fc1\",\"dweb:/ipfs/QmcbDevtdikuKzJsMxTzBJeKdKzKxcRYztML35uRcM5tGW\"]},\"src/libraries/MathLib.sol\":{\"keccak256\":\"0x64a5930daf1fca5de578ac6916325e61ec84454850ed498b9b9d09240e48cb50\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://5eada052e161d9cb3dab95caffe4200f9be3cf54988335302ba61c4980e661f2\",\"dweb:/ipfs/QmeeAdQq8y9ZL6JPPw3sggmBjk1LHqbRax9HP8Fo4VTViW\"]},\"src/libraries/ProtocolConfigLib.sol\":{\"keccak256\":\"0x93f693578a3d4a5cff4f2cf4f0996121def5e69797d2e03a4e59a7a0d72623f2\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://0417ad8be105f2c8b668bbeda1681f457ecc97a9c2b310243d15e3a5fdb50e69\",\"dweb:/ipfs/QmPXiKZBrkTKpSEYTgU5GdK4feiJB1KyKYx3qdkJ8gKQ6y\"]},\"src/libraries/SharesMathLib.sol\":{\"keccak256\":\"0xe6d1c0ee97239bcda3ca8429fdbad2486faf4192312ce6c4b322772e038f01a8\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://0cf520d5984e253a2d2a9abe195c2d8a6c33b3cddc049175e93a5f22e9972c11\",\"dweb:/ipfs/QmP8rkFEMhx8X7jxtRUkLcq3MdFkTr3nxzof3vzwGhab8p\"]},\"src/libraries/UtilsLib.sol\":{\"keccak256\":\"0x1aba7112612b066203e3d682b34d68f1af6f80b0db817f72c3ce734c04cba604\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://1a99d9ab8598fc1993439318ffedd2ce95146dfd428d45da52de295fe048fce1\",\"dweb:/ipfs/QmZ6xEc7M6xxQBgmX6rTVX4GVMp1rwHpaMAGUGfSUSrMhu\"]},\"src/libraries/periphery/MorphoBalancesLib.sol\":{\"keccak256\":\"0x597b405e91cd7e4359efdc6d4270efc32ab2b3fd13da8921f93b6a6e003c715b\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://568b1f4230f4a24bab19a760a5a38cb4ad0dfbf659ea2cb359409833b12248c2\",\"dweb:/ipfs/QmQWu542MoUYHHHaHehHyTNPprb5ftqa5Gn8jLdNvsDack\"]},\"src/libraries/periphery/MorphoLib.sol\":{\"keccak256\":\"0x7d59323645f4977e73c388cdb3aa7aeb393fc18251e9249e30ad6ece3b92908a\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://a55b606bef16a26907e2afb10f87f14b15f3a02675028484a727e2974fb38e7d\",\"dweb:/ipfs/QmTHQ2uamjnqQwV2Ca3xkAAZ4GAfLhdKGRBxog7Quwn9Ke\"]},\"src/libraries/periphery/MorphoStorageLib.sol\":{\"keccak256\":\"0x4b00bf79174702bc969d6c551e870b326bc9b80858bd1c58efd0e3b11655a977\",\"license\":\"GPL-2.0-or-later\",\"urls\":[\"bzz-raw://2a342079f8a17740391894d90634a2a2bae1dc7de8ea3bcdec69b42072b1663b\",\"dweb:/ipfs/QmbpDPcxHNkVURHk6YQjKZPpcXt4EPhgh87Xun7jUj5Xar\"]},\"src/usd3/USD3.sol\":{\"keccak256\":\"0x2e2f0b800dc634ad74eb517e07fa67ec6bdf41f255ffd79f69c52bc5acd86abd\",\"license\":\"AGPL-3.0\",\"urls\":[\"bzz-raw://043f51a6fb58ee128e371a93743031927b3850c45a314475f1c4ac6c10a8eaf0\",\"dweb:/ipfs/QmNydAsWnBTc5wKfJTBaTR8Qg9bE5StG8qJV5UazwLmzEt\"]},\"src/usd3/base/BaseHooksUpgradeable.sol\":{\"keccak256\":\"0x192cd36199c5fe4c8b8bbc18bbf8f1f5d5e664cf9a848cff16540fb37edc61e9\",\"license\":\"AGPL-3.0\",\"urls\":[\"bzz-raw://136bee8800ca25255b878863aa743bc09a1bc4038b6feb1cca8d7a559f009747\",\"dweb:/ipfs/QmQ9uWFPtDevc1GFjAfDr6i8kpgyYFx3XVrXHZW26dz9Zq\"]},\"src/usd3/base/BaseStrategyUpgradeable.sol\":{\"keccak256\":\"0x8ac546d1341684308f1821e8cc8838b513b5544d55958fdbccb7f0415d64aef9\",\"license\":\"AGPL-3.0\",\"urls\":[\"bzz-raw://a5ec6694591636e95de4835a31544e8117e1d4ed6eabbfddaf4dc051e520d9cd\",\"dweb:/ipfs/QmfAYeswJHcSwJoSmUR6yPvDWBtkippsKiv44FCpD4hkiw\"]}},\"version\":1}","userdoc":{"kind":"user","errors":{"MaxUint128Exceeded()":[{"notice":"Thrown when the maximum uint128 is exceeded."}]},"notice":"Senior tranche strategy for USDC-based lending on 3Jane's credit markets","methods":{"sUSD3()":{"notice":"Address of the subordinate sUSD3 strategy"},"report()":{"notice":"Report profit and loss with pre-report context for accurate loss absorption"},"symbol()":{"notice":"Get the symbol for the USD3 token"},"marketId()":{"notice":"Market ID for the lending market this strategy uses"},"minDeposit()":{"notice":"Minimum deposit amount required"},"maxOnCredit()":{"notice":"Get the maximum percentage of funds to deploy to credit markets from ProtocolConfig"},"tendTrigger()":{"notice":"Returns if tend() should be called by a keeper."},"marketParams()":{"notice":"Get the market parameters for this strategy"},"morphoCredit()":{"notice":"MorphoCredit contract for lending operations"},"suppliedWaUSDC()":{"notice":"Get the amount of waUSDC supplied to MorphoCredit"},"balanceOfWaUSDC()":{"notice":"Get the balance of waUSDC held locally (not deployed to MorphoCredit)"},"setSUSD3(address)":{"notice":"Set the sUSD3 subordinate strategy address"},"tendThis(uint256)":{"notice":"Will call the internal '_tend' when a keeper tends the strategy."},"freeFunds(uint256)":{"notice":"Should attempt to free the '_amount' of 'asset'."},"harvestAndReport()":{"notice":"Returns the accurate amount of all funds currently held by the Strategy."},"syncTrancheShare()":{"notice":"Sync the tranche share (performance fee) from ProtocolConfig"},"deployFunds(uint256)":{"notice":"Can deploy up to '_amount' of 'asset' in yield source."},"mint(uint256,address)":{"notice":"Mint shares by depositing assets"},"ringFencedLiquidity()":{"notice":"Fenced capital-call cash in USDC asset units."},"setMinDeposit(uint256)":{"notice":"Set minimum deposit amount"},"deposit(uint256,address)":{"notice":"Deposit assets and receive shares"},"supplyCapExempt(address)":{"notice":"Receivers whose self-deposits bypass USD3 supply-cap headroom and first-time minimum-deposit checks."},"releaseRingFence(uint256)":{"notice":"Release ring-fenced liquidity back into the withdrawable liquidity calculation."},"ringFenceConduit(address)":{"notice":"Conduits whose self-deposits add to the ring-fenced liquidity accumulator."},"shutdownWithdraw(uint256)":{"notice":"Will call the internal '_emergencyWithdraw' function."},"transfer(address,uint256)":{"notice":"Transfer shares to another address"},"availableWithdrawLimit(address)":{"notice":"Returns the withdrawable assets for an owner after liquidity and floor checks."},"redeem(uint256,address,address)":{"notice":"Redeem shares for assets"},"setProfitMaxUnlockTime(uint256)":{"notice":"Set the profit unlock time without releasing locked profit ahead of an unreported loss."},"setSupplyCapExempt(address,bool)":{"notice":"Update supply-cap and first-time minimum-deposit exemption status for a receiver."},"setRingFenceConduit(address,bool)":{"notice":"Update whether a conduit self-deposit adds to ring-fenced liquidity."},"withdraw(uint256,address,address)":{"notice":"Withdraw assets by burning shares"},"transferFrom(address,address,uint256)":{"notice":"Transfer shares from one address to another"},"redeem(uint256,address,address,uint256)":{"notice":"Redeem shares with custom max loss"},"withdraw(uint256,address,address,uint256)":{"notice":"Withdraw assets with custom max loss"}},"version":1},"devdoc":{"kind":"dev","title":"USD3","author":"3Jane Protocol","errors":{"NotInitializing()":[{"details":"The contract is not initializing."}],"InvalidInitialization()":[{"details":"The contract is already initialized."}]},"events":{"Initialized(uint64)":{"details":"Triggered when the contract has been initialized or reinitialized."},"Transfer(address,address,uint256)":{"details":"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero."}},"details":"Implements Yearn V3 tokenized strategy pattern for unsecured lending via MorphoCredit. Deploys USDC capital to 3Jane's modified Morpho Blue markets that use credit-based underwriting instead of collateral. Its loss waterfall uses strategy-owned locked-profit shares before sUSD3 subordinate capital, then exposes USD3 holders to any residual loss. Key features: - Senior tranche whose current principal and PPS are buffered first by locked profit, then by sUSD3 holdings - Configurable deployment ratio to credit markets (maxOnCredit) - Automatic yield distribution to sUSD3 via performance fees - Loss absorption through direct share burning of sUSD3 holdings - Supply-cap exemptions for protocol-controlled deposit receivers - Dynamic fee adjustment via ProtocolConfig integration Yield Distribution Mechanism: - Tranche share distributed to sUSD3 holders via TokenizedStrategy's performance fee - Performance fee can be set from 0-100% through syncTrancheShare() - Direct storage manipulation bypasses TokenizedStrategy's 50% fee limit - Keeper-controlled updates ensure protocol-wide consistency Loss Absorption Mechanism: - TokenizedStrategy first burns strategy-owned locked-profit shares remaining from prior profitable reports - USD3 burns sUSD3-held USD3 shares only for the loss remaining after that locked-profit burn - Current USD3 principal and PPS remain protected while locked profit covers the loss, but cash-collected profit   that would otherwise unlock to USD3 holders is consumed before junior principal - Direct storage manipulation burns the required sUSD3-held shares without asset transfers, capped by its balance - Losses exceeding both outstanding locked profit and sUSD3's USD3 balance reduce USD3 holders proportionally - Both loss-to-share conversions round down; at high PPS, a loss worth less than one base share can burn nothing   from either buffer and still reduce senior PPS","methods":{"nav()":{"details":"Net asset value of the strategy in USDC terms","returns":{"_0":"Sum of deployed and local waUSDC converted to assets, plus idle USDC held by the strategy"}},"report()":{"returns":{"loss":"Amount of loss incurred","profit":"Amount of profit generated"}},"symbol()":{"returns":{"_0":"Symbol string \"USD3\""}},"constructor":{"custom:oz-upgrades-unsafe-allow":"constructor"},"maxOnCredit()":{"details":"Returns the value from ProtocolConfig directly. If not configured in ProtocolConfig,      it returns 0, effectively preventing deployment until explicitly configured.Below 100%, this is an honest-operation deployment and liquidity-buffer target, not an adversarially      enforceable exposure boundary. DEBT_CAP is the enforceable boundary: MorphoCredit borrow admission reads      debt but never supply, so a temporary deposit cannot increase the borrowable total by even one unit.","returns":{"_0":"Maximum deployment ratio in basis points (10000 = 100%)"}},"tendTrigger()":{"returns":{"_0":". Should return true if tend() should be called by keeper or false if not.","_1":". Calldata for the tend call."}},"marketParams()":{"returns":{"_0":"MarketParams struct containing lending market configuration"}},"suppliedWaUSDC()":{"returns":{"_0":"Amount of waUSDC deployed to the lending market"}},"balanceOfWaUSDC()":{"returns":{"_0":"Amount of waUSDC held in this contract"}},"setSUSD3(address)":{"params":{"_sUSD3":"Address of the sUSD3 strategy"},"details":"Only callable by management. After calling, also set performance fee recipient."},"tendThis(uint256)":{"params":{"_totalIdle":"The amount of current idle funds that can be deployed during the tend"},"details":"Callback for the TokenizedStrategy to initiate a _tend call in the strategy. This can only be called after a tend() delegateCall to the TokenizedStrategy so msg.sender == address(this). We name the function `tendThis` so that `tend` calls are forwarded to the TokenizedStrategy."},"freeFunds(uint256)":{"params":{"_amount":"The amount of 'asset' that the strategy should attempt to free up."},"details":"Callback for the TokenizedStrategy to call during a withdraw or redeem to free the needed funds to service the withdraw. This can only be called after a 'withdraw' or 'redeem' delegateCall to the TokenizedStrategy so msg.sender == address(this)."},"harvestAndReport()":{"details":"Callback for the TokenizedStrategy to call during a report to get an accurate accounting of assets the strategy controls. This can only be called after a report() delegateCall to the TokenizedStrategy so msg.sender == address(this).","returns":{"_0":". A trusted and accurate account for the total amount of 'asset' the strategy currently holds including idle funds."}},"syncTrancheShare()":{"details":"Reads TRANCHE_SHARE_VARIANT from ProtocolConfig and updates local storage IMPORTANT: Direct storage manipulation is necessary here because TokenizedStrategy's setPerformanceFee() function has a hardcoded MAX_FEE limit of 5000 (50%). Since we need to support higher fee distributions to sUSD3 (potentially up to 100% for full subordination scenarios), we must bypass this restriction by directly modifying the storage slot. Storage layout in TokenizedStrategy (slot 9): - Bits 0-31: profitMaxUnlockTime (uint32) - Bits 32-47: performanceFee (uint16) <- We modify this - Bits 48-207: performanceFeeRecipient (address)Only callable by keepers to ensure controlled updates"},"deployFunds(uint256)":{"params":{"_amount":"The amount of 'asset' that the strategy can attempt to deposit in the yield source."},"details":"Callback for the TokenizedStrategy to call during a {deposit} or {mint} to tell the strategy it can deploy funds. Since this can only be called after a {deposit} or {mint} delegateCall to the TokenizedStrategy msg.sender == address(this). Unless a whitelist is implemented this will be entirely permissionless and thus can be sandwiched or otherwise manipulated."},"getMarketLiquidity()":{"details":"Get current market liquidity information","returns":{"totalShares":"Total supply shares in the market","waUSDCLiquidity":"Available liquidity in the market","totalBorrowAssets":"Total assets borrowed from the market","totalSupplyAssets":"Total assets supplied to the market"}},"mint(uint256,address)":{"params":{"shares":"Amount of shares to mint","receiver":"Address to receive the shares"},"returns":{"assets":"Amount of assets deposited"}},"setMinDeposit(uint256)":{"params":{"_minDeposit":"Minimum amount required for deposits"}},"deposit(uint256,address)":{"params":{"assets":"Amount of assets to deposit","receiver":"Address to receive the shares"},"returns":{"shares":"Amount of shares minted"}},"releaseRingFence(uint256)":{"params":{"_assets":"Amount of fenced liquidity to release, in USDC asset units."}},"shutdownWithdraw(uint256)":{"params":{"_amount":"The amount of asset to attempt to free."},"details":"Callback for the TokenizedStrategy during an emergency withdraw. This can only be called after a emergencyWithdraw() delegateCall to the TokenizedStrategy so msg.sender == address(this). We name the function `shutdownWithdraw` so that `emergencyWithdraw` calls are forwarded to the TokenizedStrategy."},"transfer(address,uint256)":{"params":{"to":"Address to receive the shares","amount":"Amount of shares to transfer"},"returns":{"_0":"success Whether the transfer succeeded"}},"availableDepositLimit(address)":{"params":{"_owner":"Address to check limit for"},"details":"Returns available deposit limit, enforcing borrower restrictions and supply cap","returns":{"_0":"Maximum amount that can be deposited"}},"availableWithdrawLimit(address)":{"details":"The bps floor is a scaling/rate knob applied to then-current total assets, so repeated redemptions drain geometrically toward the nominal floor. The nominal floor is the hard ring-fence and should be set alongside the bps floor whenever a fixed asset amount must remain reserved.","returns":{"_0":"Maximum amount that can be withdrawn"}},"redeem(uint256,address,address)":{"params":{"owner":"Address whose shares are burned","shares":"Amount of shares to redeem","receiver":"Address to receive the assets"},"returns":{"assets":"Amount of assets withdrawn"}},"setProfitMaxUnlockTime(uint256)":{"details":"Nonzero updates retain the TokenizedStrategy implementation's behavior."},"setSupplyCapExempt(address,bool)":{"params":{"_exempt":"True to require self-deposits that bypass supply-cap headroom and first-time minimum-deposit checks; false to allow third-party deposits and apply the ordinary checks.","_account":"Receiver address to update."},"details":"An exempt receiver may only be deposited to by itself. A third party depositing directly to that exempt receiver reverts. Helper is the USD3 receiver only on its hop path, and its user-level limit check still applies the supply cap and borrower restriction before the deposit. Exempting Helper therefore bypasses only the receiver-level first-time minimum for that path; it does not affect the non-hop path, whose receiver is the user.Pair this flag operationally with `ringFenceConduit`. When both flags are set, every accepted deposit is a self-deposit and receives ring-fence credit. Revoking this exemption while leaving the conduit flag set permits third-party deposits that receive no ring-fence credit. LCC deployment grants both flags atomically; revoke them atomically as well."},"setRingFenceConduit(address,bool)":{"params":{"_conduit":"Receiver address to update.","_enabled":"True to accumulate self-deposits into the ring fence, false to disable accumulation."},"details":"Pair this flag operationally with `supplyCapExempt`. When both flags are set, every accepted deposit is a self-deposit and receives ring-fence credit. Revoking the exemption while leaving this conduit flag set permits third-party deposits that receive no ring-fence credit. LCC deployment grants both flags atomically; revoke them atomically as well."},"withdraw(uint256,address,address)":{"params":{"owner":"Address whose shares are burned","assets":"Amount of assets to withdraw","receiver":"Address to receive the assets"},"returns":{"shares":"Amount of shares burned"}},"transferFrom(address,address,uint256)":{"params":{"to":"Address to transfer to","from":"Address to transfer from","amount":"Amount of shares to transfer"},"returns":{"_0":"success Whether the transfer succeeded"}},"redeem(uint256,address,address,uint256)":{"params":{"owner":"Address whose shares are burned","shares":"Amount of shares to redeem","maxLoss":"Maximum acceptable loss in basis points","receiver":"Address to receive the assets"},"returns":{"assets":"Amount of assets withdrawn"}},"withdraw(uint256,address,address,uint256)":{"params":{"owner":"Address whose shares are burned","assets":"Amount of assets to withdraw","maxLoss":"Maximum acceptable loss in basis points","receiver":"Address to receive the assets"},"returns":{"shares":"Amount of shares burned"}}},"version":1,"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"},"sUSD3":{"details":"Used for loss absorption and yield distribution"}}},"storageLayout":{"types":{"t_bool":{"label":"bool","encoding":"inplace","numberOfBytes":"1"},"t_address":{"label":"address","encoding":"inplace","numberOfBytes":"20"},"t_uint256":{"label":"uint256","encoding":"inplace","numberOfBytes":"32"},"t_contract(ERC20)4872":{"label":"contract ERC20","encoding":"inplace","numberOfBytes":"20"},"t_contract(IMorpho)6876":{"label":"contract IMorpho","encoding":"inplace","numberOfBytes":"20"},"t_mapping(t_address,t_bool)":{"key":"t_address","label":"mapping(address => bool)","value":"t_bool","encoding":"mapping","numberOfBytes":"32"},"t_array(t_uint256)37_storage":{"base":"t_uint256","label":"uint256[37]","encoding":"inplace","numberOfBytes":"1184"},"t_array(t_uint256)48_storage":{"base":"t_uint256","label":"uint256[48]","encoding":"inplace","numberOfBytes":"1536"},"t_mapping(t_address,t_uint256)":{"key":"t_address","label":"mapping(address => uint256)","value":"t_uint256","encoding":"mapping","numberOfBytes":"32"},"t_userDefinedValueType(Id)6519":{"label":"Id","encoding":"inplace","numberOfBytes":"32"},"t_contract(ITokenizedStrategy)6484":{"label":"contract ITokenizedStrategy","encoding":"inplace","numberOfBytes":"20"},"t_struct(MarketParams)6532_storage":{"label":"struct MarketParams","members":[{"slot":"0","type":"t_address","astId":6521,"label":"loanToken","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"1","type":"t_address","astId":6523,"label":"collateralToken","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"2","type":"t_address","astId":6525,"label":"oracle","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"3","type":"t_address","astId":6527,"label":"irm","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"4","type":"t_uint256","astId":6529,"label":"lltv","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"5","type":"t_address","astId":6531,"label":"creditLine","offset":0,"contract":"src/usd3/USD3.sol:USD3"}],"encoding":"inplace","numberOfBytes":"192"}},"storage":[{"slot":"0","type":"t_contract(ERC20)4872","astId":11710,"label":"asset","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"1","type":"t_contract(ITokenizedStrategy)6484","astId":11714,"label":"TokenizedStrategy","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"2","type":"t_array(t_uint256)48_storage","astId":11719,"label":"__gap","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"50","type":"t_contract(IMorpho)6876","astId":9103,"label":"morphoCredit","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"51","type":"t_userDefinedValueType(Id)6519","astId":9107,"label":"marketId","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"52","type":"t_struct(MarketParams)6532_storage","astId":9111,"label":"_marketParams","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"58","type":"t_address","astId":9114,"label":"sUSD3","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"58","type":"t_bool","astId":9116,"label":"__deprecated_whitelistEnabled","offset":20,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"59","type":"t_mapping(t_address,t_bool)","astId":9120,"label":"__deprecated_whitelist","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"60","type":"t_mapping(t_address,t_bool)","astId":9124,"label":"__deprecated_depositorWhitelist","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"61","type":"t_uint256","astId":9127,"label":"minDeposit","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"62","type":"t_mapping(t_address,t_uint256)","astId":9131,"label":"__deprecated_depositTimestamp","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"63","type":"t_mapping(t_address,t_bool)","astId":9136,"label":"supplyCapExempt","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"64","type":"t_mapping(t_address,t_bool)","astId":9141,"label":"ringFenceConduit","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"65","type":"t_uint256","astId":9144,"label":"ringFencedLiquidity","offset":0,"contract":"src/usd3/USD3.sol:USD3"},{"slot":"66","type":"t_array(t_uint256)37_storage","astId":11212,"label":"__gap","offset":0,"contract":"src/usd3/USD3.sol:USD3"}]},"transientStorageLayout":null,"evm":{"bytecode":{"object":"60808060405234620000bd577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c16620000ae57506001600160401b036002600160401b03198282160162000068575b604051615cee9081620000c28239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f808062000058565b63f92ee8a960e01b8152600490fd5b5f80fdfe60806040526004361015610019575b34156131f9575b5f80fd5b5f3560e01c8063020dfdc71461029457806304bd46291461028f57806323b872dd1461028a5780632606a10b146102855780632b832dbc146102805780633d6cb575146101d657806341b3d1851461027b5780634251c3541461027657806346aa2f121461027157806349317f1d1461026c5780634b4dcf8214610267578063503160d91461026257806359ddbab21461025d5780635d265d3f146102585780636e553f65146102535780636ed71ede1461024e5780637b9e68f21461024957806388bdedb7146102445780638fcc9cfb1461023f57806394bf804d1461023a57806395d89b41146102355780639d7fb70c146102305780639f40a7b31461022b578063a318c1a414610226578063a465375714610221578063a9059cbb1461021c578063a9b89c0714610217578063b460af9414610212578063ba0876521461020d578063c1590cd714610208578063c7cedf1e14610203578063cb6d71bc146101fe578063d19a3bb8146101f9578063daf3dd49146101f4578063df69b22a146101ef578063e61582b5146101ea578063efb5f911146101e5578063f51b81bf146101e0578063f7f6ba53146101db5763fde813a80361000e575b6108c6565b61229e565b61218a565b612139565b612101565b611fac565b611f71565b611f25565b611ed9565b611db9565b611d34565b611cb8565b611c3e565b611bbc565b611aad565b611914565b611895565b611808565b611775565b6116fa565b6113d1565b6112f6565b61128a565b6111c6565b611127565b610da3565b610d18565b610c6c565b610c32565b610bc6565b6109c5565b610980565b610948565b61090d565b6107a6565b61065f565b610464565b610418565b34610015575f60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043573ffffffffffffffffffffffffffffffffffffffff60015416803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f5576103e2575b506041548082116103845781810390811161037f5760418190556040805192835260208301919091527f62b761b1158418079bd8028d2057ba8c8644d3ef7f5000aaaf2d7a1d67f7d5b49190819081015b0390a180f35b61240d565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f2166656e636500000000000000000000000000000000000000000000000000006044820152fd5b6103ed91925061231c565b5f905f610328565b612402565b73ffffffffffffffffffffffffffffffffffffffff81160361001557565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576104526004356103fa565b602061045c612478565b604051908152f35b346100155760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043561049f816103fa565b6024356104ab816103fa565b60443561052a61051c6040516020957f23b872dd000000000000000000000000000000000000000000000000000000008783015273ffffffffffffffffffffffffffffffffffffffff809116958660248401521660448201528360648201526064815261051781612351565b6137a9565b848082518301019101612456565b9182918261064b575b5081610620575b508061056e575b61055d9250610561575b60405190151581529081906020820190565b0390f35b610569614a20565b61054b565b506004826105ad61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051928380927fbf86d6900000000000000000000000000000000000000000000000000000000082525afa9081156103f55761055d935f926105f3575b505015610541565b6106129250803d10610619575b61060a81836123c1565b810190612456565b5f806105eb565b503d610600565b9050610644610594603a5473ffffffffffffffffffffffffffffffffffffffff1690565b145f61053a565b151591505f610533565b5f91031261001557565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576106af61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b604051907f18160ddd0000000000000000000000000000000000000000000000000000000082526020908183600481845afa9283156103f5575f93610782575b5081600491604051928380927f01e1d1140000000000000000000000000000000000000000000000000000000082525afa9182156103f5575f92610755575b505061074461073b613823565b93909284613872565b604080519182526020820192909252f35b6107749250803d1061077b575b61076c81836123c1565b810190612447565b5f8061072e565b503d610762565b600491935061079e8391823d841161077b5761076c81836123c1565b9391506106ef565b34610015575f60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576004356107e2816103fa565b73ffffffffffffffffffffffffffffffffffffffff8060015416803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f5576108b3575b50603a5491818316610015571690811561001557817fc3212a26ea3792ed00e630d63eb8ec2a9295974fe90e94ff25a8f70987fcdeeb927fffffffffffffffffffffffff00000000000000000000000000000000000000006040931617603a558151905f82526020820152a180f35b6108be91935061231c565b5f915f610844565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557610900303314613b17565b61090b600435613b87565b005b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576020603d54604051908152f35b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c6129d6565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c6004356109c0816103fa565b612a49565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576109fb613b7c565b610a03612e92565b610a2561059460325473ffffffffffffffffffffffffffffffffffffffff1690565b803b15610015576040517f1e4711cf000000000000000000000000000000000000000000000000000000008152905f908290818381610a678860048301611162565b03925af180156103f557610bad575b50610a9961059460015473ffffffffffffffffffffffffffffffffffffffff1690565b60405180917fbf86d69000000000000000000000000000000000000000000000000000000000825281600460209485935afa9081156103f5575f91610b90575b5015610afb575b61055d610aeb613071565b6040519081529081906020820190565b610b1c6105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152908290829060249082905afa9081156103f557610b6d925f92610b73575b505061500a565b80610ae0565b610b899250803d1061077b5761076c81836123c1565b8280610b66565b610ba79150823d84116106195761060a81836123c1565b82610ad9565b80610bba610bc09261231c565b80610655565b80610a76565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff600435610c16816103fa565b165f526040602052602060ff60405f2054166040519015158152f35b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155761090b303314613b17565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576080610ca4612eed565b91604051938452602084015260408301526060820152f35b91908251928382525f5b848110610d045750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201610cc6565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557610d4e6144e9565b604051907f440368a300000000000000000000000000000000000000000000000000000000602083015260048252610d858261236d565b61055d60405192839215158352604060208401526040830190610cbc565b34610015576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043560243591610de3836103fa565b81821580611120575b61108a575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ffd575b610e52610e4e610e478673ffffffffffffffffffffffffffffffffffffffff165f52603f60205260405f2090565b5460ff1690565b1590565b93848015610fde575b610e6490613b17565b610e8661059460015473ffffffffffffffffffffffffffffffffffffffff1690565b83517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152906020908190839060249082905afa9384156103f55761055d97610f9795610f90945f91610fc1575b50159081610fb9575b50610fa5575b5084517f6e553f6500000000000000000000000000000000000000000000000000000000828201526024810187905273ffffffffffffffffffffffffffffffffffffffff84166044820152610f839061051781606481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826123c1565b8051810182019101612447565b8094614794565b519081529081906020820190565b610fb390603d54111561472f565b5f610eff565b90505f610ef9565b610fd89150843d861161077b5761076c81836123c1565b5f610ef0565b503373ffffffffffffffffffffffffffffffffffffffff821614610e5b565b5061101f6105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b81517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290602090829060249082905afa9081156103f5575f9161106b575b50610e19565b611084915060203d60201161077b5761076c81836123c1565b5f611065565b506110ad61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b6020825180927fb3d7f6b900000000000000000000000000000000000000000000000000000000825281806110e960048201905f602083019252565b03915afa9081156103f5575f91611101575b50610df1565b61111a915060203d60201161077b5761076c81836123c1565b5f6110fb565b505f610dec565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576020603354604051908152f35b6111c49092919260c081019360a0908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015282606082015116606086015260808101516080860152015116910152565b565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015575f60a060405161120381612335565b828152826020820152826040820152826060820152826080820152015260c061122a612e92565b611288604051809260a0908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015282606082015116606086015260808101516080860152015116910152565bf35b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff6004356112da816103fa565b165f52603f602052602060ff60405f2054166040519015158152f35b34610015575f60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043573ffffffffffffffffffffffffffffffffffffffff60015416803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f5576113bd575b506020817f96a008f96f1c0ab9fa3d9ddd43cdfc614848c4d054d51f43662ed900e9d094c892603d55604051908152a180f35b6113c891925061231c565b5f90602061138a565b34610015576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043560243591611411836103fa565b5f82611663575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146115d6575b61146e610e4e610e478673ffffffffffffffffffffffffffffffffffffffff165f52603f60205260405f2090565b938480156115b7575b61148090613b17565b6114a261059460015473ffffffffffffffffffffffffffffffffffffffff1690565b83517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152906020908190839060249082905afa9384156103f55761055d97610f9795611577945f9161159a575b50159081611592575b5061157e575b5084517f94bf804d00000000000000000000000000000000000000000000000000000000828201526024810187905273ffffffffffffffffffffffffffffffffffffffff84166044820152610f83906105178160648101610f57565b9384614794565b61158c90603d54111561472f565b5f61151b565b90505f611515565b6115b19150843d861161077b5761076c81836123c1565b5f61150c565b503373ffffffffffffffffffffffffffffffffffffffff821614611477565b506115f86105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b81517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290602090829060249082905afa9081156103f5575f91611644575b50611440565b61165d915060203d60201161077b5761076c81836123c1565b5f61163e565b5061168661059460015473ffffffffffffffffffffffffffffffffffffffff1690565b6020825180927fb3d7f6b900000000000000000000000000000000000000000000000000000000825281806116c388600483019190602083019252565b03915afa9081156103f5575f916116db575b50611418565b6116f4915060203d60201161077b5761076c81836123c1565b5f6116d5565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155761055d6040516117378161236d565b600481527f55534433000000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190610cbc565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576117af303314613b17565b61090b60043561492f565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc608091011261001557600435906024356117f4816103fa565b90604435611801816103fa565b9060643590565b3461001557602061045c611887610f57610517611824366117ba565b6040517f9f40a7b3000000000000000000000000000000000000000000000000000000008a820152602481019490945273ffffffffffffffffffffffffffffffffffffffff928316604485015291166064830152608482015291829060a4820190565b828082518301019101612447565b3461001557602061045c611887610f576105176118b1366117ba565b6040517fa318c1a4000000000000000000000000000000000000000000000000000000008a820152602481019490945273ffffffffffffffffffffffffffffffffffffffff928316604485015291166064830152608482015291829060a4820190565b34610015575f807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff8060015416803b15610015575f602491604051928380927fd43fdcf70000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f557611a99575b5060206004916119b36135fd565b16604051928380927f76e66a1c0000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f91611a7a575b506127108111610015576103797f617d69aa6f8f8f7158e168208ffd102c878214b34e8510746322af83f775aab7917fd2841a5d2692465040bd5e06a6f3b37483952c866e0f304dc0e03f76a1f8a0b97fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff8154168260201b179055604051918291829190602083019252565b611a93915060203d60201161077b5761076c81836123c1565b5f6119ee565b611aa491925061231c565b5f9060206119a5565b346100155760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557600435611ae8816103fa565b602435611b58611b4a60405173ffffffffffffffffffffffffffffffffffffffff6020957fa9059cbb00000000000000000000000000000000000000000000000000000000878401521660248201528360448201526044815261051781612389565b838082518301019101612456565b80918192611bb2575b5080611b88575b8061056e5761055d92506105615760405190151581529081906020820190565b50611bab610594603a5473ffffffffffffffffffffffffffffffffffffffff1690565b3314611b68565b905015155f611b61565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c612f73565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126100155760043590602435611c2e816103fa565b90604435611c3b816103fa565b90565b3461001557602061045c611887611c5436611bf4565b604051927fa318c1a40000000000000000000000000000000000000000000000000000000087850152602484015273ffffffffffffffffffffffffffffffffffffffff80921660448401521660648201525f60848201526084815261051781612335565b3461001557602061045c611887611cce36611bf4565b604051927f9f40a7b30000000000000000000000000000000000000000000000000000000087850152602484015273ffffffffffffffffffffffffffffffffffffffff809216604484015216606482015261271060848201526084815261051781612335565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c613071565b8015150361001557565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc604091011261001557600435611dac816103fa565b90602435611c3b81611d6c565b3461001557611dc736611d76565b6001545f9273ffffffffffffffffffffffffffffffffffffffff809216803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f557611e9f575b507f62374b3ccb739da5991edc41e2ea922bab2b874148694015005a9b2691df5f52916020911692835f52603f8252611e938160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a280f35b602091945091611ecf7f62374b3ccb739da5991edc41e2ea922bab2b874148694015005a9b2691df5f529361231c565b5f94915091611e2c565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602060405173d4fa2d31b7968e448877f69a96de69f5de8cd23e8152f35b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602060405173d377919fa87120584b21279a491f82d5265a139c8152f35b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576020604154604051908152f35b34610015575f60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff60015416803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f5576120f0575b50600435158015906120e1575b156120835761207f61205b36612f39565b61206860405191826123c1565b368152365f60208301375f602036830101526137a9565b5080f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f216c6f73730000000000000000000000000000000000000000000000000000006044820152fd5b506120ea613229565b1561204a565b6120fa915061231c565b5f8061203d565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c61319a565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602073ffffffffffffffffffffffffffffffffffffffff60325416604051908152f35b346100155761219836611d76565b6001545f9273ffffffffffffffffffffffffffffffffffffffff809216803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f557612264575b507fffd73fc43ae6addb25c141d1108d251a943fb8be0d967a6a8fe8b436d564d921916020911692835f5260408252611e938160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6020919450916122947fffd73fc43ae6addb25c141d1108d251a943fb8be0d967a6a8fe8b436d564d9219361231c565b5f949150916121fd565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602073ffffffffffffffffffffffffffffffffffffffff603a5416604051908152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b67ffffffffffffffff811161233057604052565b6122ef565b60c0810190811067ffffffffffffffff82111761233057604052565b60a0810190811067ffffffffffffffff82111761233057604052565b6040810190811067ffffffffffffffff82111761233057604052565b6080810190811067ffffffffffffffff82111761233057604052565b6060810190811067ffffffffffffffff82111761233057604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761233057604052565b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9190820391821161037f57565b90816020910312610015575190565b908160209103126100155751611c3b81611d6c565b9190820180921161037f57565b6124996105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048083019190915292602092908390839060249082905afa9182156103f5575f926129b0575b5061250b61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b8151927f01e1d11400000000000000000000000000000000000000000000000000000000845284848781855afa9384156103f5575f94612991575b5061254f613229565b6129875761255b6132d3565b9291505f8551917f5c975abb00000000000000000000000000000000000000000000000000000000835273d4fa2d31b7968e448877f69a96de69f5de8cd23e9489848c81895afa80156103f5578a945f9161296a575b50156127fa575050506125f8925f905b865180809681947f07a2d13a0000000000000000000000000000000000000000000000000000000083528d83019190602083019252565b03915afa9182156103f55787928792612618925f926127db575b5061246b565b928451928380927fbf86d6900000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f916127be575b506127b657604154810390811115029361266d6105946135fd565b908251907fcc718f7600000000000000000000000000000000000000000000000000000000928383528683806126c9858201907f3412c9f85ed46ce3ec8f65a167e2554559c90769888f1561e7879ccce085f6ee602083019252565b0381845afa9384156103f5576127189588945f96612797575b505180968194829383528201907f79742dc31db595cf1ca3dc9e1e2303db56ca7a50d0795409429542539d8e3a9a602083019252565b03915afa9384156103f557612764946127579361274b925f9261277a575b505080612710809111612772575b50846136b2565b90818082119118021890565b8103908111159190820290565b829150808093109118021890565b90505f612744565b6127909250803d1061077b5761076c81836123c1565b5f80612736565b6127af919650853d871161077b5761076c81836123c1565b945f6126e2565b935050505090565b6127d59150853d87116106195761060a81836123c1565b5f612652565b6127f3919250843d861161077b5761076c81836123c1565b905f612612565b9061281661281c9261280a6129d6565b92818118908211021890565b9061246b565b938461282d575b6125f894506125c1565b86517fd905777e00000000000000000000000000000000000000000000000000000000808252308c83019081529194509192508990849081906020010381855afa80156103f55789935f9161294d575b501590816128b7575b506125f894901561289957505f90612823565b6128b1906128a56133f1565b90818082109118021890565b90612823565b61290e9391506128df61059460325473ffffffffffffffffffffffffffffffffffffffff1690565b908851948592839283528d830191909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b0381845afa9384156103f5576125f89489935f91612930575b50159094612886565b6129479150843d861161077b5761076c81836123c1565b5f612927565b6129649150843d861161077b5761076c81836123c1565b5f61287d565b6129819150853d87116106195761060a81836123c1565b5f6125b1565b5050505050505f90565b6129a9919450853d871161077b5761076c81836123c1565b925f612546565b6129c8919250833d851161077b5761076c81836123c1565b905f6124e8565b1561001557565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91612a30575090565b611c3b915060203d60201161077b5761076c81836123c1565b612a77610e4e610e478373ffffffffffffffffffffffffffffffffffffffff165f52603f60205260405f2090565b80612e1b575b612c5657612aad81612aa460325473ffffffffffffffffffffffffffffffffffffffff1690565b60335490613e49565b612c5657612abc6105946135fd565b6040517fcc718f760000000000000000000000000000000000000000000000000000000081527f4bba860c0c28b1a4ae0214c01f08e53b00bfe2e087690d7a04d73a15360ec6a76004820152906020908190839060249082905afa9182156103f5575f92612dfc575b508115612df557612b57610e478473ffffffffffffffffffffffffffffffffffffffff165f52603f60205260405f2090565b8015612dcc575b612da557612b8461059460015473ffffffffffffffffffffffffffffffffffffffff1690565b916040517f01e1d1140000000000000000000000000000000000000000000000000000000081528281600481875afa9081156103f5575f91612d88575b5080821115612d6057612bd39161243a565b92604051917fc6e6f592000000000000000000000000000000000000000000000000000000008352808380612c1088600483019190602083019252565b0381875afa9283156103f5575f93612d69575b508215612d6057603d5491818315918215612cde575b5050612cd757818510928315612c5b575b5050509050612c565790565b505f90565b819350612c9c929460405180809581947fb3d7f6b9000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b03915afa9182156103f5575f92612cba575b505010805f8080612c4a565b612cd09250803d1061077b5761076c81836123c1565b5f80612cae565b5050505090565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff919091166004820152915081602481885afa9081156103f5575f91612d43575b501515815f612c39565b612d5a9150823d841161077b5761076c81836123c1565b5f612d39565b50505050505f90565b81612d819294503d851161077b5761076c81836123c1565b915f612c23565b612d9f9150833d851161077b5761076c81836123c1565b5f612bc1565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214612b5e565b5050505f90565b81612e149293503d841161077b5761076c81836123c1565b905f612b25565b506040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91612e73575b50612a7d565b612e8c915060203d6020116106195761060a81836123c1565b5f612e6d565b60405190612e9f82612335565b8160a073ffffffffffffffffffffffffffffffffffffffff80603454168352806035541660208401528060365416604084015280603754166060840152603854608084015260395416910152565b612f1773ffffffffffffffffffffffffffffffffffffffff60325416612f11612e92565b906140fa565b509283919280948082115f14612f3357810390811161037f5790565b50505f90565b67ffffffffffffffff811161233057601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b61301c73ffffffffffffffffffffffffffffffffffffffff60325416612f97612e92565b5f612fe960c08320604051602081019182526002604082015260408152612fbd816123a5565b5190206040805130602082019081529181019290925290612fe18160608101610f57565b519020614fe5565b604051809581927f7784c68500000000000000000000000000000000000000000000000000000000835260048301613dd4565b0381855afa9081156103f55761304061304792611c3b955f9161304f575b50613e0f565b51926140fa565b5050916149bb565b61306b91503d805f833e61306381836123c1565b810190613d5a565b5f61303a565b6130c361308761307f612f73565b6128166129d6565b604051907f07a2d13a00000000000000000000000000000000000000000000000000000000825281806020948593600483019190602083019252565b038173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f9161317d575b5061310c6105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291908390839060249082905afa9182156103f557611c3b935f9361315e575b505061246b565b613175929350803d1061077b5761076c81836123c1565b905f80613157565b6131949150823d841161077b5761076c81836123c1565b5f6130ea565b6004602073ffffffffffffffffffffffffffffffffffffffff6131bb6135fd565b16604051928380927f111e3c080000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f91612a30575090565b365f80375f80368173d377919fa87120584b21279a491f82d5265a139c5af43d5f803e15613225573d5ff35b3d5ffd5b613231613071565b6002810180911161037f57600490602073ffffffffffffffffffffffffffffffffffffffff60015416604051938480927f01e1d1140000000000000000000000000000000000000000000000000000000082525afa9182156103f5575f9261329857501090565b6132b291925060203d60201161077b5761076c81836123c1565b1190565b51906fffffffffffffffffffffffffffffffff8216820361001557565b73ffffffffffffffffffffffffffffffffffffffff6032541660606033546044604051809481937f93c5206200000000000000000000000000000000000000000000000000000000835260048301523060248301525afa9081156103f5575f91613353575b505190613350613346612eed565b90509291856149bb565b91565b90506060813d6060116133c0575b8161336e606093836123c1565b8101031261001557604051906060820182811067ffffffffffffffff821117612330576133b5916040918252805184526133aa602082016132b6565b6020850152016132b6565b60408201525f613338565b3d9150613361565b908160209103126100155751611c3b816103fa565b9081602091031261001557611c3b906132b6565b6040517f7535d24600000000000000000000000000000000000000000000000000000000815260209073d4fa2d31b7968e448877f69a96de69f5de8cd23e908281600481855afa9081156103f5575f916135e0575b506040517f38d52e0f0000000000000000000000000000000000000000000000000000000081528381600481865afa9081156103f55773ffffffffffffffffffffffffffffffffffffffff9285926134f2925f916135b3575b506040519485809481937f6fb07f960000000000000000000000000000000000000000000000000000000083526004830191909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b0392165afa80156103f5576135589284925f92613584575b5060405180809581947fc6e6f592000000000000000000000000000000000000000000000000000000008352600483019190916fffffffffffffffffffffffffffffffff6020820193169052565b03915afa9182156103f5575f9261356e57505090565b611c3b9250803d1061077b5761076c81836123c1565b6135a5919250833d85116135ac575b61359d81836123c1565b8101906133dd565b905f61350a565b503d613593565b6135d39150843d86116135d9575b6135cb81836123c1565b8101906133c8565b5f61349f565b503d6135c1565b6135f79150833d85116135d9576135cb81836123c1565b5f613446565b73ffffffffffffffffffffffffffffffffffffffff600460208260325416604051928380927ff5efbb4f0000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f9161365957501690565b613672915060203d6020116135d9576135cb81836123c1565b1690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b81156136ad570490565b613676565b906136bd81836149de565b918115613718576127109082821115613706577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b634e487b715f5260116020526024601cfd5b505061271091500490565b9161372e82846149de565b929093841561379c578483111561378f5790829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b8215600302601118614a10565b505090611c3b92506136a3565b5f809160208151910173d377919fa87120584b21279a491f82d5265a139c5af43d15613805573d906137da82612f39565b916137e860405193846123c1565b82523d5f602084013e5b156137fa5790565b6040513d90815f823efd5b6060906137f2565b9190826040910312610015576020825192015190565b61386e61385f6040517f2606a10b000000000000000000000000000000000000000000000000000000006020820152600481526105178161236d565b6020808251830101910161380d565b9091565b909181151580613ada575b80613ad1575b80613ac8575b613921575b5050506138b26105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290602090829060249082905afa80156103f5576111c4915f91613902575b5061492f565b61391b915060203d60201161077b5761076c81836123c1565b5f6138fc565b6139ba61394661059460015473ffffffffffffffffffffffffffffffffffffffff1690565b92613966603a5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152946020928390879081906024820190565b0381885afa9586156103f5575f96613aa9575b50856139dc575b50505061388e565b6139ea839185600494613723565b94604051928380927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa9182156103f5575f92613a8c575b505080821115613a8457613a389161243a565b80821115613a7b57613a499161243a565b905b808211613a73575b5080613a64575b80808080806139d4565b613a6d90614bac565b5f613a5a565b90505f613a53565b50505f90613a4b565b50505f613a38565b613aa29250803d1061077b5761076c81836123c1565b5f80613a25565b613ac1919650833d851161077b5761076c81836123c1565b945f6139cd565b50801515613889565b50821515613883565b5073ffffffffffffffffffffffffffffffffffffffff613b0f603a5473ffffffffffffffffffffffffffffffffffffffff1690565b16151561387d565b15613b1e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f2173656c660000000000000000000000000000000000000000000000000000006044820152fd5b6111c4303314613b17565b8015613cde576040517f0a28a47700000000000000000000000000000000000000000000000000000000815280613bc8602093600483019190602083019252565b0390828173d4fa2d31b7968e448877f69a96de69f5de8cd23e9381855afa80156103f557613c13915f91613d25575b50613c006129d6565b818110613d00575b808218908211021890565b6040517fd905777e000000000000000000000000000000000000000000000000000000008152306004820152908382602481865afa9081156103f557613c66925f92613ce1575b50808218908211021890565b9081613c7157505050565b6040517fba0876520000000000000000000000000000000000000000000000000000000081526004810192909252306024830181905260448301528290829060649082905f905af180156103f557613cc8575b5050565b81613cde92903d1061077b5761076c81836123c1565b50565b613cf9919250853d871161077b5761076c81836123c1565b905f613c5a565b613d12613d0d828461243a565b614d96565b15613c085750613d206129d6565b613c08565b613d3c9150843d861161077b5761076c81836123c1565b5f613bf7565b67ffffffffffffffff81116123305760051b60200190565b60209081818403126100155780519067ffffffffffffffff821161001557019180601f84011215610015578251613d9081613d42565b93613d9e60405195866123c1565b818552838086019260051b820101928311610015578301905b828210613dc5575050505090565b81518152908301908301613db7565b60209060206040818301928281528551809452019301915f5b828110613dfb575050505090565b835185529381019392810192600101613ded565b805115613e1c5760200190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b9190613ea7610f5791604051602081019182526002604082015260408152613e70816123a5565b5190206040519283916020830195866020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b519020906001820180921161037f57613f0e5f91613ed973ffffffffffffffffffffffffffffffffffffffff94614fe5565b6040519485809481937f7784c68500000000000000000000000000000000000000000000000000000000835260048301613dd4565b0392165afa80156103f557613f30613f4691611c3b935f9161304f5750613e0f565b516fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1690565b908160e0910312610015576040519060e0820182811067ffffffffffffffff82111761233057613ff19160c091604052613f94816132b6565b8452613fa2602082016132b6565b6020850152613fb3604082016132b6565b6040850152613fc4606082016132b6565b6060850152613fd5608082016132b6565b6080850152613fe660a082016132b6565b60a0850152016132b6565b60c082015290565b61018060c06111c4939594614064846101a081019860a0908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015282606082015116606086015260808101516080860152015116910152565b80516fffffffffffffffffffffffffffffffff908116858401526020820151811660e086015260408201518116610100860152606082015181166101208601526080820151811661014086015260a08201511661016085015201516fffffffffffffffffffffffffffffffff16910152565b9190916fffffffffffffffffffffffffffffffff8080941691160191821161037f57565b60c082206040517f5c60e39a00000000000000000000000000000000000000000000000000000000815260048101919091529173ffffffffffffffffffffffffffffffffffffffff9160e0908490602490829086165afa9283156103f5575f9361448e575b50829061418b614185613f4660808501516fffffffffffffffffffffffffffffffff1690565b4261243a565b928315159081614455575b81614429575b50614229575b50516fffffffffffffffffffffffffffffffff16905060208201516fffffffffffffffffffffffffffffffff169261420a60606141f260408601516fffffffffffffffffffffffffffffffff1690565b9401516fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff928316948316938316921690565b61428d91816142576105946105946060602096015173ffffffffffffffffffffffffffffffffffffffff1690565b906040518095819482937f2a944b5500000000000000000000000000000000000000000000000000000000845260048401613ff9565b03915afa9081156103f557614315916142d9915f9161440a575b506142d360408601946142cd613f4687516fffffffffffffffffffffffffffffffff1690565b92615656565b9061569e565b916142ff6142e6846156b5565b82516fffffffffffffffffffffffffffffffff166140d6565b6fffffffffffffffffffffffffffffffff169052565b61435361433d614324836156b5565b84516fffffffffffffffffffffffffffffffff166140d6565b6fffffffffffffffffffffffffffffffff168352565b6fffffffffffffffffffffffffffffffff61438160a08401516fffffffffffffffffffffffffffffffff1690565b168061438f575b82906141a2565b6143a5670de0b6b3a764000091614403936144d6565b046142ff6142e66143fe6143d5846143d0613f4689516fffffffffffffffffffffffffffffffff1690565b61243a565b9360208701946143f8613f4687516fffffffffffffffffffffffffffffffff1690565b916156fc565b6156b5565b5f80614388565b614423915060203d60201161077b5761076c81836123c1565b5f6142a7565b905061444c606083015173ffffffffffffffffffffffffffffffffffffffff1690565b1615155f61419c565b90506fffffffffffffffffffffffffffffffff61448560408501516fffffffffffffffffffffffffffffffff1690565b16151590614196565b6144b191935060e03d60e0116144b8575b6144a981836123c1565b810190613f5b565b915f61415f565b503d61449f565b906127109182810292818404149015171561037f57565b8181029291811591840414171561037f57565b61450b61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b60405180917fbf86d69000000000000000000000000000000000000000000000000000000000825281600460209485935afa9081156103f5575f91614712575b50612c56576040517f5c975abb000000000000000000000000000000000000000000000000000000008152818160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f916146f5575b50612c56576145ad612f73565b906145b66129d6565b916145c96145c4848361246b565b61571e565b9182156146ec576145db6105946135fd565b8160405180927fcc718f76000000000000000000000000000000000000000000000000000000008252818061463760048201907fe1bb37f3f38496b3457796e7729ac8101c3fa82af647ce70ac30761a8520fe17602083019252565b03915afa9182156103f5575f926146cf575b505080156146c7575b61466c8161466661271061467494106129cf565b846144d6565b612710900490565b928282116146bc5781831190816146b2575b50806146a1575b614698575050505f90565b6132b29161243a565b506146ad610e4e613229565b61468d565b905015155f614686565b50906132b29161243a565b50600a614652565b6146e59250803d1061077b5761076c81836123c1565b5f80614649565b50915050151590565b61470c9150823d84116106195761060a81836123c1565b5f6145a0565b6147299150823d84116106195761060a81836123c1565b5f61454b565b1561473657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600460248201527f3c6d696e000000000000000000000000000000000000000000000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff83169283331490816148fc575b506147c7575b5050506111c461573c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114614842575b7fb45b0dd408214bf930dafc547364e44f4474bd439a3db3ae3edf0c60fa31a5b491506148266148218260415461246b565b604155565b60415460408051928352602083019190915290a25f80806147bc565b5060206148a49161486b61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b60405180809581947f07a2d13a000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b03915afa80156103f5577fb45b0dd408214bf930dafc547364e44f4474bd439a3db3ae3edf0c60fa31a5b4915f916148dd575b506147ef565b6148f6915060203d60201161077b5761076c81836123c1565b5f6148d7565b6149299150610e479073ffffffffffffffffffffffffffffffffffffffff165f52604060205260405f2090565b5f6147b6565b6004602073ffffffffffffffffffffffffffffffffffffffff60015416604051928380927fbf86d6900000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f9161499c575b50613cde57614994906151d9565b6111c4614ad1565b6149b5915060203d6020116106195761060a81836123c1565b5f614986565b91906001810180911161037f57620f4240820180921161037f57611c3b92615889565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183099102908180821091030391565b634e487b715f526020526024601cfd5b6040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91614ab2575b506111c457614a7e612f73565b614a866129d6565b810180821161037f57614a989061571e565b80821115613cc457810390811161037f57613cde90614d96565b614acb915060203d6020116106195761060a81836123c1565b5f614a71565b6040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91614b8d575b506111c457614b2f612f73565b614b376129d6565b90614b456145c4838361246b565b9182821115614b5c5750613cde91613d0d9161243a565b81831180614b84575b614b6f575b505050565b6128a5614b7f92613cde9461243a565b615924565b50801515614b65565b614ba6915060203d6020116106195761060a81836123c1565b5f614b22565b5f9073ffffffffffffffffffffffffffffffffffffffff80603a5416604051602081019182527fd2841a5d2692465040bd5e06a6f3b37483952c866e0f304dc0e03f76a1f8a0b4604082015260408152614c05816123a5565b51902080547fd2841a5d2692465040bd5e06a6f3b37483952c866e0f304dc0e03f76a1f8a0b291825491808611614c74575b85900390558390039055603a5460405192835216907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3565b945084614c37565b91610120919493610140840195614cda8560a073ffffffffffffffffffffffffffffffffffffffff80603454168352806035541660208401528060365416604084015280603754166060840152603854608084015260395416910152565b60c08501525f60e085015273ffffffffffffffffffffffffffffffffffffffff80921661010085015216910152565b91610120919493610140840195614d678560a073ffffffffffffffffffffffffffffffffffffffff80603454168352806035541660208401528060365416604084015280603754166060840152603854608084015260395416910152565b5f60c086015260e085015273ffffffffffffffffffffffffffffffffffffffff80921661010085015216910152565b8015612c5657614dbe61059460325473ffffffffffffffffffffffffffffffffffffffff1690565b803b15610015576040905f825180927f1e4711cf000000000000000000000000000000000000000000000000000000008252818381614e4c6004820160345473ffffffffffffffffffffffffffffffffffffffff908116825260355481166020830152603654811660408301526037548116606083015260385460808301526039541660a082015260c00190565b03925af180156103f557614fd2575b50614e78614e676132d3565b909491928186188287100290911890565b8015612d605780821891811191909102189283614e96575b50505090565b82908410614f4357614efe5f92614ec561059460325473ffffffffffffffffffffffffffffffffffffffff1690565b9083519485809481937fa0b16cc70000000000000000000000000000000000000000000000000000000083523090309060048501614d09565b03925af180156103f557614f18575b50505b5f8080614e90565b81614f3792903d10614f3c575b614f2f81836123c1565b81019061380d565b614f0d565b503d614f25565b5050614f6761059460325473ffffffffffffffffffffffffffffffffffffffff1690565b81805180927fa0b16cc7000000000000000000000000000000000000000000000000000000008252815f81614fa130308b60048501614c7c565b03925af180156103f557614fb7575b5050614f10565b81614fcd92903d10614f3c57614f2f81836123c1565b614fb0565b80610bba614fdf9261231c565b5f614e5b565b60405190614ff28261236d565b600182526020368184013761500682613e0f565b5290565b80158015615162575b613cde576040517fef8b30f700000000000000000000000000000000000000000000000000000000815280615052602093600483019190602083019252565b03828273d4fa2d31b7968e448877f69a96de69f5de8cd23e9281845afa9182156103f5575f92615143575b506040517fc63d75b600000000000000000000000000000000000000000000000000000000815230600482015282908481602481865afa9081156103f5575f91615126575b5080911161511e575b508115614b6a576040517f94bf804d000000000000000000000000000000000000000000000000000000008152600481019290925230602483015282908290815f81604481015b03925af1613cc8575050565b91505f6150cb565b61513d9150853d871161077b5761076c81836123c1565b5f6150c2565b61515b919250833d851161077b5761076c81836123c1565b905f61507d565b506040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f916151ba575b50615013565b6151d3915060203d6020116106195761060a81836123c1565b5f6151b4565b801580156155df575b613cde5760408051907fef8b30f7000000000000000000000000000000000000000000000000000000008252602092826152256004928383019190602083019252565b03848473d4fa2d31b7968e448877f69a96de69f5de8cd23e9281845afa9384156103f5575f946155c0575b5082517fc63d75b6000000000000000000000000000000000000000000000000000000008152308382019081528591908790829081906020010381865afa9081156103f5575f916155a3575b5080911161559b575b5083156154fc576152b761307f612f73565b9280517f07a2d13a00000000000000000000000000000000000000000000000000000000908181528781806152f3898983019190602083019252565b0381875afa9081156103f5575f9161557e575b508251957fb3d7f6b90000000000000000000000000000000000000000000000000000000087528887806153418b8a83019190602083019252565b0381885afa9283156103f557888a9261537d995f96615559575b50906153669161246b565b908551988992839283528983019190602083019252565b0381875afa80156103f5578161539c918a985f9161553c575b5061243a565b918281116153ec575b505090517f94bf804d00000000000000000000000000000000000000000000000000000000815292830194855250306020850152909283919082905f908290604001615112565b90919295506154126105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b88875180927f70a082310000000000000000000000000000000000000000000000000000000082528180615465308c830191909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b03915afa80156103f5578693615481925f92615524575061246b565b92886154a561059460015473ffffffffffffffffffffffffffffffffffffffff1690565b8851948580927f01e1d1140000000000000000000000000000000000000000000000000000000082525afa9081156103f5576154ed935f92615503575b50612816919261243a565b116154fc5784925f80806153a5565b5050505050565b612816925061551e908b3d8d1161077b5761076c81836123c1565b916154e2565b6127f39192508b3d8d1161077b5761076c81836123c1565b6155539150893d8b1161077b5761076c81836123c1565b5f615396565b6153669291965061557690853d871161077b5761076c81836123c1565b95909161535b565b6155959150883d8a1161077b5761076c81836123c1565b5f615306565b93505f6152a5565b6155ba9150873d891161077b5761076c81836123c1565b5f61529c565b6155d8919450853d871161077b5761076c81836123c1565b925f615250565b506040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91615637575b506151e2565b615650915060203d6020116106195761060a81836123c1565b5f615631565b90615660916144d6565b671bc16d674ec8000061567382806144d6565b046729a2241af62c000061568783836144d6565b0490820180921161037f57810180911161037f5790565b670de0b6b3a7640000916156b1916144d6565b0490565b6fffffffffffffffffffffffffffffffff908181116156d2571690565b60046040517f6acc9c8f000000000000000000000000000000000000000000000000000000008152fd5b91620f4240810180911161037f576001820180921161037f57611c3b92615889565b6157336127109161572d61319a565b906144d6565b046128a56159f9565b61575d6105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526020918290829060249082905afa9081156103f5575f9161586c575b508015613cc4576157b5906151d9565b6040517f5c975abb000000000000000000000000000000000000000000000000000000008152818160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9182156103f5575f9261584f575b50506111c45761581361319a565b156111c457615820612f73565b6158286129d6565b906158366145c4838361246b565b9181831115614b6a576128a5614b7f92613cde9461243a565b6158659250803d106106195761060a81836123c1565b5f80615805565b6158839150823d841161077b5761076c81836123c1565b5f6157a5565b906136a3916144d6565b905f9073ffffffffffffffffffffffffffffffffffffffff61016094610140926159048660a073ffffffffffffffffffffffffffffffffffffffff80603454168352806035541660208401528060365416604084015280603754166060840152603854608084015260395416910152565b60c08601528360e086015216610100840152806101208401528201520190565b801580156159eb575b612c565761595361059460325473ffffffffffffffffffffffffffffffffffffffff1690565b6040805180927f370160a0000000000000000000000000000000000000000000000000000000008252815f8161598d308960048401615893565b03925af190816159cd575b50611c3b576040519081527fbe96638bde19b2e58565dd987769a2932fcbbd362f2ea7a0201d9fe524e799ba90602090a15f90565b6159e59060403d604011614f3c57614f2f81836123c1565b50615998565b506159f4613229565b61592d565b603a5473ffffffffffffffffffffffffffffffffffffffff168015615cbc57615a236105946135fd565b6040517fcc718f760000000000000000000000000000000000000000000000000000000081527f6f17d12aaeef2cb47b81cd9a8d7ae8c8b3af200ada02c2e61aecbb6b4cbb86246004820152602092918390829060249082905afa9081156103f5575f91615c9f575b508015612da557615b0a9083615aba61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90951660048601529392839081906024820190565b0381865afa9182156103f5575f92615c80575b50604051907f18160ddd0000000000000000000000000000000000000000000000000000000082528482600481875afa9182156103f55760049486915f94615c61575b50604051958680927f01e1d1140000000000000000000000000000000000000000000000000000000082525afa9384156103f5575f94615c42575b5081158015615c3a575b8015615c32575b612d6057615bca615bc5615bcf93615c07968896613723565b6144bf565b6136a3565b604051809381927fc6e6f592000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b038173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9182156103f5575f9261356e57505090565b508215615bac565b508315615ba5565b615c5a919450853d871161077b5761076c81836123c1565b925f615b9b565b615c79919450823d841161077b5761076c81836123c1565b925f615b60565b615c98919250843d861161077b5761076c81836123c1565b905f615b1d565b615cb69150833d851161077b5761076c81836123c1565b5f615a8c565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9056fea164736f6c6343000816000a","sourceMap":"3310:37370:32:-:0;;;;;;;3147:66:1;3310:37370:32;;;;;;;;;7894:76:1;;-1:-1:-1;;;;;;;;;;;;3310:37370:32;;;7983:34:1;7979:146;;-1:-1:-1;3310:37370:32;;;;;;;;;7979:146:1;-1:-1:-1;;;;;;3310:37370:32;;;;;;;;;;;;;8085:29:1;;3310:37370:32;;8085:29:1;7979:146;;;;;7894:76;-1:-1:-1;;;7936:23:1;;;;;3310:37370:32;;;","linkReferences":{}},"deployedBytecode":{"object":"60806040526004361015610019575b34156131f9575b5f80fd5b5f3560e01c8063020dfdc71461029457806304bd46291461028f57806323b872dd1461028a5780632606a10b146102855780632b832dbc146102805780633d6cb575146101d657806341b3d1851461027b5780634251c3541461027657806346aa2f121461027157806349317f1d1461026c5780634b4dcf8214610267578063503160d91461026257806359ddbab21461025d5780635d265d3f146102585780636e553f65146102535780636ed71ede1461024e5780637b9e68f21461024957806388bdedb7146102445780638fcc9cfb1461023f57806394bf804d1461023a57806395d89b41146102355780639d7fb70c146102305780639f40a7b31461022b578063a318c1a414610226578063a465375714610221578063a9059cbb1461021c578063a9b89c0714610217578063b460af9414610212578063ba0876521461020d578063c1590cd714610208578063c7cedf1e14610203578063cb6d71bc146101fe578063d19a3bb8146101f9578063daf3dd49146101f4578063df69b22a146101ef578063e61582b5146101ea578063efb5f911146101e5578063f51b81bf146101e0578063f7f6ba53146101db5763fde813a80361000e575b6108c6565b61229e565b61218a565b612139565b612101565b611fac565b611f71565b611f25565b611ed9565b611db9565b611d34565b611cb8565b611c3e565b611bbc565b611aad565b611914565b611895565b611808565b611775565b6116fa565b6113d1565b6112f6565b61128a565b6111c6565b611127565b610da3565b610d18565b610c6c565b610c32565b610bc6565b6109c5565b610980565b610948565b61090d565b6107a6565b61065f565b610464565b610418565b34610015575f60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043573ffffffffffffffffffffffffffffffffffffffff60015416803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f5576103e2575b506041548082116103845781810390811161037f5760418190556040805192835260208301919091527f62b761b1158418079bd8028d2057ba8c8644d3ef7f5000aaaf2d7a1d67f7d5b49190819081015b0390a180f35b61240d565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f2166656e636500000000000000000000000000000000000000000000000000006044820152fd5b6103ed91925061231c565b5f905f610328565b612402565b73ffffffffffffffffffffffffffffffffffffffff81160361001557565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576104526004356103fa565b602061045c612478565b604051908152f35b346100155760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043561049f816103fa565b6024356104ab816103fa565b60443561052a61051c6040516020957f23b872dd000000000000000000000000000000000000000000000000000000008783015273ffffffffffffffffffffffffffffffffffffffff809116958660248401521660448201528360648201526064815261051781612351565b6137a9565b848082518301019101612456565b9182918261064b575b5081610620575b508061056e575b61055d9250610561575b60405190151581529081906020820190565b0390f35b610569614a20565b61054b565b506004826105ad61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051928380927fbf86d6900000000000000000000000000000000000000000000000000000000082525afa9081156103f55761055d935f926105f3575b505015610541565b6106129250803d10610619575b61060a81836123c1565b810190612456565b5f806105eb565b503d610600565b9050610644610594603a5473ffffffffffffffffffffffffffffffffffffffff1690565b145f61053a565b151591505f610533565b5f91031261001557565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576106af61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b604051907f18160ddd0000000000000000000000000000000000000000000000000000000082526020908183600481845afa9283156103f5575f93610782575b5081600491604051928380927f01e1d1140000000000000000000000000000000000000000000000000000000082525afa9182156103f5575f92610755575b505061074461073b613823565b93909284613872565b604080519182526020820192909252f35b6107749250803d1061077b575b61076c81836123c1565b810190612447565b5f8061072e565b503d610762565b600491935061079e8391823d841161077b5761076c81836123c1565b9391506106ef565b34610015575f60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576004356107e2816103fa565b73ffffffffffffffffffffffffffffffffffffffff8060015416803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f5576108b3575b50603a5491818316610015571690811561001557817fc3212a26ea3792ed00e630d63eb8ec2a9295974fe90e94ff25a8f70987fcdeeb927fffffffffffffffffffffffff00000000000000000000000000000000000000006040931617603a558151905f82526020820152a180f35b6108be91935061231c565b5f915f610844565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557610900303314613b17565b61090b600435613b87565b005b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576020603d54604051908152f35b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c6129d6565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c6004356109c0816103fa565b612a49565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576109fb613b7c565b610a03612e92565b610a2561059460325473ffffffffffffffffffffffffffffffffffffffff1690565b803b15610015576040517f1e4711cf000000000000000000000000000000000000000000000000000000008152905f908290818381610a678860048301611162565b03925af180156103f557610bad575b50610a9961059460015473ffffffffffffffffffffffffffffffffffffffff1690565b60405180917fbf86d69000000000000000000000000000000000000000000000000000000000825281600460209485935afa9081156103f5575f91610b90575b5015610afb575b61055d610aeb613071565b6040519081529081906020820190565b610b1c6105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152908290829060249082905afa9081156103f557610b6d925f92610b73575b505061500a565b80610ae0565b610b899250803d1061077b5761076c81836123c1565b8280610b66565b610ba79150823d84116106195761060a81836123c1565b82610ad9565b80610bba610bc09261231c565b80610655565b80610a76565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff600435610c16816103fa565b165f526040602052602060ff60405f2054166040519015158152f35b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155761090b303314613b17565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576080610ca4612eed565b91604051938452602084015260408301526060820152f35b91908251928382525f5b848110610d045750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201610cc6565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557610d4e6144e9565b604051907f440368a300000000000000000000000000000000000000000000000000000000602083015260048252610d858261236d565b61055d60405192839215158352604060208401526040830190610cbc565b34610015576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043560243591610de3836103fa565b81821580611120575b61108a575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ffd575b610e52610e4e610e478673ffffffffffffffffffffffffffffffffffffffff165f52603f60205260405f2090565b5460ff1690565b1590565b93848015610fde575b610e6490613b17565b610e8661059460015473ffffffffffffffffffffffffffffffffffffffff1690565b83517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152906020908190839060249082905afa9384156103f55761055d97610f9795610f90945f91610fc1575b50159081610fb9575b50610fa5575b5084517f6e553f6500000000000000000000000000000000000000000000000000000000828201526024810187905273ffffffffffffffffffffffffffffffffffffffff84166044820152610f839061051781606481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826123c1565b8051810182019101612447565b8094614794565b519081529081906020820190565b610fb390603d54111561472f565b5f610eff565b90505f610ef9565b610fd89150843d861161077b5761076c81836123c1565b5f610ef0565b503373ffffffffffffffffffffffffffffffffffffffff821614610e5b565b5061101f6105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b81517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290602090829060249082905afa9081156103f5575f9161106b575b50610e19565b611084915060203d60201161077b5761076c81836123c1565b5f611065565b506110ad61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b6020825180927fb3d7f6b900000000000000000000000000000000000000000000000000000000825281806110e960048201905f602083019252565b03915afa9081156103f5575f91611101575b50610df1565b61111a915060203d60201161077b5761076c81836123c1565b5f6110fb565b505f610dec565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576020603354604051908152f35b6111c49092919260c081019360a0908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015282606082015116606086015260808101516080860152015116910152565b565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015575f60a060405161120381612335565b828152826020820152826040820152826060820152826080820152015260c061122a612e92565b611288604051809260a0908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015282606082015116606086015260808101516080860152015116910152565bf35b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff6004356112da816103fa565b165f52603f602052602060ff60405f2054166040519015158152f35b34610015575f60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043573ffffffffffffffffffffffffffffffffffffffff60015416803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f5576113bd575b506020817f96a008f96f1c0ab9fa3d9ddd43cdfc614848c4d054d51f43662ed900e9d094c892603d55604051908152a180f35b6113c891925061231c565b5f90602061138a565b34610015576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155760043560243591611411836103fa565b5f82611663575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146115d6575b61146e610e4e610e478673ffffffffffffffffffffffffffffffffffffffff165f52603f60205260405f2090565b938480156115b7575b61148090613b17565b6114a261059460015473ffffffffffffffffffffffffffffffffffffffff1690565b83517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152906020908190839060249082905afa9384156103f55761055d97610f9795611577945f9161159a575b50159081611592575b5061157e575b5084517f94bf804d00000000000000000000000000000000000000000000000000000000828201526024810187905273ffffffffffffffffffffffffffffffffffffffff84166044820152610f83906105178160648101610f57565b9384614794565b61158c90603d54111561472f565b5f61151b565b90505f611515565b6115b19150843d861161077b5761076c81836123c1565b5f61150c565b503373ffffffffffffffffffffffffffffffffffffffff821614611477565b506115f86105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b81517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290602090829060249082905afa9081156103f5575f91611644575b50611440565b61165d915060203d60201161077b5761076c81836123c1565b5f61163e565b5061168661059460015473ffffffffffffffffffffffffffffffffffffffff1690565b6020825180927fb3d7f6b900000000000000000000000000000000000000000000000000000000825281806116c388600483019190602083019252565b03915afa9081156103f5575f916116db575b50611418565b6116f4915060203d60201161077b5761076c81836123c1565b5f6116d5565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155761055d6040516117378161236d565b600481527f55534433000000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190610cbc565b346100155760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576117af303314613b17565b61090b60043561492f565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc608091011261001557600435906024356117f4816103fa565b90604435611801816103fa565b9060643590565b3461001557602061045c611887610f57610517611824366117ba565b6040517f9f40a7b3000000000000000000000000000000000000000000000000000000008a820152602481019490945273ffffffffffffffffffffffffffffffffffffffff928316604485015291166064830152608482015291829060a4820190565b828082518301019101612447565b3461001557602061045c611887610f576105176118b1366117ba565b6040517fa318c1a4000000000000000000000000000000000000000000000000000000008a820152602481019490945273ffffffffffffffffffffffffffffffffffffffff928316604485015291166064830152608482015291829060a4820190565b34610015575f807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff8060015416803b15610015575f602491604051928380927fd43fdcf70000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f557611a99575b5060206004916119b36135fd565b16604051928380927f76e66a1c0000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f91611a7a575b506127108111610015576103797f617d69aa6f8f8f7158e168208ffd102c878214b34e8510746322af83f775aab7917fd2841a5d2692465040bd5e06a6f3b37483952c866e0f304dc0e03f76a1f8a0b97fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff8154168260201b179055604051918291829190602083019252565b611a93915060203d60201161077b5761076c81836123c1565b5f6119ee565b611aa491925061231c565b5f9060206119a5565b346100155760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557600435611ae8816103fa565b602435611b58611b4a60405173ffffffffffffffffffffffffffffffffffffffff6020957fa9059cbb00000000000000000000000000000000000000000000000000000000878401521660248201528360448201526044815261051781612389565b838082518301019101612456565b80918192611bb2575b5080611b88575b8061056e5761055d92506105615760405190151581529081906020820190565b50611bab610594603a5473ffffffffffffffffffffffffffffffffffffffff1690565b3314611b68565b905015155f611b61565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c612f73565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126100155760043590602435611c2e816103fa565b90604435611c3b816103fa565b90565b3461001557602061045c611887611c5436611bf4565b604051927fa318c1a40000000000000000000000000000000000000000000000000000000087850152602484015273ffffffffffffffffffffffffffffffffffffffff80921660448401521660648201525f60848201526084815261051781612335565b3461001557602061045c611887611cce36611bf4565b604051927f9f40a7b30000000000000000000000000000000000000000000000000000000087850152602484015273ffffffffffffffffffffffffffffffffffffffff809216604484015216606482015261271060848201526084815261051781612335565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c613071565b8015150361001557565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc604091011261001557600435611dac816103fa565b90602435611c3b81611d6c565b3461001557611dc736611d76565b6001545f9273ffffffffffffffffffffffffffffffffffffffff809216803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f557611e9f575b507f62374b3ccb739da5991edc41e2ea922bab2b874148694015005a9b2691df5f52916020911692835f52603f8252611e938160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a280f35b602091945091611ecf7f62374b3ccb739da5991edc41e2ea922bab2b874148694015005a9b2691df5f529361231c565b5f94915091611e2c565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602060405173d4fa2d31b7968e448877f69a96de69f5de8cd23e8152f35b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602060405173d377919fa87120584b21279a491f82d5265a139c8152f35b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610015576020604154604051908152f35b34610015575f60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff60015416803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f5576120f0575b50600435158015906120e1575b156120835761207f61205b36612f39565b61206860405191826123c1565b368152365f60208301375f602036830101526137a9565b5080f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f216c6f73730000000000000000000000000000000000000000000000000000006044820152fd5b506120ea613229565b1561204a565b6120fa915061231c565b5f8061203d565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602061045c61319a565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602073ffffffffffffffffffffffffffffffffffffffff60325416604051908152f35b346100155761219836611d76565b6001545f9273ffffffffffffffffffffffffffffffffffffffff809216803b15610015575f602491604051928380927f48e4a6490000000000000000000000000000000000000000000000000000000082523360048301525afa80156103f557612264575b507fffd73fc43ae6addb25c141d1108d251a943fb8be0d967a6a8fe8b436d564d921916020911692835f5260408252611e938160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6020919450916122947fffd73fc43ae6addb25c141d1108d251a943fb8be0d967a6a8fe8b436d564d9219361231c565b5f949150916121fd565b34610015575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602073ffffffffffffffffffffffffffffffffffffffff603a5416604051908152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b67ffffffffffffffff811161233057604052565b6122ef565b60c0810190811067ffffffffffffffff82111761233057604052565b60a0810190811067ffffffffffffffff82111761233057604052565b6040810190811067ffffffffffffffff82111761233057604052565b6080810190811067ffffffffffffffff82111761233057604052565b6060810190811067ffffffffffffffff82111761233057604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761233057604052565b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9190820391821161037f57565b90816020910312610015575190565b908160209103126100155751611c3b81611d6c565b9190820180921161037f57565b6124996105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048083019190915292602092908390839060249082905afa9182156103f5575f926129b0575b5061250b61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b8151927f01e1d11400000000000000000000000000000000000000000000000000000000845284848781855afa9384156103f5575f94612991575b5061254f613229565b6129875761255b6132d3565b9291505f8551917f5c975abb00000000000000000000000000000000000000000000000000000000835273d4fa2d31b7968e448877f69a96de69f5de8cd23e9489848c81895afa80156103f5578a945f9161296a575b50156127fa575050506125f8925f905b865180809681947f07a2d13a0000000000000000000000000000000000000000000000000000000083528d83019190602083019252565b03915afa9182156103f55787928792612618925f926127db575b5061246b565b928451928380927fbf86d6900000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f916127be575b506127b657604154810390811115029361266d6105946135fd565b908251907fcc718f7600000000000000000000000000000000000000000000000000000000928383528683806126c9858201907f3412c9f85ed46ce3ec8f65a167e2554559c90769888f1561e7879ccce085f6ee602083019252565b0381845afa9384156103f5576127189588945f96612797575b505180968194829383528201907f79742dc31db595cf1ca3dc9e1e2303db56ca7a50d0795409429542539d8e3a9a602083019252565b03915afa9384156103f557612764946127579361274b925f9261277a575b505080612710809111612772575b50846136b2565b90818082119118021890565b8103908111159190820290565b829150808093109118021890565b90505f612744565b6127909250803d1061077b5761076c81836123c1565b5f80612736565b6127af919650853d871161077b5761076c81836123c1565b945f6126e2565b935050505090565b6127d59150853d87116106195761060a81836123c1565b5f612652565b6127f3919250843d861161077b5761076c81836123c1565b905f612612565b9061281661281c9261280a6129d6565b92818118908211021890565b9061246b565b938461282d575b6125f894506125c1565b86517fd905777e00000000000000000000000000000000000000000000000000000000808252308c83019081529194509192508990849081906020010381855afa80156103f55789935f9161294d575b501590816128b7575b506125f894901561289957505f90612823565b6128b1906128a56133f1565b90818082109118021890565b90612823565b61290e9391506128df61059460325473ffffffffffffffffffffffffffffffffffffffff1690565b908851948592839283528d830191909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b0381845afa9384156103f5576125f89489935f91612930575b50159094612886565b6129479150843d861161077b5761076c81836123c1565b5f612927565b6129649150843d861161077b5761076c81836123c1565b5f61287d565b6129819150853d87116106195761060a81836123c1565b5f6125b1565b5050505050505f90565b6129a9919450853d871161077b5761076c81836123c1565b925f612546565b6129c8919250833d851161077b5761076c81836123c1565b905f6124e8565b1561001557565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91612a30575090565b611c3b915060203d60201161077b5761076c81836123c1565b612a77610e4e610e478373ffffffffffffffffffffffffffffffffffffffff165f52603f60205260405f2090565b80612e1b575b612c5657612aad81612aa460325473ffffffffffffffffffffffffffffffffffffffff1690565b60335490613e49565b612c5657612abc6105946135fd565b6040517fcc718f760000000000000000000000000000000000000000000000000000000081527f4bba860c0c28b1a4ae0214c01f08e53b00bfe2e087690d7a04d73a15360ec6a76004820152906020908190839060249082905afa9182156103f5575f92612dfc575b508115612df557612b57610e478473ffffffffffffffffffffffffffffffffffffffff165f52603f60205260405f2090565b8015612dcc575b612da557612b8461059460015473ffffffffffffffffffffffffffffffffffffffff1690565b916040517f01e1d1140000000000000000000000000000000000000000000000000000000081528281600481875afa9081156103f5575f91612d88575b5080821115612d6057612bd39161243a565b92604051917fc6e6f592000000000000000000000000000000000000000000000000000000008352808380612c1088600483019190602083019252565b0381875afa9283156103f5575f93612d69575b508215612d6057603d5491818315918215612cde575b5050612cd757818510928315612c5b575b5050509050612c565790565b505f90565b819350612c9c929460405180809581947fb3d7f6b9000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b03915afa9182156103f5575f92612cba575b505010805f8080612c4a565b612cd09250803d1061077b5761076c81836123c1565b5f80612cae565b5050505090565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff919091166004820152915081602481885afa9081156103f5575f91612d43575b501515815f612c39565b612d5a9150823d841161077b5761076c81836123c1565b5f612d39565b50505050505f90565b81612d819294503d851161077b5761076c81836123c1565b915f612c23565b612d9f9150833d851161077b5761076c81836123c1565b5f612bc1565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214612b5e565b5050505f90565b81612e149293503d841161077b5761076c81836123c1565b905f612b25565b506040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91612e73575b50612a7d565b612e8c915060203d6020116106195761060a81836123c1565b5f612e6d565b60405190612e9f82612335565b8160a073ffffffffffffffffffffffffffffffffffffffff80603454168352806035541660208401528060365416604084015280603754166060840152603854608084015260395416910152565b612f1773ffffffffffffffffffffffffffffffffffffffff60325416612f11612e92565b906140fa565b509283919280948082115f14612f3357810390811161037f5790565b50505f90565b67ffffffffffffffff811161233057601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b61301c73ffffffffffffffffffffffffffffffffffffffff60325416612f97612e92565b5f612fe960c08320604051602081019182526002604082015260408152612fbd816123a5565b5190206040805130602082019081529181019290925290612fe18160608101610f57565b519020614fe5565b604051809581927f7784c68500000000000000000000000000000000000000000000000000000000835260048301613dd4565b0381855afa9081156103f55761304061304792611c3b955f9161304f575b50613e0f565b51926140fa565b5050916149bb565b61306b91503d805f833e61306381836123c1565b810190613d5a565b5f61303a565b6130c361308761307f612f73565b6128166129d6565b604051907f07a2d13a00000000000000000000000000000000000000000000000000000000825281806020948593600483019190602083019252565b038173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f9161317d575b5061310c6105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291908390839060249082905afa9182156103f557611c3b935f9361315e575b505061246b565b613175929350803d1061077b5761076c81836123c1565b905f80613157565b6131949150823d841161077b5761076c81836123c1565b5f6130ea565b6004602073ffffffffffffffffffffffffffffffffffffffff6131bb6135fd565b16604051928380927f111e3c080000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f91612a30575090565b365f80375f80368173d377919fa87120584b21279a491f82d5265a139c5af43d5f803e15613225573d5ff35b3d5ffd5b613231613071565b6002810180911161037f57600490602073ffffffffffffffffffffffffffffffffffffffff60015416604051938480927f01e1d1140000000000000000000000000000000000000000000000000000000082525afa9182156103f5575f9261329857501090565b6132b291925060203d60201161077b5761076c81836123c1565b1190565b51906fffffffffffffffffffffffffffffffff8216820361001557565b73ffffffffffffffffffffffffffffffffffffffff6032541660606033546044604051809481937f93c5206200000000000000000000000000000000000000000000000000000000835260048301523060248301525afa9081156103f5575f91613353575b505190613350613346612eed565b90509291856149bb565b91565b90506060813d6060116133c0575b8161336e606093836123c1565b8101031261001557604051906060820182811067ffffffffffffffff821117612330576133b5916040918252805184526133aa602082016132b6565b6020850152016132b6565b60408201525f613338565b3d9150613361565b908160209103126100155751611c3b816103fa565b9081602091031261001557611c3b906132b6565b6040517f7535d24600000000000000000000000000000000000000000000000000000000815260209073d4fa2d31b7968e448877f69a96de69f5de8cd23e908281600481855afa9081156103f5575f916135e0575b506040517f38d52e0f0000000000000000000000000000000000000000000000000000000081528381600481865afa9081156103f55773ffffffffffffffffffffffffffffffffffffffff9285926134f2925f916135b3575b506040519485809481937f6fb07f960000000000000000000000000000000000000000000000000000000083526004830191909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b0392165afa80156103f5576135589284925f92613584575b5060405180809581947fc6e6f592000000000000000000000000000000000000000000000000000000008352600483019190916fffffffffffffffffffffffffffffffff6020820193169052565b03915afa9182156103f5575f9261356e57505090565b611c3b9250803d1061077b5761076c81836123c1565b6135a5919250833d85116135ac575b61359d81836123c1565b8101906133dd565b905f61350a565b503d613593565b6135d39150843d86116135d9575b6135cb81836123c1565b8101906133c8565b5f61349f565b503d6135c1565b6135f79150833d85116135d9576135cb81836123c1565b5f613446565b73ffffffffffffffffffffffffffffffffffffffff600460208260325416604051928380927ff5efbb4f0000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f9161365957501690565b613672915060203d6020116135d9576135cb81836123c1565b1690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b81156136ad570490565b613676565b906136bd81836149de565b918115613718576127109082821115613706577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b634e487b715f5260116020526024601cfd5b505061271091500490565b9161372e82846149de565b929093841561379c578483111561378f5790829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b8215600302601118614a10565b505090611c3b92506136a3565b5f809160208151910173d377919fa87120584b21279a491f82d5265a139c5af43d15613805573d906137da82612f39565b916137e860405193846123c1565b82523d5f602084013e5b156137fa5790565b6040513d90815f823efd5b6060906137f2565b9190826040910312610015576020825192015190565b61386e61385f6040517f2606a10b000000000000000000000000000000000000000000000000000000006020820152600481526105178161236d565b6020808251830101910161380d565b9091565b909181151580613ada575b80613ad1575b80613ac8575b613921575b5050506138b26105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290602090829060249082905afa80156103f5576111c4915f91613902575b5061492f565b61391b915060203d60201161077b5761076c81836123c1565b5f6138fc565b6139ba61394661059460015473ffffffffffffffffffffffffffffffffffffffff1690565b92613966603a5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152946020928390879081906024820190565b0381885afa9586156103f5575f96613aa9575b50856139dc575b50505061388e565b6139ea839185600494613723565b94604051928380927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa9182156103f5575f92613a8c575b505080821115613a8457613a389161243a565b80821115613a7b57613a499161243a565b905b808211613a73575b5080613a64575b80808080806139d4565b613a6d90614bac565b5f613a5a565b90505f613a53565b50505f90613a4b565b50505f613a38565b613aa29250803d1061077b5761076c81836123c1565b5f80613a25565b613ac1919650833d851161077b5761076c81836123c1565b945f6139cd565b50801515613889565b50821515613883565b5073ffffffffffffffffffffffffffffffffffffffff613b0f603a5473ffffffffffffffffffffffffffffffffffffffff1690565b16151561387d565b15613b1e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f2173656c660000000000000000000000000000000000000000000000000000006044820152fd5b6111c4303314613b17565b8015613cde576040517f0a28a47700000000000000000000000000000000000000000000000000000000815280613bc8602093600483019190602083019252565b0390828173d4fa2d31b7968e448877f69a96de69f5de8cd23e9381855afa80156103f557613c13915f91613d25575b50613c006129d6565b818110613d00575b808218908211021890565b6040517fd905777e000000000000000000000000000000000000000000000000000000008152306004820152908382602481865afa9081156103f557613c66925f92613ce1575b50808218908211021890565b9081613c7157505050565b6040517fba0876520000000000000000000000000000000000000000000000000000000081526004810192909252306024830181905260448301528290829060649082905f905af180156103f557613cc8575b5050565b81613cde92903d1061077b5761076c81836123c1565b50565b613cf9919250853d871161077b5761076c81836123c1565b905f613c5a565b613d12613d0d828461243a565b614d96565b15613c085750613d206129d6565b613c08565b613d3c9150843d861161077b5761076c81836123c1565b5f613bf7565b67ffffffffffffffff81116123305760051b60200190565b60209081818403126100155780519067ffffffffffffffff821161001557019180601f84011215610015578251613d9081613d42565b93613d9e60405195866123c1565b818552838086019260051b820101928311610015578301905b828210613dc5575050505090565b81518152908301908301613db7565b60209060206040818301928281528551809452019301915f5b828110613dfb575050505090565b835185529381019392810192600101613ded565b805115613e1c5760200190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b9190613ea7610f5791604051602081019182526002604082015260408152613e70816123a5565b5190206040519283916020830195866020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b519020906001820180921161037f57613f0e5f91613ed973ffffffffffffffffffffffffffffffffffffffff94614fe5565b6040519485809481937f7784c68500000000000000000000000000000000000000000000000000000000835260048301613dd4565b0392165afa80156103f557613f30613f4691611c3b935f9161304f5750613e0f565b516fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1690565b908160e0910312610015576040519060e0820182811067ffffffffffffffff82111761233057613ff19160c091604052613f94816132b6565b8452613fa2602082016132b6565b6020850152613fb3604082016132b6565b6040850152613fc4606082016132b6565b6060850152613fd5608082016132b6565b6080850152613fe660a082016132b6565b60a0850152016132b6565b60c082015290565b61018060c06111c4939594614064846101a081019860a0908173ffffffffffffffffffffffffffffffffffffffff9182815116855282602082015116602086015282604082015116604086015282606082015116606086015260808101516080860152015116910152565b80516fffffffffffffffffffffffffffffffff908116858401526020820151811660e086015260408201518116610100860152606082015181166101208601526080820151811661014086015260a08201511661016085015201516fffffffffffffffffffffffffffffffff16910152565b9190916fffffffffffffffffffffffffffffffff8080941691160191821161037f57565b60c082206040517f5c60e39a00000000000000000000000000000000000000000000000000000000815260048101919091529173ffffffffffffffffffffffffffffffffffffffff9160e0908490602490829086165afa9283156103f5575f9361448e575b50829061418b614185613f4660808501516fffffffffffffffffffffffffffffffff1690565b4261243a565b928315159081614455575b81614429575b50614229575b50516fffffffffffffffffffffffffffffffff16905060208201516fffffffffffffffffffffffffffffffff169261420a60606141f260408601516fffffffffffffffffffffffffffffffff1690565b9401516fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff928316948316938316921690565b61428d91816142576105946105946060602096015173ffffffffffffffffffffffffffffffffffffffff1690565b906040518095819482937f2a944b5500000000000000000000000000000000000000000000000000000000845260048401613ff9565b03915afa9081156103f557614315916142d9915f9161440a575b506142d360408601946142cd613f4687516fffffffffffffffffffffffffffffffff1690565b92615656565b9061569e565b916142ff6142e6846156b5565b82516fffffffffffffffffffffffffffffffff166140d6565b6fffffffffffffffffffffffffffffffff169052565b61435361433d614324836156b5565b84516fffffffffffffffffffffffffffffffff166140d6565b6fffffffffffffffffffffffffffffffff168352565b6fffffffffffffffffffffffffffffffff61438160a08401516fffffffffffffffffffffffffffffffff1690565b168061438f575b82906141a2565b6143a5670de0b6b3a764000091614403936144d6565b046142ff6142e66143fe6143d5846143d0613f4689516fffffffffffffffffffffffffffffffff1690565b61243a565b9360208701946143f8613f4687516fffffffffffffffffffffffffffffffff1690565b916156fc565b6156b5565b5f80614388565b614423915060203d60201161077b5761076c81836123c1565b5f6142a7565b905061444c606083015173ffffffffffffffffffffffffffffffffffffffff1690565b1615155f61419c565b90506fffffffffffffffffffffffffffffffff61448560408501516fffffffffffffffffffffffffffffffff1690565b16151590614196565b6144b191935060e03d60e0116144b8575b6144a981836123c1565b810190613f5b565b915f61415f565b503d61449f565b906127109182810292818404149015171561037f57565b8181029291811591840414171561037f57565b61450b61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b60405180917fbf86d69000000000000000000000000000000000000000000000000000000000825281600460209485935afa9081156103f5575f91614712575b50612c56576040517f5c975abb000000000000000000000000000000000000000000000000000000008152818160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f916146f5575b50612c56576145ad612f73565b906145b66129d6565b916145c96145c4848361246b565b61571e565b9182156146ec576145db6105946135fd565b8160405180927fcc718f76000000000000000000000000000000000000000000000000000000008252818061463760048201907fe1bb37f3f38496b3457796e7729ac8101c3fa82af647ce70ac30761a8520fe17602083019252565b03915afa9182156103f5575f926146cf575b505080156146c7575b61466c8161466661271061467494106129cf565b846144d6565b612710900490565b928282116146bc5781831190816146b2575b50806146a1575b614698575050505f90565b6132b29161243a565b506146ad610e4e613229565b61468d565b905015155f614686565b50906132b29161243a565b50600a614652565b6146e59250803d1061077b5761076c81836123c1565b5f80614649565b50915050151590565b61470c9150823d84116106195761060a81836123c1565b5f6145a0565b6147299150823d84116106195761060a81836123c1565b5f61454b565b1561473657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600460248201527f3c6d696e000000000000000000000000000000000000000000000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff83169283331490816148fc575b506147c7575b5050506111c461573c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114614842575b7fb45b0dd408214bf930dafc547364e44f4474bd439a3db3ae3edf0c60fa31a5b491506148266148218260415461246b565b604155565b60415460408051928352602083019190915290a25f80806147bc565b5060206148a49161486b61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b60405180809581947f07a2d13a000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b03915afa80156103f5577fb45b0dd408214bf930dafc547364e44f4474bd439a3db3ae3edf0c60fa31a5b4915f916148dd575b506147ef565b6148f6915060203d60201161077b5761076c81836123c1565b5f6148d7565b6149299150610e479073ffffffffffffffffffffffffffffffffffffffff165f52604060205260405f2090565b5f6147b6565b6004602073ffffffffffffffffffffffffffffffffffffffff60015416604051928380927fbf86d6900000000000000000000000000000000000000000000000000000000082525afa9081156103f5575f9161499c575b50613cde57614994906151d9565b6111c4614ad1565b6149b5915060203d6020116106195761060a81836123c1565b5f614986565b91906001810180911161037f57620f4240820180921161037f57611c3b92615889565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183099102908180821091030391565b634e487b715f526020526024601cfd5b6040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91614ab2575b506111c457614a7e612f73565b614a866129d6565b810180821161037f57614a989061571e565b80821115613cc457810390811161037f57613cde90614d96565b614acb915060203d6020116106195761060a81836123c1565b5f614a71565b6040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91614b8d575b506111c457614b2f612f73565b614b376129d6565b90614b456145c4838361246b565b9182821115614b5c5750613cde91613d0d9161243a565b81831180614b84575b614b6f575b505050565b6128a5614b7f92613cde9461243a565b615924565b50801515614b65565b614ba6915060203d6020116106195761060a81836123c1565b5f614b22565b5f9073ffffffffffffffffffffffffffffffffffffffff80603a5416604051602081019182527fd2841a5d2692465040bd5e06a6f3b37483952c866e0f304dc0e03f76a1f8a0b4604082015260408152614c05816123a5565b51902080547fd2841a5d2692465040bd5e06a6f3b37483952c866e0f304dc0e03f76a1f8a0b291825491808611614c74575b85900390558390039055603a5460405192835216907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602090a3565b945084614c37565b91610120919493610140840195614cda8560a073ffffffffffffffffffffffffffffffffffffffff80603454168352806035541660208401528060365416604084015280603754166060840152603854608084015260395416910152565b60c08501525f60e085015273ffffffffffffffffffffffffffffffffffffffff80921661010085015216910152565b91610120919493610140840195614d678560a073ffffffffffffffffffffffffffffffffffffffff80603454168352806035541660208401528060365416604084015280603754166060840152603854608084015260395416910152565b5f60c086015260e085015273ffffffffffffffffffffffffffffffffffffffff80921661010085015216910152565b8015612c5657614dbe61059460325473ffffffffffffffffffffffffffffffffffffffff1690565b803b15610015576040905f825180927f1e4711cf000000000000000000000000000000000000000000000000000000008252818381614e4c6004820160345473ffffffffffffffffffffffffffffffffffffffff908116825260355481166020830152603654811660408301526037548116606083015260385460808301526039541660a082015260c00190565b03925af180156103f557614fd2575b50614e78614e676132d3565b909491928186188287100290911890565b8015612d605780821891811191909102189283614e96575b50505090565b82908410614f4357614efe5f92614ec561059460325473ffffffffffffffffffffffffffffffffffffffff1690565b9083519485809481937fa0b16cc70000000000000000000000000000000000000000000000000000000083523090309060048501614d09565b03925af180156103f557614f18575b50505b5f8080614e90565b81614f3792903d10614f3c575b614f2f81836123c1565b81019061380d565b614f0d565b503d614f25565b5050614f6761059460325473ffffffffffffffffffffffffffffffffffffffff1690565b81805180927fa0b16cc7000000000000000000000000000000000000000000000000000000008252815f81614fa130308b60048501614c7c565b03925af180156103f557614fb7575b5050614f10565b81614fcd92903d10614f3c57614f2f81836123c1565b614fb0565b80610bba614fdf9261231c565b5f614e5b565b60405190614ff28261236d565b600182526020368184013761500682613e0f565b5290565b80158015615162575b613cde576040517fef8b30f700000000000000000000000000000000000000000000000000000000815280615052602093600483019190602083019252565b03828273d4fa2d31b7968e448877f69a96de69f5de8cd23e9281845afa9182156103f5575f92615143575b506040517fc63d75b600000000000000000000000000000000000000000000000000000000815230600482015282908481602481865afa9081156103f5575f91615126575b5080911161511e575b508115614b6a576040517f94bf804d000000000000000000000000000000000000000000000000000000008152600481019290925230602483015282908290815f81604481015b03925af1613cc8575050565b91505f6150cb565b61513d9150853d871161077b5761076c81836123c1565b5f6150c2565b61515b919250833d851161077b5761076c81836123c1565b905f61507d565b506040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f916151ba575b50615013565b6151d3915060203d6020116106195761060a81836123c1565b5f6151b4565b801580156155df575b613cde5760408051907fef8b30f7000000000000000000000000000000000000000000000000000000008252602092826152256004928383019190602083019252565b03848473d4fa2d31b7968e448877f69a96de69f5de8cd23e9281845afa9384156103f5575f946155c0575b5082517fc63d75b6000000000000000000000000000000000000000000000000000000008152308382019081528591908790829081906020010381865afa9081156103f5575f916155a3575b5080911161559b575b5083156154fc576152b761307f612f73565b9280517f07a2d13a00000000000000000000000000000000000000000000000000000000908181528781806152f3898983019190602083019252565b0381875afa9081156103f5575f9161557e575b508251957fb3d7f6b90000000000000000000000000000000000000000000000000000000087528887806153418b8a83019190602083019252565b0381885afa9283156103f557888a9261537d995f96615559575b50906153669161246b565b908551988992839283528983019190602083019252565b0381875afa80156103f5578161539c918a985f9161553c575b5061243a565b918281116153ec575b505090517f94bf804d00000000000000000000000000000000000000000000000000000000815292830194855250306020850152909283919082905f908290604001615112565b90919295506154126105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b88875180927f70a082310000000000000000000000000000000000000000000000000000000082528180615465308c830191909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b03915afa80156103f5578693615481925f92615524575061246b565b92886154a561059460015473ffffffffffffffffffffffffffffffffffffffff1690565b8851948580927f01e1d1140000000000000000000000000000000000000000000000000000000082525afa9081156103f5576154ed935f92615503575b50612816919261243a565b116154fc5784925f80806153a5565b5050505050565b612816925061551e908b3d8d1161077b5761076c81836123c1565b916154e2565b6127f39192508b3d8d1161077b5761076c81836123c1565b6155539150893d8b1161077b5761076c81836123c1565b5f615396565b6153669291965061557690853d871161077b5761076c81836123c1565b95909161535b565b6155959150883d8a1161077b5761076c81836123c1565b5f615306565b93505f6152a5565b6155ba9150873d891161077b5761076c81836123c1565b5f61529c565b6155d8919450853d871161077b5761076c81836123c1565b925f615250565b506040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9081156103f5575f91615637575b506151e2565b615650915060203d6020116106195761060a81836123c1565b5f615631565b90615660916144d6565b671bc16d674ec8000061567382806144d6565b046729a2241af62c000061568783836144d6565b0490820180921161037f57810180911161037f5790565b670de0b6b3a7640000916156b1916144d6565b0490565b6fffffffffffffffffffffffffffffffff908181116156d2571690565b60046040517f6acc9c8f000000000000000000000000000000000000000000000000000000008152fd5b91620f4240810180911161037f576001820180921161037f57611c3b92615889565b6157336127109161572d61319a565b906144d6565b046128a56159f9565b61575d6105945f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526020918290829060249082905afa9081156103f5575f9161586c575b508015613cc4576157b5906151d9565b6040517f5c975abb000000000000000000000000000000000000000000000000000000008152818160048173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9182156103f5575f9261584f575b50506111c45761581361319a565b156111c457615820612f73565b6158286129d6565b906158366145c4838361246b565b9181831115614b6a576128a5614b7f92613cde9461243a565b6158659250803d106106195761060a81836123c1565b5f80615805565b6158839150823d841161077b5761076c81836123c1565b5f6157a5565b906136a3916144d6565b905f9073ffffffffffffffffffffffffffffffffffffffff61016094610140926159048660a073ffffffffffffffffffffffffffffffffffffffff80603454168352806035541660208401528060365416604084015280603754166060840152603854608084015260395416910152565b60c08601528360e086015216610100840152806101208401528201520190565b801580156159eb575b612c565761595361059460325473ffffffffffffffffffffffffffffffffffffffff1690565b6040805180927f370160a0000000000000000000000000000000000000000000000000000000008252815f8161598d308960048401615893565b03925af190816159cd575b50611c3b576040519081527fbe96638bde19b2e58565dd987769a2932fcbbd362f2ea7a0201d9fe524e799ba90602090a15f90565b6159e59060403d604011614f3c57614f2f81836123c1565b50615998565b506159f4613229565b61592d565b603a5473ffffffffffffffffffffffffffffffffffffffff168015615cbc57615a236105946135fd565b6040517fcc718f760000000000000000000000000000000000000000000000000000000081527f6f17d12aaeef2cb47b81cd9a8d7ae8c8b3af200ada02c2e61aecbb6b4cbb86246004820152602092918390829060249082905afa9081156103f5575f91615c9f575b508015612da557615b0a9083615aba61059460015473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90951660048601529392839081906024820190565b0381865afa9182156103f5575f92615c80575b50604051907f18160ddd0000000000000000000000000000000000000000000000000000000082528482600481875afa9182156103f55760049486915f94615c61575b50604051958680927f01e1d1140000000000000000000000000000000000000000000000000000000082525afa9384156103f5575f94615c42575b5081158015615c3a575b8015615c32575b612d6057615bca615bc5615bcf93615c07968896613723565b6144bf565b6136a3565b604051809381927fc6e6f592000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b038173d4fa2d31b7968e448877f69a96de69f5de8cd23e5afa9182156103f5575f9261356e57505090565b508215615bac565b508315615ba5565b615c5a919450853d871161077b5761076c81836123c1565b925f615b9b565b615c79919450823d841161077b5761076c81836123c1565b925f615b60565b615c98919250843d861161077b5761076c81836123c1565b905f615b1d565b615cb69150833d851161077b5761076c81836123c1565b5f615a8c565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9056fea164736f6c6343000816000a","sourceMap":"3310:37370:32:-:0;;;;;;;;;-1:-1:-1;3310:37370:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;3310:37370:32;;;;;;;;;;1422:17:34;3310:37370:32;;1422:47:34;;;;;-1:-1:-1;3310:37370:32;;;;1422:47:34;;;;3310:37370:32;1422:47:34;;1458:10;3310:37370:32;1422:47:34;;3310:37370:32;1422:47:34;;;;;;;;3310:37370:32;;37112:19;3310:37370;37101:30;;;3310:37370;;;;;;;;;;37112:19;3310:37370;;;;;;;;;;;;;;;;37197:47;;3310:37370;;;;;37197:47;;;;3310:37370;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1422:47:34;;;;;;:::i;:::-;-1:-1:-1;1422:47:34;;;;;;:::i;3310:37370:32:-;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;21268:2891;;:::i;:::-;3310:37370;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;5975:139:33;5999:97;3310:37370:32;;;6013:82:33;3310:37370:32;6013:82:33;;;;3310:37370:32;;;;6013:82:33;;3310:37370:32;6013:82:33;;3310:37370:32;;;;;;;;;;;;6013:82:33;;;;;:::i;:::-;5999:97;:::i;:::-;3310:37370:32;;;;5975:139:33;;;;;;:::i;:::-;29856:21:32;;;;;;3310:37370;29856:38;;;;3310:37370;29856:73;;;;3310:37370;;29852:101;;;;3310:37370;;;;;;;;;;;;;;;;;;;;29852:101;29947:5;;:::i;:::-;29852:101;;29856:73;3310:37370;;;29899:28;3310:37370;29899:17;3310:37370;;;;;;;;;;29899:28;3310:37370;;29899:30;;;;3310:37370;29899:30;;;;;;;;;3310:37370;29899:30;-1:-1:-1;29899:30:32;;;29856:73;29898:31;;;29856:73;;29899:30;;;;;;-1:-1:-1;29899:30:32;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;29856:38;3310:37370;;29881:13;3310:37370;29889:5;3310:37370;;;;;29881:13;;29856:38;;;:21;29867:10;;;-1:-1:-1;29856:21:32;;;3310:37370;;;;;;;:::o;:::-;;;;;;;;;;;27716:29;3310:37370;27716:17;3310:37370;;;;;27716:29;3310:37370;;27716:31;3310:37370;27716:31;;;;;;3310:37370;27716:31;;;;;;;;;3310:37370;27716:31;;;3310:37370;;;;;;;27777:31;;;;3310:37370;27777:31;;;;;;;;;3310:37370;27777:31;;;3310:37370;27862:17;;27922:9;27862:17;;:::i;:::-;27922:9;;;;;:::i;:::-;3310:37370;;;;;;;;;;;;;;27777:31;;;;;;-1:-1:-1;27777:31:32;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;27716;3310:37370;27716:31;;;;;;;;;;;;;;;;:::i;:::-;;;;;;3310:37370;;;;-1:-1:-1;3310:37370:32;;;;;;;;;;;;:::i;:::-;;;1422:17:34;3310:37370:32;;1422:47:34;;;;;-1:-1:-1;3310:37370:32;;;;1422:47:34;;;;3310:37370:32;1422:47:34;;1458:10;3310:37370:32;1422:47:34;;3310:37370:32;1422:47:34;;;;;;;;3310:37370:32;;34212:5;3310:37370;;;;;;;;34250:20;;;3310:37370;;;34311:40;3310:37370;;;;;;34212:5;3310:37370;;;;-1:-1:-1;3310:37370:32;;;;;;34311:40;3310:37370;;1422:47:34;;;;;;:::i;:::-;-1:-1:-1;1422:47:34;;;;3310:37370:32;;;;;;;;;;;2109:45:34;2139:4;2117:10;:27;2109:45;:::i;:::-;14236:7;3310:37370:32;;14236:7:34;:::i;:::-;3310:37370:32;;;;;;;;;;;;;4792:25;3310:37370;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;1223:59:34;;:::i;:::-;3310:37370:32;;:::i;:::-;15740:27;3310:37370;15740:12;3310:37370;;;;;15740:27;:35;;;;;3310:37370;;;15740:35;;3310:37370;;;;;;;;15740:35;3310:37370;;15740:35;;;:::i;:::-;;;;;;;;;;;3310:37370;;15791:28;3310:37370;15791:17;3310:37370;;;;;15791:28;3310:37370;;15791:30;;3310:37370;15791:30;;;3310:37370;15791:30;;;;;;;;;;;3310:37370;15791:30;;;3310:37370;15790:31;;15786:85;;3310:37370;;15889:5;;:::i;:::-;3310:37370;;;;;;;;;;;;;15786:85;15833:15;3310:37370;;;;;;;15833:15;3310:37370;;;15833:30;;15857:4;3310:37370;15833:30;;3310:37370;;;;;;;;;;15833:30;;;;;;;15865:5;15833:30;3310:37370;15833:30;;;15786:85;15865:5;;;:::i;:::-;15786:85;;;15833:30;;;;;;-1:-1:-1;15833:30:32;;;;;;:::i;:::-;;;;;15791;;;;;;;;;;;;;;:::i;:::-;;;;15740:35;;;;;;:::i;:::-;;;:::i;:::-;;;;3310:37370;;;;;;;;;;;;;;;;;:::i;:::-;;-1:-1:-1;3310:37370:32;5158:48;3310:37370;;;;5158:48;-1:-1:-1;3310:37370:32;;;5158:48;3310:37370;;;;;;;;;;;;;;;;;;2109:45:34;2139:4;2117:10;:27;2109:45;:::i;3310:37370:32:-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;9506:14:34;;:::i;:::-;3310:37370:32;;9585:56:34;9608:32;9585:56;;;;;;;;;;:::i;:::-;3310:37370:32;;;;;;;;;;;9585:56:34;3310:37370:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::i;:::-;1623:8:33;26252:11:32;;:25;;;3310:37370;26248:102;;3310:37370;26443:17;26433:27;;26429:94;;3310:37370;26590:7;26547:25;;;3310:37370;;;;24461:15;3310:37370;;;;;;;26547:25;3310:37370;;;;;26547:25;26590:7;;3310:37370;26590:7;:33;;;;;;3310:37370;26582:51;;;:::i;:::-;26735:27;3310:37370;26735:17;3310:37370;;;;;26735:27;3310:37370;;;26735:37;;3310:37370;;;;26735:37;;3310:37370;;26735:37;;;;3310:37370;;;;;;26735:37;;;;;;;3310:37370;26735:37;1831:8:33;26735:37:32;1651:137:33;26735:37:32;-1:-1:-1;26735:37:32;;;3310:37370;26786:19;;:30;;;;3310:37370;26782:98;;;3310:37370;-1:-1:-1;3310:37370:32;;;1689:77:33;;;;3310:37370:32;1689:77:33;;3310:37370:32;;;;;;;;;;1675:92:33;;1689:77;3310:37370:32;;;;1689:77:33;;;;;;;;;:::i;1675:92::-;3310:37370:32;;1651:137:33;;;;;;;:::i;:::-;1831:8;;;:::i;:::-;3310:37370:32;;;;;;;;;;;;26782:98;26832:37;3310:37370;26850:10;3310:37370;-1:-1:-1;26840:20:32;26832:37;:::i;:::-;26782:98;;;26786:30;;;;;;26735:37;;;;;;;;;;;;;;:::i;:::-;;;;26590:33;-1:-1:-1;26601:10:32;3310:37370;;;26601:22;26590:33;;26429:94;3310:37370;26485:15;3310:37370;-1:-1:-1;3310:37370:32;;;;;26485:15;3310:37370;;;26485:27;;26501:10;3310:37370;26485:27;;3310:37370;;26485:27;;3310:37370;;;;;;26485:27;;;;;;;-1:-1:-1;26485:27:32;;;26429:94;26476:36;26429:94;;26485:27;;;;;;;;;;;;;;:::i;:::-;;;;26248:102;3310:37370;26302:29;3310:37370;26302:17;3310:37370;;;;;26302:29;:37;3310:37370;;26302:37;;3310:37370;26302:37;;;;;3310:37370;26302:37;;3310:37370;-1:-1:-1;3310:37370:32;;;;;;26302:37;;;;;;;;;;-1:-1:-1;26302:37:32;;;26248:102;26293:46;26248:102;;26302:37;;;;;;;;;;;;;;:::i;:::-;;;;26252:25;;-1:-1:-1;26252:25:32;;3310:37370;;;;;;;;;;;;4110:18;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;-1:-1:-1;3310:37370:32;5013:47;3310:37370;;;;;-1:-1:-1;3310:37370:32;;;;;;;;;;;;;;;-1:-1:-1;3310:37370:32;;;;;;;;;;1422:17:34;3310:37370:32;;1422:47:34;;;;;-1:-1:-1;3310:37370:32;;;;1422:47:34;;;;3310:37370:32;1422:47:34;;1458:10;3310:37370:32;1422:47:34;;3310:37370:32;1422:47:34;;;;;;;;3310:37370:32;;;;37495:30;3310:37370;37456:24;3310:37370;;;;;;37495:30;3310:37370;;1422:47:34;;;;;;:::i;:::-;-1:-1:-1;;3310:37370:32;1422:47:34;;3310:37370:32;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;26267:10:32;26248:102;;3310:37370;26443:17;26433:27;;26429:94;;3310:37370;26590:7;26547:25;;;3310:37370;;;;24461:15;3310:37370;;;;;;;26590:7;:33;;;;;;3310:37370;26582:51;;;:::i;:::-;26735:27;3310:37370;26252:11;3310:37370;;;;;26735:27;3310:37370;;;26735:37;;3310:37370;;;;26735:37;;3310:37370;;26735:37;;;;3310:37370;;;;;;26735:37;;;;;;;3310:37370;26735:37;2402:8:33;26735:37:32;2225:134:33;26735:37:32;-1:-1:-1;26735:37:32;;;3310:37370;26786:19;;:30;;;;3310:37370;26782:98;;;3310:37370;-1:-1:-1;3310:37370:32;;;2263:74:33;;;;3310:37370:32;2263:74:33;;3310:37370:32;;;;;;;;;;2249:89:33;;2263:74;3310:37370:32;;;;2263:74:33;3310:37370:32;2225:134:33;2402:8;;;:::i;26782:98:32:-;26832:37;3310:37370;26850:10;3310:37370;-1:-1:-1;26840:20:32;26832:37;:::i;:::-;26782:98;;;26786:30;;;;;;26735:37;;;;;;;;;;;;;;:::i;:::-;;;;26590:33;-1:-1:-1;26601:10:32;3310:37370;;;26601:22;26590:33;;26429:94;3310:37370;26485:15;3310:37370;-1:-1:-1;3310:37370:32;;;;;26485:15;3310:37370;;;26485:27;;26501:10;3310:37370;26485:27;;3310:37370;;26485:27;;3310:37370;;;;;;26485:27;;;;;;;-1:-1:-1;26485:27:32;;;26429:94;26476:36;26429:94;;26485:27;;;;;;;;;;;;;;:::i;:::-;;;;26248:102;3310:37370;26302:29;3310:37370;26252:11;3310:37370;;;;;26302:29;:37;3310:37370;;26302:37;;3310:37370;26302:37;;;;;;3310:37370;26302:37;;3310:37370;;;;;;;;26302:37;;;;;;;;;;-1:-1:-1;26302:37:32;;;26248:102;26293:46;26248:102;;26302:37;;;;;;;;;;;;;;:::i;:::-;;;;3310:37370;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;2109:45:34;2139:4;2117:10;:27;2109:45;:::i;:::-;15525:10;3310:37370:32;;15525:10:34;:::i;3310:37370:32:-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;4753:92:33;4715:164;4739:107;4753:92;;3310:37370:32;;;:::i;:::-;;;4776:34:33;4753:92;;;;;;;3310:37370:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4739:107:33;3310:37370:32;;;;4715:164:33;;;;;;:::i;3310:37370:32:-;;;;3490:94:33;3435:196;3459:139;3490:94;;3310:37370:32;;;:::i;:::-;;;3513:36:33;3490:94;;;;;;;3310:37370:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1652:17:34;3310:37370:32;;1652:55:34;;;;;3310:37370:32;;;;;1652:55:34;;;;3310:37370:32;1652:55:34;;1696:10;3310:37370:32;1652:55:34;;3310:37370:32;1652:55:34;;;;;;;;3310:37370:32;39351:17;39483:31;3310:37370;39351:17;;;:::i;:::-;3310:37370;;;39483:31;;;;3310:37370;39483:31;;;;;;;;;3310:37370;39483:31;;;3310:37370;39532:22;39548:6;39532:22;;3310:37370;;40173:32;;3310:37370;;39944:24;39782:70;;40002:23;3310:37370;39483:31;3310:37370;40001:48;40093:65;;3310:37370;;40173:32;;;;3310:37370;;;;;;;;39483:31;;;;;;;;;;;;;;:::i;:::-;;;;1652:55:34;;;;;;:::i;:::-;3310:37370:32;;39483:31;1652:55:34;;3310:37370:32;;;;;;;;;;;;;;;;:::i;:::-;;;5343:107:33;5354:87;3310:37370:32;;;;5368:72:33;3310:37370:32;5368:72:33;;;;3310:37370:32;;5368:72:33;;3310:37370:32;;;;;;;5368:72:33;;;;;:::i;5354:87::-;3310:37370:32;;;;5343:107:33;;;;;;:::i;:::-;;;;29856:21:32;;;3310:37370;29856:38;;;;3310:37370;29856:73;;;3310:37370;29852:101;;;;3310:37370;;;;;;;;;;;;;;;29856:38;3310:37370;29881:13;3310:37370;29889:5;3310:37370;;;;;29881:13;5478:10:33;29881:13:32;29856:38;;:21;29867:10;;;;29856:21;;;3310:37370;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;:::o;:::-;;;;3490:94:33;3435:196;3459:139;3310:37370:32;;;:::i;:::-;;;3490:94:33;3513:36;3490:94;;;;;;;3310:37370:32;;;;;;;;;;;;;;-1:-1:-1;3310:37370:32;;;;;3490:94:33;;;;;:::i;3310:37370:32:-;;;;4753:92:33;4715:164;4739:107;3310:37370:32;;;:::i;:::-;;;4753:92:33;4776:34;4753:92;;;;;;;3310:37370:32;;;;;;;;;;;;;;1078:6:33;3310:37370:32;;;;;4753:92:33;;;;;:::i;3310:37370:32:-;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;1422:17:34;3310:37370:32;-1:-1:-1;3310:37370:32;;;;;1422:47:34;;;;;-1:-1:-1;3310:37370:32;;;;1422:47:34;;;;3310:37370:32;1422:47:34;;1458:10;3310:37370:32;1422:47:34;;3310:37370:32;1422:47:34;;;;;;;;3310:37370:32;;35922:41;3310:37370;;;;;;-1:-1:-1;3310:37370:32;35872:15;3310:37370;;35872:35;3310:37370;;-1:-1:-1;3310:37370:32;;;;;;;;;;;;;;;35872:35;3310:37370;;;;;;;35922:41;3310:37370;;1422:47:34;3310:37370:32;1422:47:34;;;;;35922:41:32;1422:47:34;;:::i;:::-;-1:-1:-1;1422:47:34;;;;;;3310:37370:32;;;;;;;;;;;;;;3707:42;3310:37370;;;;;;;;;;;;;;;;;2967:42:34;3310:37370:32;;;;;;;;;;;;;;;5275:34;3310:37370;;;;;;;;;;;-1:-1:-1;3310:37370:32;;;;;;;;1422:17:34;3310:37370:32;;1422:47:34;;;;;-1:-1:-1;3310:37370:32;;;;1422:47:34;;;;3310:37370:32;1422:47:34;;1458:10;3310:37370:32;1422:47:34;;3310:37370:32;1422:47:34;;;;;;;;3310:37370:32;;;;37831:25;;;:44;;;3310:37370;;;;37895:23;3310:37370;;;:::i;:::-;;;;;;;:::i;:::-;;;;;-1:-1:-1;3310:37370:32;;;;-1:-1:-1;3310:37370:32;;;;;;37895:23;:::i;:::-;;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;37831:44;37861:14;;;:::i;:::-;37860:15;37831:44;;1422:47:34;;;;;:::i;:::-;-1:-1:-1;1422:47:34;;;3310:37370:32;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4008:27;3310:37370;;;;;;;;;;;;;;;:::i;:::-;1422:17:34;3310:37370:32;-1:-1:-1;3310:37370:32;;;;;1422:47:34;;;;;-1:-1:-1;3310:37370:32;;;;1422:47:34;;;;3310:37370:32;1422:47:34;;1458:10;3310:37370:32;1422:47:34;;3310:37370:32;1422:47:34;;;;;;;;3310:37370:32;;36767:43;3310:37370;;;;;;-1:-1:-1;3310:37370:32;;;;36715:37;3310:37370;;-1:-1:-1;3310:37370:32;;;;;;;;;;;;;;;1422:47:34;3310:37370:32;1422:47:34;;;;;36767:43:32;1422:47:34;;:::i;:::-;-1:-1:-1;1422:47:34;;;;;;3310:37370:32;;;;;;;;;;;;;4535:20;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;582:1:31;3310:37370:32;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;21268:2891::-;21419:15;3310:37370;;;;;;;21419:15;3310:37370;;;;21419:30;;21443:4;21419:30;;;;3310:37370;;;;21419:30;;;3310:37370;21419:30;;3310:37370;;;;;;21419:30;;;;;;;3310:37370;21419:30;;;21268:2891;3310:37370;21481:29;3310:37370;21481:17;3310:37370;;;;;21481:29;3310:37370;;21481:31;3310:37370;21481:31;;;;;;;;;;;;;;3310:37370;21481:31;;;21268:2891;22375:14;;;:::i;:::-;22371:53;;22483:13;;:::i;:::-;22507:23;;;3310:37370;;;22545:34;3310:37370;22545:34;;3707:42;22545:34;;;;;;;;;;;;;;3310:37370;22545:34;;;21268:2891;-1:-1:-1;22541:649:32;;;22595:19;;;23241:39;22595:19;3310:37370;22541:649;;3310:37370;;23241:39;;;;;3310:37370;23241:39;;;;;3310:37370;;;;;;;;23241:39;;;;;;;;;;;;;;23229:51;23241:39;3310:37370;23241:39;;;22541:649;23229:51;;:::i;:::-;3310:37370;;;23378:30;;;;3310:37370;23378:30;;;;;;;;;3310:37370;23378:30;;;22541:649;23374:86;;;23643:19;3310:37370;940:4:5;;2218:6:7;;;;940:4:5;;23749:13:32;23699:17;;:::i;23749:13::-;3310:37370;;;;;23749:54;;;;;;;;;;;2461:34:26;;;;;3310:37370:32;;2461:34:26;23749:54:32;;;;;;;;;;;23832:58;23749:54;;;3310:37370;23749:54;;;22541:649;3310:37370;;23832:58;;;;;;;;;;2461:34:26;2675:38;2461:34;;;3310:37370:32;;2461:34:26;23832:58:32;;;;;;;;;;4325:12:7;23832:58:32;24034:32;23832:58;23971:37;23832:58;3310:37370;23832:58;;;22541:649;23813:77;;;1078:6:33;23904:18:32;;;23900:42;;22541:649;23971:37;;;:::i;:::-;24034:32;5527:5:7;;;;5312;;940:4:5;5306:42:7;5435:111;;24034:32:32;940:4:5;;2218:6:7;;;;;940:4:5;;;;2052:240:7;4325:12;5709:5;;;;;;;5312;;940:4:5;5306:42:7;21268:2891:32;:::o;23900:42::-;23924:18;;23900:42;;;23832:58;;;;;;-1:-1:-1;23832:58:32;;;;;;:::i;:::-;;;;;23749:54;;;;;;;;;;;;;;;:::i;:::-;;;;;23374:86;23424:25;;;;;;:::o;23378:30::-;;;;;;;;;;;;;;:::i;:::-;;;;23241:39;;;;;;;;;;;;;;;:::i;:::-;;;;;22541:649;22667:17;5701:20:7;22803:26:32;22667:17;;;:::i;:::-;5709:5:7;5312;;;5709;;-1:-1:-1;940:4:5;5306:42:7;;5071:294;5701:20;22803:26:32;;:::i;:::-;22848:25;;22844:336;;22541:649;23241:39;22541:649;;;;22844:336;3310:37370;;;22897:31;;;21443:4;22897:31;;;3310:37370;;;;;-1:-1:-1;3310:37370:32;;-1:-1:-1;21443:4:32;;3310:37370;;;;;;22897:31;;;;;;;;;;;3310:37370;22897:31;;;22844:336;22897:36;;:84;;;;22844:336;-1:-1:-1;23241:39:32;;22893:273;;;;23005:19;3310:37370;22893:273;22844:336;;22893:273;23089:58;23121:25;;;:::i;:::-;23089:58;5709:5:7;;;;5312;;940:4:5;5306:42:7;5617:111;;23089:58:32;22893:273;22844:336;;22897:84;22937:39;3310:37370;;;22954:21;3310:37370;22962:12;3310:37370;;;;;22954:21;3310:37370;;;22937:39;;;;;;;;;;3310:37370;;;;;;;;;;;;22937:39;;;;;;;;;;;23241;22937;;;3310:37370;22937:39;;;22897:84;22937:44;;22897:84;;;;22937:39;;;;;;;;;;;;;;:::i;:::-;;;;22897:31;;;;;;;;;;;;;;:::i;:::-;;;;22545:34;;;;;;;;;;;;;;:::i;:::-;;;;22371:53;22405:8;;;;;;3310:37370;22405:8;:::o;21481:31::-;;;;;;;;;;;;;;;:::i;:::-;;;;;21419:30;;;;;;;;;;;;;;;:::i;:::-;;;;;3310:37370;;;;:::o;32118:112::-;3310:37370;;;32192:31;;32217:4;32192:31;;;3310:37370;32192:31;;3310:37370;32192:31;3707:42;32192:31;;;;;;;-1:-1:-1;32192:31:32;;;32185:38;32118:112;:::o;32192:31::-;;;;;;;;;;;;;;:::i;24360:1478::-;24460:24;24461:23;;;3310:37370;;;;24461:15;3310:37370;;;;;;;24460:24;:62;;;24360:1478;24456:101;;24612:43;3310:37370;;24612:12;3310:37370;;;;;;24638:8;3310:37370;24612:43;;:::i;:::-;24608:86;;24718:24;:17;;:::i;:24::-;3310:37370;;;24718:59;;2258:28:26;24718:59:32;;;3310:37370;;24718:59;;;;3310:37370;;2461:34:26;;3310:37370:32;;24718:59;;;;;;;-1:-1:-1;24718:59:32;;;24360:1478;24791:8;;;24787:47;;24847:23;;;3310:37370;;;;24461:15;3310:37370;;;;;;;24847:23;:51;;;;24360:1478;24843:106;;24988:29;3310:37370;24988:17;3310:37370;;;;;24988:29;3310:37370;;;;24988:31;;;;24718:59;24988:31;;;;;;;;;-1:-1:-1;24988:31:32;;;24360:1478;25033:25;;;;;25029:64;;25122:24;;;:::i;:::-;3310:37370;;;25176:43;3310:37370;25176:43;;;;;;;24718:59;25176:43;;3310:37370;;;;;;;;25176:43;;;;;;;;;;;-1:-1:-1;25176:43:32;;;24360:1478;25233:14;;;25229:124;;25381:10;3310:37370;25405:12;;;;:56;;;;;24360:1478;25401:102;;;;25516:18;;;:72;;;;;24360:1478;25512:295;;;;;;;24360:1478;:::o;25512:295::-;25788:8;-1:-1:-1;25788:8:32;:::o;25516:72::-;3310:37370;;;25538:40;3310:37370;;;;25538:40;;;;;3310:37370;25538:40;;24718:59;25538:40;;3310:37370;;;;;;;;25538:40;;;;;;;;;;-1:-1:-1;25538:40:32;;;25516:72;25538:50;;;25516:72;;;;;;25538:40;;;;;;-1:-1:-1;25538:40:32;;;;;;:::i;:::-;;;;;25401:102;25477:15;;;;;:::o;25405:56::-;3310:37370;;;25421:35;;3310:37370;;;;;24718:59;25421:35;;3310:37370;;-1:-1:-1;3310:37370:32;;;25421:35;;;;;;;;-1:-1:-1;25421:35:32;;;25405:56;25421:40;;;25405:56;;;;25421:35;;;;;;;;;;;;;;:::i;:::-;;;;25229:124;25334:8;;;;;-1:-1:-1;25334:8:32;:::o;25176:43::-;;;;;;;;;;;;;;;:::i;:::-;;;;;24988:31;;;;;;;;;;;;;;:::i;:::-;;;;24843:106;24914:24;;;24921:17;24914:24;:::o;24847:51::-;24874:24;24881:17;24874:24;;24847:51;;24787:47;24815:8;;;-1:-1:-1;24815:8:32;:::o;24718:59::-;;;;;;;;;;;;;;;:::i;:::-;;;;;24460:62;3310:37370;;;;24488:34;;;;;;3707:42;24488:34;;;;;;;;;;;24460:62;;;;24488:34;;;;;;;;;;;;;;:::i;:::-;;;;3310:37370;;;;;;;:::i;:::-;;;;;15716:13;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7302:410::-;7546:50;3310:37370;7546:12;3310:37370;;;;:::i;:::-;7546:50;;:::i;:::-;7491:105;;;;;;7624:81;:37;;;:81;:37;;;3310:37370;;;;;;;7302:410;:::o;7624:81::-;;;-1:-1:-1;7302:410:32;:::o;3310:37370::-;;;;;;;;;;;;;:::o;32380:143::-;676:22:30;3310:37370:32;32453:12;3310:37370;;;;:::i;:::-;-1:-1:-1;592:59:30;696:118:24;;;3310:37370:32;;1948:29:31;;;3310:37370:32;;;582:1:31;3310:37370:32;582:1:31;;3310:37370:32;;1948:29:31;;;;;:::i;:::-;3310:37370:32;1938:40:31;;3310:37370:32;;;32510:4;1948:29:31;1921:58;;3310:37370:32;;;582:1:31;;;3310:37370:32;;;;1921:58:31;;3310:37370:32;582:1:31;;;1921:58;582:1;1921:58;3310:37370:32;1911:69:31;;592:59:30;:::i;:::-;3310:37370:32;;676:22:30;;;;3310:37370:32;676:22:30;;;;;;:::i;:::-;;;;;;;;;;;:25;4710:44:29;676:22:30;4772:63:29;676:22:30;-1:-1:-1;676:22:30;;;32380:143:32;676:25:30;;:::i;:::-;3310:37370:32;4710:44:29;;:::i;:::-;4772:63;;;;:::i;676:22:30:-;;;;;;-1:-1:-1;676:22:30;;;;;;:::i;:::-;;;;;:::i;:::-;;;;32694:162:32;32756:60;32779:36;:16;;:::i;:::-;32798:17;;:::i;32779:36::-;3310:37370;;32756:60;3310:37370;32756:60;;;;;;;;;;;3310:37370;;;;;;;;32756:60;;;3707:42;32756:60;;;;;;;-1:-1:-1;32756:60:32;;;32694:162;3310:37370;32819:15;3310:37370;-1:-1:-1;3310:37370:32;;;;;32819:15;3310:37370;;;32819:30;;32843:4;32756:60;32819:30;;3310:37370;;;;;;;;;;;32819:30;;;;;;;32756:93;32819:30;-1:-1:-1;32819:30:32;;;32694:162;32756:93;;;:::i;32819:30::-;;;;;;;-1:-1:-1;32819:30:32;;;;;;:::i;:::-;;;;;;32756:60;;;;;;;;;;;;;;:::i;:::-;;;;33577:152;33699:23;;3310:37370;33665:17;;:::i;:::-;3310:37370;;;33699:23;;;;3310:37370;33699:23;;;;;;;;;-1:-1:-1;33699:23:32;;;33692:30;33577:152;:::o;17683:770:34:-;17896:551;;;;;;;;2967:42;17896:551;;;;;;;;;;;;;;;;8757:120:32;8827:5;;:::i;:::-;8835:1;3310:37370;;;;;;;8839:31;3310:37370;8839:31;3310:37370;8839:17;3310:37370;;;;8839:31;;;;3310:37370;8839:31;;;;;;;;;-1:-1:-1;8839:31:32;;;8827:43;;8757:120;:::o;8839:31::-;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;8757:120:32;:::o;3310:37370::-;;;;;;;;;;:::o;7965:411::-;3310:37370;8090:12;3310:37370;;8090:46;8112:8;3310:37370;;;;8090:46;;;;3310:37370;8090:46;;;;;3310:37370;8130:4;3310:37370;;;;8090:46;;;;;;;-1:-1:-1;8090:46:32;;;7965:411;3310:37370;;8276:20;8318:51;8276:20;;:::i;:::-;8223:73;;;;8318:51;;:::i;:::-;7965:411;:::o;8090:46::-;;;;;;;;;;;;;;;;;:::i;:::-;;;3310:37370;;;;;;;8090:46;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;8090:46;;;;;;-1:-1:-1;8090:46:32;;3310:37370;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;20440:172::-;3310:37370;;;20547:13;;;3707:42;;20547:13;;;;;;;;;;;;;;;;;20440:172;3310:37370;;;;20589:14;;;;20547:13;20589:14;;;;;;;;;3310:37370;20589:14;;;20547:57;20589:14;20547:13;20589:14;;;20440:172;3310:37370;;;20547:57;;;;;;3310:37370;20547:57;;:13;:57;;3310:37370;;;;;;;;;;;;20547:57;;3310:37370;;20547:57;;;;;;20524:81;20547:57;;;:13;:57;;;20440:172;3310:37370;;;20524:81;;;;;3310:37370;20524:81;;20547:13;20524:81;;3310:37370;;;;;;;;;;;;20524:81;;;;;;;;;;20547:13;20524:81;;;20517:88;;20440:172;:::o;20524:81::-;;;;;;-1:-1:-1;20524:81:32;;;;;;:::i;20547:57::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;20589:14;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;20547:13;;;;;;;;;;;;;;:::i;:::-;;;;8382:161;3310:37370;8482:53;;3310:37370;8504:12;3310:37370;;;;8482:53;;;;3310:37370;8482:53;;;;;;;;;-1:-1:-1;8482:53:32;;;3310:37370;;8382:161;:::o;8482:53::-;;;;;;;;;;;;;;:::i;:::-;3310:37370;8382:161;:::o;3310:37370::-;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;7242:3683:7:-;;7404:12;;;;:::i;:::-;7498:9;;;7494:365;;1078:6:33;7969:19:7;;;;;7965:142;;940:4:5;8390:308:7;;;;;;;;940:4:5;;8390:308:7;;8962:384;;9409:18;940:4:5;7242:3683:7;:::o;7965:142::-;1829:135:5;;;5306:42:7;1829:135:5;;;;;7494:365:7;3310:37370:32;;1078:6:33;3310:37370:32;;;7820:24:7;:::o;7242:3683::-;;7404:12;;;;:::i;:::-;7498:9;;;;;7494:365;;7969:19;;;;7965:142;;8390:308;;;;940:4:5;7506:1:7;940:4:5;8917:31:7;;8962:384;;;9800:1;940:4:5;;9781:1:7;940:4:5;9780:21:7;940:4:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8962:384:7;;;;7506:1;8962:384;;;8390:308;;;;;;940:4:5;8390:308:7;;8962:384;9409:18;940:4:5;7242:3683:7;:::o;7965:142::-;8028:16;;5312:5;940:4:5;;5306:42:7;8020:71;:::i;7494:365::-;7827:17;;;;;;;:::i;16655:594:34:-;16854:48;16655:594;;16854:48;;;;;2967:42;16854:48;;3310:37370:32;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;16854:48:34;;3310:37370:32;;;;16968:8:34;16964:225;;16655:594;:::o;16964:225::-;16992:187;;;;;16854:48;16992:187;;;3310:37370:32;;;;;;;;;;;;;;;;;;;;;;:::o;6641:228:33:-;6755:107;6766:75;3310:37370:32;;;6780:60:33;;;;;;;;;;:::i;6766:75::-;6780:60;3310:37370:32;;;6755:107:33;;;;;;:::i;:::-;6726:136;6641:228;:::o;28011:1325:32:-;;;28111:8;;;:31;;;28011:1325;28111:48;;;28011:1325;28111:65;;;28011:1325;28107:1175;;28011:1325;3310:37370;;;29298:15;3310:37370;28118:1;3310:37370;;;;;29298:15;3310:37370;;;29298:30;;29322:4;29298:30;;;3310:37370;;29298:30;;3310:37370;;;;;;29298:30;;;;;;;;28118:1;29298:30;;;28011:1325;29298:30;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;28107:1175;28263:34;:27;3310:37370;28263:17;3310:37370;;;;;28263:27;3310:37370;;28291:5;3310:37370;;;;;;;;;28263:34;;3310:37370;;;;28263:34;;;3310:37370;;28263:34;;;;3310:37370;;;;;;;;;28263:34;;;;;;;;;;;28118:1;28263:34;;;28107:1175;28316:16;;28312:960;;28107:1175;;;;;;28312:960;11181:25:7;;;;28263:34:32;11181:25:7;;:::i;:::-;3310:37370:32;;;28649:31;;;;3310:37370;28649:31;;;;;;;;;28118:1;28649:31;;;28312:960;-1:-1:-1;;28719:22:32;;;;;;28744;;;:::i;:::-;28873:28;;;;;;28904;;;:::i;:::-;28873:63;;28850:86;;29046:27;29042:101;;28873:63;29165:16;;29161:97;;28873:63;28312:960;;;;;;;29161:97;29226:12;;;:::i;:::-;29161:97;;;29042:101;29097:27;;29042:101;;;28873:63;;;28118:1;28873:63;;;28719:51;;;28118:1;28719:51;;28649:31;;;;;;-1:-1:-1;28649:31:32;;;;;;:::i;:::-;;;;;28263:34;;;;;;;;;;;;;;;:::i;:::-;;;;;28111:65;28163:13;;;;28111:65;;:48;28146:13;;;;28111:48;;:31;3310:37370;;;28123:5;3310:37370;;;;;;;28123:19;;28111:31;;3310:37370;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;2064:97:34;2109:45;2139:4;2117:10;:27;2109:45;:::i;14199:895:32:-;14268:12;;14264:49;;3310:37370;;;14391:31;;;;;;;;;3310:37370;;;;;;;;14391:31;;3707:42;;;;14391:31;;;;;;;;;5701:20:7;14391:31:32;14279:1;14391:31;;;14199:895;14499:17;;;:::i;:::-;14531:26;;;14527:329;;14199:895;5312:5:7;;;5709;;-1:-1:-1;940:4:5;5306:42:7;;5071:294;5701:20;3310:37370:32;;;14937:31;;14962:4;14391:31;14937;;3310:37370;;14962:4;3310:37370;;;14937:31;;;;;;;;5701:20:7;14937:31:32;14279:1;14937:31;;;14199:895;-1:-1:-1;5312:5:7;;;5709;;-1:-1:-1;940:4:5;5306:42:7;;5071:294;5701:20;14984:18:32;;14980:108;;14199:895;;;:::o;14980:108::-;3310:37370;;;15018:59;;14391:31;15018:59;;3310:37370;;;;14962:4;3310:37370;;;;;;;;;;;;;;;;;;-1:-1:-1;;15018:59:32;;;;;;;;14980:108;14199:895;;:::o;15018:59::-;;;;;;-1:-1:-1;15018:59:32;;;;;;:::i;:::-;;14199:895::o;14937:31::-;;;;;;;;;;;;;;;:::i;:::-;;;;;14527:329;14711:37;14650:26;;;;:::i;:::-;14711:37;:::i;:::-;14763:83;14527:329;14763:83;14814:17;;;:::i;:::-;14527:329;;14391:31;;;;;;;;;;;;;;:::i;:::-;;;;3310:37370;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;-1:-1:-1;3310:37370:32;;;;;-1:-1:-1;3310:37370:32;715:264:30;;;2187:58:31;;715:264:30;3310:37370:32;;2214:29:31;;;3310:37370:32;;;582:1:31;3310:37370:32;582:1:31;;3310:37370:32;;2214:29:31;;;;;:::i;:::-;3310:37370:32;2204:40:31;;3310:37370:32;;2187:58:31;;;2214:29;2187:58;;;;582:1;;;;;;3310:37370:32;582:1:31;;;3310:37370:32;;;;582:1:31;3310:37370:32;582:1:31;2187:58;3310:37370:32;2177:69:31;;3310:37370:32;1175:1:27;3310:37370:32;;;;;;;945:22:30;-1:-1:-1;840:72:30;;3310:37370:32;840:72:30;;:::i;:::-;3310:37370:32;;945:22:30;;;;;;3310:37370:32;945:22:30;;;;;;:::i;:::-;;3310:37370:32;;945:22:30;;;;;;:25;929:43;945:22;922:50;945:22;-1:-1:-1;945:22:30;;;:25;;:::i;:::-;3310:37370:32;;;;;929:43:30;3310:37370:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1451:1496:29:-;696:118:24;;;3310:37370:32;;;1688:17:29;;;;;3310:37370:32;;;;;;;;;;;;;;;;;1688:17:29;;;;;;;-1:-1:-1;1688:17:29;;;1451:1496;1752:17;;;1734:35;;3310:37370:32;1752:17:29;;;3310:37370:32;;;;;1734:35:29;:15;:35;:::i;:::-;1902:12;;;;:45;;;;1451:1496;1902:79;;;1451:1496;1898:921;;;1451:1496;-1:-1:-1;3310:37370:32;;;;-1:-1:-1;2863:24:29;;;3310:37370:32;;;2889:24:29;3310:37370:32;2915:24:29;3310:37370:32;;2889:24:29;;3310:37370:32;;;;;;2915:24:29;;3310:37370:32;;;;;;;;;;;;;;;;;;;1451:1496:29:o;1898:921::-;2018:59;2023:16;;2018:37;:22;3310:37370:32;2023:16:29;2018:59;2023:16;;3310:37370:32;;;;;2018:37:29;3310:37370:32;;;2018:59:29;;;;;;3310:37370:32;2018:59:29;;1688:17;2018:59;;;:::i;:::-;;;;;;;;;;2196:48;2018:59;2110:72;2018:59;-1:-1:-1;2018:59:29;;;1898:921;2110:24;2144:37;3310:37370:32;2110:24:29;;3310:37370:32;2110:33:29;3310:37370:32;;;;;;;2110:33:29;2144:37;;:::i;:::-;2110:72;;:::i;:::-;2224:20;2196:48;2224:20;;;:::i;:::-;3310:37370:32;;;;2196:48:29;:::i;:::-;3310:37370:32;;;;;2196:48:29;2258;;2286:20;;;:::i;:::-;3310:37370:32;;;;2196:48:29;:::i;2258:::-;3310:37370:32;;;;;2258:48:29;3310:37370:32;;2325:10:29;;;3310:37370:32;;;;;;;2325:15:29;2321:488;;1898:921;;;;;2321:488;943:5:25;93:4;943:5;2745:49:29;943:5:25;;:::i;:::-;3310:37370:32;2745:49:29;2773:21;2641:86;2664:36;3310:37370:32;2664:36:29;3310:37370:32;;;;;;;2664:36:29;;:::i;:::-;2702:24;2018:59;2702:24;;3310:37370:32;2641:86:29;3310:37370:32;;;;;;;2641:86:29;;;:::i;:::-;2773:21;:::i;2745:49::-;2321:488;;;;2018:59;;;;;;;;;;;;;;:::i;:::-;;;;1902:79;1951:16;;3310:37370:32;1951:16:29;;;3310:37370:32;;;;;;;1951:30:29;;1902:79;;;:45;1918:24;;3310:37370:32;;;1918:24:29;;3310:37370:32;;;;;;;1918:29:29;;1902:45;;;1688:17;;;;;3310:37370:32;1688:17:29;3310:37370:32;1688:17:29;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;2786:33:26;;10141:6:32;2786:33:26;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::o;17624:996:32:-;17700:28;3310:37370;17700:17;3310:37370;;;;;17700:28;3310:37370;;17700:30;;3310:37370;17700:30;;;;;;;;;;;;;;;;;;;17624:996;17696:73;;;3310:37370;;;17782:34;;;;17700:30;17782:34;3707:42;17782:34;;;;;;;17700:30;17782:34;;;17624:996;17778:52;;;17860:16;;:::i;:::-;17908:17;;;:::i;:::-;17957:22;18006:38;17957:22;;;;:::i;:::-;18006:38;:::i;:::-;18059:11;;;18055:36;;18173:13;18127:17;;:::i;18173:13::-;3310:37370;;;18173:53;;3310:37370;18173:53;;;;;17700:30;18173:53;;2461:34:26;2786:33;2461:34;;;3310:37370:32;;2461:34:26;18173:53:32;;;;;;;;;;17700:30;18173:53;;;17624:996;18154:72;;;18240:13;18236:32;;17624:996;18335:17;18286;18278:26;18297:6;18334:28;18286:17;;18278:26;:::i;:::-;18335:17;;:::i;:::-;18297:6;3310:37370;;;;18334:28;18377:17;;;;18373:86;;18472:17;;;:36;;;;17624:996;18472:55;;;;17624:996;18468:124;;18601:12;;;17700:30;17624:996;:::o;18468:124::-;18551:17;;;:::i;18472:55::-;18513:14;18512:15;18513:14;;:::i;18512:15::-;18472:55;;:36;18493:15;;;;18472:36;;;18373:86;18418:17;;;;;:::i;18236:32::-;-1:-1:-1;18266:2:32;18236:32;;18173:53;;;;;;-1:-1:-1;18173:53:32;;;;;;:::i;:::-;;;;;18055:36;18079:12;;;;;;18072:19;:::o;17782:34::-;;;;;;;;;;;;;;:::i;:::-;;;;17700:30;;;;;;;;;;;;;;:::i;:::-;;;;3310:37370;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;26966:439;3310:37370;;;27074:10;;;:22;:52;;;;26966:439;27070:295;;;26966:439;27070:295;;;;;:::i;:::-;27156:17;27146:27;;27142:83;;27070:295;27287:67;3310:37370;;27239:29;;3310:37370;27239:29;3310:37370;27239:29;:::i;:::-;;3310:37370;;27239:29;;3310:37370;;;;;;;;;;;;;;;27287:67;27070:295;;;;;27142:83;3310:37370;27184:41;;3310:37370;27184:33;3310:37370;27184:17;3310:37370;;;;;27184:33;3310:37370;;27184:41;;;;;3310:37370;27184:41;;;;;3310:37370;;;;;;;;27184:41;;;;;;;;;27287:67;27184:41;-1:-1:-1;27184:41:32;;;27142:83;27175:50;27142:83;;27184:41;;;;;;;;;;;;;;:::i;:::-;;;;27074:52;27100:26;;;;;3310:37370;;;;27100:16;3310:37370;;27100:16;3310:37370;;;;27100:26;27074:52;;;16048:251;16115:30;;3310:37370;16115:17;3310:37370;;;;16115:30;;;;3310:37370;16115:30;;;;;;;;;-1:-1:-1;16115:30:32;;;16048:251;16111:67;;;16255:4;;;:::i;:::-;16287;;:::i;16115:30::-;;;;;;;;;;;;;;:::i;:::-;;;;1560:213:27;;;1175:1;3310:37370:32;;;;;;;992:3:27;3310:37370:32;;;;;;;1689:77:27;;;:::i;1027:550:7:-;;1412:159;;;;;;;;;;;;;;1027:550;:::o;1776:194:5:-;1829:135;;;;;;;;16613:931:32;3310:37370;;;16678:34;;;;;;3707:42;16678:34;;;;;;;-1:-1:-1;16678:34:32;;;16613:931;16674:47;;;16801:16;;:::i;:::-;16849:17;;:::i;:::-;3310:37370;;;;;;;16968:38;;;:::i;:::-;17021:37;;;;;;3310:37370;;;;;;;17201:37;;;:::i;16678:34::-;;;;;;;;;;;;;;:::i;:::-;;;;16613:931;3310:37370;;;16678:34;;;;;;3707:42;16678:34;;;;;;;;;;;16613:931;16674:47;;;16801:16;;:::i;:::-;16849:17;;:::i;:::-;16898:28;16968:38;16898:28;;;;:::i;16968:38::-;17021:37;;;;;;;17150;17201;17150;;;;:::i;17017:521::-;17274:37;;;17259:71;;;17017:521;17255:283;;17017:521;;;;16613:931::o;17255:283::-;17444:37;17422:60;17444:37;17496:31;17444:37;;:::i;17422:60::-;17496:31;:::i;17259:71::-;17315:15;;;;17259:71;;16678:34;;;;;;;;;;;;;;:::i;:::-;;;;30760:1012;-1:-1:-1;30760:1012:32;3310:37370;;31022:5;3310:37370;;;;7155:37:18;;;3310:37370:32;;;;;582:1:31;;3310:37370:32;;7155:37:18;;;;;:::i;:::-;3310:37370:32;7145:48:18;;31138:126:32;;3310:37370;31138:126;;;31326:27;;;31367;31363:85;;30760:1012;31484:158;;;;;;;;;;31022:5;3310:37370;;;;;;;;31719:46;;7155:37:18;;31719:46:32;30760:1012::o;31363:85::-;31410:27;-1:-1:-1;31410:27:32;31363:85;;3310:37370;;;;;;;;;;;;;;;19753:13;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19703:1;3310:37370;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;19753:13;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19703:1;3310:37370;;;;;;;;;;;;;;;;;;;;:::o;19573:861::-;19684:20;;19680:34;;19725:27;3310:37370;19725:12;3310:37370;;;;;19725:27;:42;;;;;3310:37370;;19703:1;3310:37370;;19725:42;;3310:37370;19725:42;;;;;;;;;19753:13;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19725:42;;;;;;;;;;;19573:861;19840:13;5701:20:7;19840:13:32;;:::i;:::-;5709:5:7;;;;5312;;;5709;;;940:4:5;5306:42:7;;;;5071:294;5701:20;19941::32;;19937:59;;5312:5:7;;;5709;;-1:-1:-1;940:4:5;;;;5306:42:7;20081:19:32;;20077:318;;19573:861;20405:22;;;19573:861;:::o;20077:318::-;20120:28;;;;;;20168:77;19703:1;3310:37370;20168:21;3310:37370;19725:12;3310:37370;;;;;20168:21;3310:37370;;;20168:77;;;;;;3310:37370;20168:77;;20224:4;;;20168:77;19725:42;20168:77;;;:::i;:::-;;;;;;;;;;;20116:269;;;;20077:318;;;;;20168:77;;;;;;-1:-1:-1;20168:77:32;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;20116:269;3310:37370;;20284:21;3310:37370;19725:12;3310:37370;;;;;20284:21;3310:37370;;;20284:86;;3310:37370;20284:86;;20349:4;19703:1;20349:4;20284:86;20349:4;;20284:86;19725:42;20284:86;;;:::i;:::-;;;;;;;;;;;20116:269;;;;;20284:86;;;;;;-1:-1:-1;20284:86:32;;;;;;:::i;:::-;;;19725:42;;;;;;:::i;:::-;;;;2728:163:30;3310:37370:32;;;;;;:::i;:::-;2842:1:30;3310:37370:32;;;;;;;;2854:10:30;;;:::i;:::-;3310:37370:32;2728:163:30;:::o;11334:920:32:-;11410:11;;:49;;;;11334:920;11406:62;;3310:37370;;;11494:29;;;;;;;;;3310:37370;;;;;;;;11494:29;;3707:42;;;11494:29;;;;;;;;;;3310:37370;11494:29;;;11334:920;-1:-1:-1;3310:37370:32;;;11553:29;;11576:4;11494:29;11553;;3310:37370;11477:46;;11576:4;3310:37370;;;11553:29;;;;;;;;3310:37370;11553:29;;;11334:920;11596:18;;;;11592:42;;11334:920;11648:11;;;11644:24;;3310:37370;;;12202:34;;11494:29;12202:34;;3310:37370;;;;11576:4;3310:37370;;;;;;;;;;;;;;12202:34;;;;;;;11334:920;;:::o;11592:42::-;11616:18;-1:-1:-1;11592:42:32;;;11553:29;;;;;;;;;;;;;;:::i;:::-;;;;11494;;;;;;;;;;;;;;;:::i;:::-;;;;;11410:49;3310:37370;;;;11425:34;;;;;;3707:42;11425:34;;;;;;;3310:37370;11425:34;;;11410:49;;;;11425:34;;;;;;;;;;;;;;:::i;:::-;;;;11334:920;11410:11;;:49;;;;11334:920;11406:62;;3310:37370;;;11494:29;3310:37370;11494:29;;;;;;;;;;;3310:37370;;;;;;;;11494:29;;3707:42;;;11494:29;;;;;;;;;;11420:1;11494:29;;;11334:920;-1:-1:-1;3310:37370:32;;;11553:29;;11576:4;11553:29;;;3310:37370;;;11477:46;;3310:37370;11576:4;;3310:37370;;;;;;11553:29;;;;;;;;;;11420:1;11553:29;;;11334:920;11596:18;;;;11592:42;;11334:920;11648:11;;;11644:24;;11729:36;:16;;:::i;:36::-;3310:37370;;;;11799:33;;;;;;;;;;;;3310:37370;;;;;;;;11799:33;;;;;;;;;;;11420:1;11799:33;;;11334:920;3310:37370;;;11861:26;3310:37370;11861:26;;;;;;;;;;3310:37370;;;;;;;;11861:26;;;;;;;;;;;;;;11916:42;11861:26;11420:1;11861:26;;;11334:920;11939:18;;;;;:::i;:::-;3310:37370;;;11916:42;;;;;;;;;;3310:37370;;;;;;;;11916:42;;;;;;;;;;;:54;:42;;;11420:1;11916:42;;;11334:920;11916:54;;:::i;:::-;11988:11;;;;11984:195;;11334:920;-1:-1:-1;;3310:37370:32;;;12202:34;;;;;3310:37370;;;-1:-1:-1;11576:4:32;3310:37370;;;;;;;;-1:-1:-1;3310:37370:32;;11420:1;;3310:37370;;;;12202:34;3310:37370;11984:195;3310:37370;;;;;12048:15;3310:37370;11420:1;3310:37370;;;;;12048:15;3310:37370;;;12048:30;;3310:37370;12048:30;;11576:4;;12048:30;11576:4;12048:30;;;3310:37370;;;;;;;;;;;;12048:30;;;;;;;;;;;12036:42;12048:30;11420:1;12048:30;;;12036:42;;:::i;:::-;3310:37370;;12100:29;3310:37370;16115:17;3310:37370;;;;;12100:29;3310:37370;;12100:31;;;;3310:37370;12100:31;;;;;;;;;:47;:31;11420:1;12100:31;;;11984:195;12135:11;;;;;:::i;12100:47::-;:56;12096:69;;11984:195;;;;;;;12096:69;12158:7;;;;;:::o;12100:31::-;12135:11;12100:31;;;;;;;;;;;;;;:::i;:::-;;;;12048:30;;;;;;;;;;;;;;;:::i;11916:42::-;;;;;;;;;;;;;;:::i;:::-;;;;11861:26;11939:18;11861:26;;;;;;;;;;;;;;;;:::i;:::-;;;;;;11799:33;;;;;;;;;;;;;;:::i;:::-;;;;11592:42;11616:18;-1:-1:-1;11592:42:32;;;11553:29;;;;;;;;;;;;;;:::i;:::-;;;;11494;;;;;;;;;;;;;;;:::i;:::-;;;;;11410:49;3310:37370;;;;11425:34;;;;;;3707:42;11425:34;;;;;;;11420:1;11425:34;;;11410:49;;;;11425:34;;;;;;;;;;;;;;:::i;:::-;;;;1311:319:25;;1422:5;1311:319;1422:5;:::i;:::-;2786:33:26;943:5:25;;;;:::i;:::-;3310:37370:32;2786:33:26;943:5:25;;;;:::i;:::-;3310:37370:32;;;;;;;;;;;;;;;;1311:319:25;:::o;314:117::-;93:4;314:117;943:5;314:117;943:5;:::i;:::-;3310:37370:32;314:117:25;:::o;826:170:28:-;3310:37370:32;902:21:28;;;;898:64;;3310:37370:32;826:170:28;:::o;898:64::-;932:30;3310:37370:32;;932:30:28;;;;1262:213:27;;992:3;3310:37370:32;;;;;;;1175:1:27;3310:37370:32;;;;;;;1391:77:27;;;:::i;10655:275:32:-;10779:27;10810:6;10655:275;10793:13;;:::i;:::-;10779:27;;:::i;:::-;3310:37370;10843:31;;:::i;12736:1354::-;12804:15;3310:37370;12804:5;3310:37370;;;;;12804:15;3310:37370;;;12804:30;;12828:4;12804:30;;;3310:37370;12804:30;;;;3310:37370;;;;;;12804:30;;;;;;;:5;:30;;;12736:1354;12848:11;;;12844:24;;12896:4;;;:::i;:::-;3310:37370;;;13214:34;;;;12804:30;13214:34;3707:42;13214:34;;;;;;;12804:5;13214:34;;;12736:1354;13210:47;;;;13294:13;;:::i;:::-;13321:21;13317:133;;13538:16;;:::i;:::-;13586:17;;:::i;:::-;13635:28;13704:38;13635:28;;;;:::i;13704:38::-;13757:37;;;;;13753:140;;14004:36;13982:59;14004:36;14052:31;14004:36;;:::i;13214:34::-;;;;;;-1:-1:-1;13214:34:32;;;;;;:::i;:::-;;;;;12804:30;;;;;;;;;;;;;;:::i;:::-;;;;840:120:25;;943:5;840:120;943:5;:::i;3310:37370:32:-;;19092:1;3310:37370;;;;;;;;;;;19753:13;3310:37370;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;18991:365::-;19082:11;;:29;;;;18991:365;19078:43;;19136:19;3310:37370;19136:12;3310:37370;;;;;19136:19;3310:37370;;;19136:64;;3310:37370;19136:64;;19190:4;19092:1;19190:4;19136:64;19190:4;19136:64;;;;;:::i;:::-;;;;;;;;;18991:365;-1:-1:-1;19132:218:32;;3310:37370;;;;;19292:25;;3310:37370;;19292:25;19092:1;19331:8;:::o;19136:64::-;;;3310:37370;19136:64;3310:37370;19136:64;;;;;;;:::i;:::-;;;;19082:29;19097:14;;;:::i;:::-;19082:29;;9217:1006;9304:5;3310:37370;;;9304:19;;9300:49;;9435:13;9385:17;;:::i;9435:13::-;3310:37370;;;9435:56;;1668:36:26;9435:56:32;;;3310:37370;9435:56;;;;;3310:37370;;2461:34:26;;3310:37370:32;;9435:56;;;;;;;9321:1;9435:56;;;9217:1006;9505:17;;;9501:47;;9581:34;3310:37370;;9581:27;3310:37370;9581:17;3310:37370;;;;;9581:27;3310:37370;;;9581:34;;3310:37370;;;;9435:56;9581:34;;3310:37370;;;;;;;;;;;;9581:34;;;;;;;;;;;9321:1;9581:34;;;9217:1006;3310:37370;;;9648:31;3310:37370;9648:31;;;;9435:56;9648:31;;;;;;;;;9435:56;9648:31;;;9321:1;9648:31;;;9217:1006;3310:37370;;;9712:31;;;;3310:37370;9712:31;;;;;;;;;9321:1;9712:31;;;9217:1006;9758:17;;;:38;;;;9217:1006;9758:58;;;;9217:1006;9754:72;;10124:23;11181:25:7;10123:40:32;11181:25:7;10181:35:32;11181:25:7;;;;:::i;:::-;10124:23:32;:::i;:::-;10123:40;:::i;:::-;3310:37370;;10181:35;;;;3310:37370;10181:35;;9435:56;10181:35;;3310:37370;;;;;;;;10181:35;;;3707:42;10181:35;;;;;;;9321:1;10181:35;;;10174:42;;9217:1006;:::o;9758:58::-;9800:16;;;9758:58;;:38;9779:17;;;9758:38;;9712:31;;;;;;;;;;;;;;;:::i;:::-;;;;;9648;;;;;;;;;;;;;;;:::i;:::-;;;;;9581:34;;;;;;;;;;;;;;;:::i;:::-;;;;;9435:56;;;;;;;;;;;;;;:::i;:::-;;;;9300:49;9325:24;9332:17;9325:24;:::o","linkReferences":{},"immutableReferences":{}}}}}}},"sources":{"src/usd3/USD3.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0\npragma solidity 0.8.22;\n\nimport {BaseHooksUpgradeable} from \"./base/BaseHooksUpgradeable.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Math} from \"../../lib/openzeppelin/contracts/utils/math/Math.sol\";\nimport {IMorpho, IMorphoCredit, MarketParams, Id} from \"../interfaces/IMorpho.sol\";\nimport {MorphoLib} from \"../libraries/periphery/MorphoLib.sol\";\nimport {MorphoBalancesLib} from \"../libraries/periphery/MorphoBalancesLib.sol\";\nimport {SharesMathLib} from \"../libraries/SharesMathLib.sol\";\nimport {IERC4626} from \"../../lib/openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport {Pausable} from \"../../lib/openzeppelin/contracts/utils/Pausable.sol\";\nimport {TokenizedStrategyStorageLib} from \"@periphery/libraries/TokenizedStrategyStorageLib.sol\";\nimport {IProtocolConfig} from \"../interfaces/IProtocolConfig.sol\";\nimport {ProtocolConfigLib} from \"../libraries/ProtocolConfigLib.sol\";\n\ninterface IAavePool {\n    function getVirtualUnderlyingBalance(address asset) external view returns (uint128);\n}\n\ninterface IWaUSDC is IERC4626 {\n    function POOL() external view returns (IAavePool);\n}\n\n/**\n * @title USD3\n * @author 3Jane Protocol\n * @notice Senior tranche strategy for USDC-based lending on 3Jane's credit markets\n * @dev Implements Yearn V3 tokenized strategy pattern for unsecured lending via MorphoCredit.\n * Deploys USDC capital to 3Jane's modified Morpho Blue markets that use credit-based\n * underwriting instead of collateral. Its loss waterfall uses strategy-owned locked-profit shares\n * before sUSD3 subordinate capital, then exposes USD3 holders to any residual loss.\n *\n * Key features:\n * - Senior tranche whose current principal and PPS are buffered first by locked profit, then by sUSD3 holdings\n * - Configurable deployment ratio to credit markets (maxOnCredit)\n * - Automatic yield distribution to sUSD3 via performance fees\n * - Loss absorption through direct share burning of sUSD3 holdings\n * - Supply-cap exemptions for protocol-controlled deposit receivers\n * - Dynamic fee adjustment via ProtocolConfig integration\n *\n * Yield Distribution Mechanism:\n * - Tranche share distributed to sUSD3 holders via TokenizedStrategy's performance fee\n * - Performance fee can be set from 0-100% through syncTrancheShare()\n * - Direct storage manipulation bypasses TokenizedStrategy's 50% fee limit\n * - Keeper-controlled updates ensure protocol-wide consistency\n *\n * Loss Absorption Mechanism:\n * - TokenizedStrategy first burns strategy-owned locked-profit shares remaining from prior profitable reports\n * - USD3 burns sUSD3-held USD3 shares only for the loss remaining after that locked-profit burn\n * - Current USD3 principal and PPS remain protected while locked profit covers the loss, but cash-collected profit\n *   that would otherwise unlock to USD3 holders is consumed before junior principal\n * - Direct storage manipulation burns the required sUSD3-held shares without asset transfers, capped by its balance\n * - Losses exceeding both outstanding locked profit and sUSD3's USD3 balance reduce USD3 holders proportionally\n * - Both loss-to-share conversions round down; at high PPS, a loss worth less than one base share can burn nothing\n *   from either buffer and still reduce senior PPS\n */\ncontract USD3 is BaseHooksUpgradeable {\n    using MorphoLib for IMorpho;\n    using MorphoBalancesLib for IMorpho;\n    using SharesMathLib for uint256;\n    using Math for uint256;\n\n    /*//////////////////////////////////////////////////////////////\n                        CONSTANTS\n    //////////////////////////////////////////////////////////////*/\n    IWaUSDC public constant WAUSDC = IWaUSDC(0xD4fa2D31b7968E448877f69A96DE69f5de8cD23E);\n\n    /*//////////////////////////////////////////////////////////////\n                        STORAGE - MORPHO PARAMETERS\n    //////////////////////////////////////////////////////////////*/\n    /// @notice MorphoCredit contract for lending operations\n    IMorpho public morphoCredit;\n\n    /// @notice Market ID for the lending market this strategy uses\n    Id public marketId;\n\n    /// @notice Market parameters for the lending market\n    MarketParams internal _marketParams;\n\n    /*//////////////////////////////////////////////////////////////\n                        UPGRADEABLE STORAGE\n    //////////////////////////////////////////////////////////////*/\n    /// @notice Address of the subordinate sUSD3 strategy\n    /// @dev Used for loss absorption and yield distribution\n    address public sUSD3;\n\n    bool private __deprecated_whitelistEnabled;\n\n    mapping(address => bool) private __deprecated_whitelist;\n\n    mapping(address => bool) private __deprecated_depositorWhitelist;\n\n    /// @notice Minimum deposit amount required\n    uint256 public minDeposit;\n\n    mapping(address => uint256) private __deprecated_depositTimestamp;\n\n    /// @notice Receivers whose self-deposits bypass USD3 supply-cap headroom and first-time minimum-deposit checks.\n    mapping(address => bool) public supplyCapExempt;\n\n    /// @notice Conduits whose self-deposits add to the ring-fenced liquidity accumulator.\n    mapping(address => bool) public ringFenceConduit;\n\n    /// @notice Fenced capital-call cash in USDC asset units.\n    uint256 public ringFencedLiquidity;\n\n    /*//////////////////////////////////////////////////////////////\n                            EVENTS\n    //////////////////////////////////////////////////////////////*/\n    event SUSD3StrategyUpdated(address oldStrategy, address newStrategy);\n    event SupplyCapExemptUpdated(address indexed account, bool exempt);\n    event RingFenceConduitUpdated(address indexed conduit, bool enabled);\n    event RingFencedLiquidityIncreased(address indexed conduit, uint256 assets, uint256 newTotal);\n    event RingFenceReleased(uint256 assets, uint256 newTotal);\n    event MinDepositUpdated(uint256 newMinDeposit);\n    event TrancheShareSynced(uint256 trancheShare);\n    event RebalanceDeferred(uint256 waUSDCAmount);\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        EXTERNAL VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Get the symbol for the USD3 token\n     * @return Symbol string \"USD3\"\n     */\n    function symbol() external pure returns (string memory) {\n        return \"USD3\";\n    }\n\n    /**\n     * @notice Get the market parameters for this strategy\n     * @return MarketParams struct containing lending market configuration\n     */\n    function marketParams() external view returns (MarketParams memory) {\n        return _marketParams;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        INTERNAL VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Get current market liquidity information\n     * @return totalSupplyAssets Total assets supplied to the market\n     * @return totalShares Total supply shares in the market\n     * @return totalBorrowAssets Total assets borrowed from the market\n     * @return waUSDCLiquidity Available liquidity in the market\n     */\n    function getMarketLiquidity()\n        public\n        view\n        returns (uint256 totalSupplyAssets, uint256 totalShares, uint256 totalBorrowAssets, uint256 waUSDCLiquidity)\n    {\n        (totalSupplyAssets, totalShares, totalBorrowAssets,) = morphoCredit.expectedMarketBalances(_marketParams);\n        waUSDCLiquidity = totalSupplyAssets > totalBorrowAssets ? totalSupplyAssets - totalBorrowAssets : 0;\n    }\n\n    /**\n     * @dev Get strategy's position in the market\n     * @return shares Number of supply shares held\n     * @return waUSDCMax Maximum waUSDC that can be withdrawn\n     * @return waUSDCLiquidity Available market liquidity in waUSDC\n     */\n    function getPosition() internal view returns (uint256 shares, uint256 waUSDCMax, uint256 waUSDCLiquidity) {\n        shares = morphoCredit.position(marketId, address(this)).supplyShares;\n        uint256 totalSupplyAssets;\n        uint256 totalShares;\n        (totalSupplyAssets, totalShares,, waUSDCLiquidity) = getMarketLiquidity();\n        waUSDCMax = shares.toAssetsDown(totalSupplyAssets, totalShares);\n    }\n\n    function _protocolConfig() internal view returns (IProtocolConfig) {\n        return IProtocolConfig(IMorphoCredit(address(morphoCredit)).protocolConfig());\n    }\n\n    /// @dev Whether live NAV reflects a loss that has not yet been recognized by report(). Exact on every path:\n    /// deposit-path callers run after TokenizedStrategy has added the deposit to totalAssets.\n    function _pendingLoss() internal view returns (bool) {\n        return nav() + 2 < TokenizedStrategy.totalAssets();\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    INTERNAL STRATEGY FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @dev Maximum waUSDC deployment allowed by sUSD3 backing alone.\n    /// Returns type(uint256).max when no subordination constraint applies.\n    function _subordinationDeployCapWaUSDC() internal view returns (uint256) {\n        if (sUSD3 == address(0)) return type(uint256).max;\n\n        IProtocolConfig config = _protocolConfig();\n        uint256 backingRatio = config.config(ProtocolConfigLib.MIN_SUSD3_BACKING_RATIO);\n        if (backingRatio == 0) return type(uint256).max;\n\n        uint256 sUSD3Shares = TokenizedStrategy.balanceOf(sUSD3);\n        uint256 _totalSupply = TokenizedStrategy.totalSupply();\n        uint256 _totalAssets = TokenizedStrategy.totalAssets();\n\n        if (_totalSupply == 0 || _totalAssets == 0 || sUSD3Shares == 0) return 0;\n\n        // Conservative (floor-rounded) USD3 share-to-USDC conversion,\n        // same accounting model as sUSD3.sol availableDepositLimit/availableWithdrawLimit\n        uint256 sUSD3ValueUSDC = sUSD3Shares.mulDiv(_totalAssets, _totalSupply, Math.Rounding.Floor);\n        uint256 maxDebtUSDC = (sUSD3ValueUSDC * 10_000) / backingRatio;\n\n        return WAUSDC.convertToShares(maxDebtUSDC);\n    }\n\n    /// @dev Effective deployment cap: min(maxOnCredit-based cap, subordination cap). Below 100%, MAX_ON_CREDIT is an\n    /// honest-operation deployment and liquidity-buffer target, not an adversarially enforceable exposure boundary.\n    /// DEBT_CAP is the enforceable boundary: MorphoCredit borrow admission reads debt but never supply, so a temporary\n    /// deposit cannot increase the borrowable total by even one unit.\n    function _effectiveDeployCapWaUSDC(uint256 totalWaUSDC) internal view returns (uint256) {\n        uint256 maxOnCreditCap = (totalWaUSDC * maxOnCredit()) / 10_000;\n        uint256 subCap = _subordinationDeployCapWaUSDC();\n        return Math.min(maxOnCreditCap, subCap);\n    }\n\n    /// @dev Wraps idle USDC into waUSDC via a fallible whole-share mint. Skips (leaving USDC idle,\n    /// counted at face by nav) when paused, below one share, or — on the deposit/tend path\n    /// (enforceSlack) — when the mint's ≤1-unit rounding cost is not covered by realized-but-unreported\n    /// interest, so deposit spam cannot walk totalAssets past nav()+2 and freeze withdrawals.\n    function _wrapUSDC(uint256 amount, bool enforceSlack) private {\n        if (amount == 0 || Pausable(address(WAUSDC)).paused()) return;\n        uint256 shares = WAUSDC.previewDeposit(amount);\n        uint256 maxShares = WAUSDC.maxMint(address(this));\n        if (shares > maxShares) shares = maxShares;\n        if (shares == 0) return;\n        if (enforceSlack) {\n            uint256 aggregate = suppliedWaUSDC() + balanceOfWaUSDC();\n            uint256 baseValue = WAUSDC.convertToAssets(aggregate);\n            uint256 cost = WAUSDC.previewMint(shares);\n            uint256 gain = WAUSDC.convertToAssets(aggregate + shares) - baseValue;\n            if (cost > gain) {\n                uint256 navNow = baseValue + asset.balanceOf(address(this));\n                if (TokenizedStrategy.totalAssets() + (cost - gain) > navNow) return;\n            }\n        }\n        try WAUSDC.mint(shares, address(this)) {} catch {}\n    }\n\n    /// @dev Deploy funds to MorphoCredit market respecting maxOnCredit ratio and subordination cap\n    /// @dev TokenizedStrategy calls this before adding the current deposit to totalAssets, so deployment is deferred\n    /// to the post-deposit hook where the pending-loss predicate needs no deposit compensation.\n    function _deployFunds(uint256) internal override {}\n\n    /// @dev Deploys loose funds after TokenizedStrategy has accounted for the current deposit or mint.\n    function _deployDepositedFunds() private {\n        uint256 amount = asset.balanceOf(address(this));\n        if (amount == 0) return;\n\n        _wrapUSDC(amount, true);\n\n        // A paused wrapper blocks every waUSDC transfer, not just mint and burn, so supplying to Morpho would\n        // revert and take the deposit with it. Hold the funds locally instead; a later tend or report deploys\n        // them once the pause lifts. Mirrors the guard in _applyDeployCap.\n        if (Pausable(address(WAUSDC)).paused()) return;\n\n        uint256 maxOnCreditRatio = maxOnCredit();\n        if (maxOnCreditRatio == 0) {\n            // Don't deploy anything when set to 0%, keep all waUSDC local\n            return;\n        }\n\n        // Calculate total waUSDC (deployed + local)\n        uint256 deployedWaUSDC = suppliedWaUSDC();\n        uint256 localWaUSDC = balanceOfWaUSDC();\n        uint256 totalWaUSDC = deployedWaUSDC + localWaUSDC;\n\n        uint256 maxDeployableWaUSDC = _effectiveDeployCapWaUSDC(totalWaUSDC);\n\n        if (maxDeployableWaUSDC <= deployedWaUSDC) {\n            // Already at or above max, keep all new waUSDC local\n            return;\n        }\n\n        // Deploy only the amount needed to reach max\n        uint256 waUSDCToSupply = Math.min(localWaUSDC, maxDeployableWaUSDC - deployedWaUSDC);\n\n        _supplyToMorpho(waUSDCToSupply);\n    }\n\n    /// @dev Withdraw funds from MorphoCredit market\n    /// @param _amount Amount of asset to free up\n    function _freeFunds(uint256 _amount) internal override {\n        if (_amount == 0) {\n            return;\n        }\n\n        // Calculate how much waUSDC we need\n        uint256 waUSDCNeeded = WAUSDC.previewWithdraw(_amount);\n\n        // Check local waUSDC balance first\n        uint256 localWaUSDC = balanceOfWaUSDC();\n\n        if (localWaUSDC < waUSDCNeeded) {\n            // Need to withdraw from MorphoCredit\n            uint256 waUSDCToWithdraw = waUSDCNeeded - localWaUSDC;\n\n            uint256 withdrawn = _withdrawFromMorpho(waUSDCToWithdraw);\n\n            if (withdrawn > 0) {\n                localWaUSDC = balanceOfWaUSDC();\n            }\n        }\n\n        uint256 waUSDCToUnwrap = Math.min(Math.min(localWaUSDC, waUSDCNeeded), WAUSDC.maxRedeem(address(this)));\n\n        if (waUSDCToUnwrap > 0) {\n            WAUSDC.redeem(waUSDCToUnwrap, address(this), address(this));\n        }\n    }\n\n    /// @dev Emergency withdraw function to free funds from MorphoCredit\n    /// @param amount The amount to withdraw (use type(uint256).max for all)\n    function _emergencyWithdraw(uint256 amount) internal override {\n        // This is called during shutdown to free funds from Morpho\n        // Use _freeFunds which already handles the withdrawal logic\n        _freeFunds(amount);\n    }\n\n    /// @dev Harvest interest from MorphoCredit and report total assets\n    /// @return Total assets held by the strategy\n    function _harvestAndReport() internal override returns (uint256) {\n        MarketParams memory params = _marketParams;\n\n        morphoCredit.accrueInterest(params);\n\n        if (!TokenizedStrategy.isShutdown()) _wrapUSDC(asset.balanceOf(address(this)), false);\n\n        return nav();\n    }\n\n    /// @dev Rebalances between idle and deployed funds to maintain maxOnCredit ratio\n    /// @param _totalIdle Current idle funds available\n    function _tend(uint256 _totalIdle) internal override {\n        if (TokenizedStrategy.isShutdown()) {\n            return;\n        }\n        // First wrap any idle USDC to waUSDC\n        _wrapUSDC(_totalIdle, true);\n\n        _applyDeployCap(true);\n    }\n\n    /// @dev Rebalances deployed waUSDC toward the effective deployment cap.\n    /// Withdraws excess from MorphoCredit when over the cap; otherwise tops up\n    /// deployment from local waUSDC only when supplying is permitted.\n    /// @param allowSupply Whether deploying additional local waUSDC is allowed\n    function _applyDeployCap(bool allowSupply) private {\n        if (Pausable(address(WAUSDC)).paused()) return;\n\n        // Calculate based on waUSDC amounts\n        uint256 deployedWaUSDC = suppliedWaUSDC();\n        uint256 localWaUSDC = balanceOfWaUSDC();\n        uint256 totalWaUSDC = deployedWaUSDC + localWaUSDC;\n\n        uint256 targetDeployedWaUSDC = _effectiveDeployCapWaUSDC(totalWaUSDC);\n\n        if (deployedWaUSDC > targetDeployedWaUSDC) {\n            // Withdraw excess from MorphoCredit\n            uint256 waUSDCToWithdraw = deployedWaUSDC - targetDeployedWaUSDC;\n            _withdrawFromMorpho(waUSDCToWithdraw);\n        } else if (allowSupply && targetDeployedWaUSDC > deployedWaUSDC && localWaUSDC > 0) {\n            // Deploy more if we have local waUSDC\n            uint256 waUSDCToDeploy = Math.min(localWaUSDC, targetDeployedWaUSDC - deployedWaUSDC);\n            _supplyToMorpho(waUSDCToDeploy);\n        }\n    }\n\n    /// @dev Signal keepers when deployment drifts from the effective cap\n    function _tendTrigger() internal view override returns (bool) {\n        if (TokenizedStrategy.isShutdown()) {\n            return false;\n        }\n        if (Pausable(address(WAUSDC)).paused()) return false;\n\n        uint256 deployed = suppliedWaUSDC();\n        uint256 localWaUSDC = balanceOfWaUSDC();\n        uint256 totalWaUSDC = deployed + localWaUSDC;\n        uint256 target = _effectiveDeployCapWaUSDC(totalWaUSDC);\n\n        if (target == 0) return deployed > 0;\n\n        IProtocolConfig config = _protocolConfig();\n        uint256 driftBps = config.config(ProtocolConfigLib.TEND_DRIFT_THRESHOLD);\n        if (driftBps == 0) driftBps = 10;\n        require(driftBps < 10_000);\n        uint256 threshold = (target * driftBps) / 10_000;\n\n        if (deployed > target) {\n            return (deployed - target) > threshold;\n        }\n        if (target > deployed && localWaUSDC > 0 && !_pendingLoss()) {\n            return (target - deployed) > threshold;\n        }\n        return false;\n    }\n\n    /// @dev Helper function to supply waUSDC to MorphoCredit. Skips silently under a pending loss (report() owns\n    /// recognition); a supply the market rejects is deferred to a later tend or report and surfaced by the event.\n    /// @param amount Amount of waUSDC to supply\n    /// @return supplied Actual amount supplied (for consistency with withdraw helper)\n    function _supplyToMorpho(uint256 amount) internal returns (uint256 supplied) {\n        if (amount == 0 || _pendingLoss()) return 0;\n\n        try morphoCredit.supply(_marketParams, amount, 0, address(this), \"\") returns (uint256, uint256) {\n            return amount;\n        } catch {\n            emit RebalanceDeferred(amount);\n            return 0;\n        }\n    }\n\n    /// @dev Helper function to withdraw waUSDC from MorphoCredit\n    /// @param amountRequested Amount of waUSDC to withdraw\n    /// @return amountWithdrawn Actual amount withdrawn (may be less than requested)\n    function _withdrawFromMorpho(uint256 amountRequested) internal returns (uint256 amountWithdrawn) {\n        if (amountRequested == 0) return 0;\n\n        morphoCredit.accrueInterest(_marketParams);\n        (uint256 shares, uint256 waUSDCMax, uint256 waUSDCLiquidity) = getPosition();\n\n        uint256 availableWaUSDC = Math.min(waUSDCMax, waUSDCLiquidity);\n\n        if (availableWaUSDC == 0) {\n            return 0;\n        }\n\n        amountWithdrawn = Math.min(amountRequested, availableWaUSDC);\n\n        if (amountWithdrawn > 0) {\n            if (amountWithdrawn >= waUSDCMax) {\n                morphoCredit.withdraw(_marketParams, 0, shares, address(this), address(this));\n            } else {\n                morphoCredit.withdraw(_marketParams, amountWithdrawn, 0, address(this), address(this));\n            }\n        }\n\n        return amountWithdrawn;\n    }\n\n    function _waUSDCGlobalRedeemable() internal view returns (uint256) {\n        return WAUSDC.convertToShares(WAUSDC.POOL().getVirtualUnderlyingBalance(WAUSDC.asset()));\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    PUBLIC VIEW FUNCTIONS (OVERRIDES)\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Returns the withdrawable assets for an owner after liquidity and floor checks.\n    /// @dev The bps floor is a scaling/rate knob applied to then-current total assets, so repeated redemptions drain\n    /// geometrically toward the nominal floor. The nominal floor is the hard ring-fence and should be set alongside\n    /// the bps floor whenever a fixed asset amount must remain reserved.\n    /// @return Maximum amount that can be withdrawn\n    function availableWithdrawLimit(address) public view override returns (uint256) {\n        // Get available liquidity first\n        uint256 idleAsset = asset.balanceOf(address(this));\n        uint256 totalAssets = TokenizedStrategy.totalAssets();\n\n        // Loss-waterfall guard: while nav trails totalAssets, an unrealized loss is pending, so halt withdrawals until\n        // report() applies the locked-profit-then-sUSD3 waterfall rather than paying exiting senior holders at a stale\n        // price. The +2 tolerance absorbs the <=1-unit waUSDC wrap/unwrap rounding drift. Deposit-side drift is\n        // gated at the source in _wrapUSDC (enforceSlack); the withdraw-side redeem can still nudge the gap past +2,\n        // but that halt is transient and liveness-only: nav() converts at the live waUSDC rate, so accruing interest\n        // lifts nav() back over totalAssets on its own, and report() re-bases totalAssets to nav definitively. No\n        // funds are at risk, so the residual withdraw-side drift is accepted rather than tracked in mutable state\n        // under this guard.\n        if (_pendingLoss()) {\n            return 0;\n        }\n\n        (, uint256 waUSDCMax, uint256 waUSDCLiquidity) = getPosition();\n\n        uint256 availableWaUSDC;\n\n        if (Pausable(address(WAUSDC)).paused()) {\n            availableWaUSDC = 0;\n        } else {\n            uint256 localWaUSDC = balanceOfWaUSDC();\n            uint256 morphoWaUSDC = Math.min(waUSDCMax, waUSDCLiquidity);\n            uint256 totalRedeemableWaUSDC = localWaUSDC + morphoWaUSDC;\n\n            if (totalRedeemableWaUSDC > 0) {\n                if (WAUSDC.maxRedeem(address(this)) == 0 && WAUSDC.maxRedeem(address(morphoCredit)) == 0) {\n                    availableWaUSDC = 0;\n                } else {\n                    availableWaUSDC = Math.min(totalRedeemableWaUSDC, _waUSDCGlobalRedeemable());\n                }\n            }\n        }\n\n        uint256 availableLiquidity = idleAsset + WAUSDC.convertToAssets(availableWaUSDC);\n\n        // During shutdown, bypass the going-concern redemption constraints below.\n        if (TokenizedStrategy.isShutdown()) {\n            return availableLiquidity;\n        }\n\n        // The fence reserves realized cash liquidity; nominal and bps floors reserve against totalAssets below.\n        availableLiquidity = Math.saturatingSub(availableLiquidity, ringFencedLiquidity);\n\n        IProtocolConfig config = _protocolConfig();\n        uint256 nominalFloor = config.config(ProtocolConfigLib.USD3_REDEMPTION_FLOOR);\n        uint256 floorBps = config.config(ProtocolConfigLib.USD3_REDEMPTION_FLOOR_BPS);\n        if (floorBps > MAX_BPS) floorBps = MAX_BPS;\n        uint256 bpsFloor = totalAssets.mulDiv(floorBps, MAX_BPS);\n        uint256 floor = Math.max(nominalFloor, bpsFloor);\n\n        return Math.min(availableLiquidity, Math.saturatingSub(totalAssets, floor));\n    }\n\n    /// @dev Returns available deposit limit, enforcing borrower restrictions and supply cap\n    /// @param _owner Address to check limit for\n    /// @return Maximum amount that can be deposited\n    function availableDepositLimit(address _owner) public view override returns (uint256) {\n        if (!supplyCapExempt[_owner] && Pausable(address(WAUSDC)).paused()) {\n            return 0;\n        }\n\n        // Block deposits from borrowers\n        if (morphoCredit.borrowShares(marketId, _owner) > 0) {\n            return 0;\n        }\n\n        uint256 cap = _protocolConfig().config(ProtocolConfigLib.USD3_SUPPLY_CAP);\n        if (cap == 0) {\n            return 0;\n        }\n        if (supplyCapExempt[_owner] || cap == type(uint256).max) {\n            return type(uint256).max;\n        }\n\n        uint256 currentTotalAssets = TokenizedStrategy.totalAssets();\n        if (cap <= currentTotalAssets) {\n            return 0;\n        }\n\n        uint256 headroom = cap - currentTotalAssets;\n        uint256 maxShares = TokenizedStrategy.convertToShares(headroom);\n        if (maxShares == 0) {\n            // Zero-share headroom is unexecutable for every receiver.\n            return 0;\n        }\n\n        uint256 minimum = minDeposit;\n        if (minimum == 0 || TokenizedStrategy.balanceOf(_owner) != 0) {\n            return headroom;\n        }\n        if (headroom < minimum || TokenizedStrategy.previewMint(maxShares) < minimum) {\n            // Deliberately under-advertise one executable maxDeposit value for fresh receivers in this narrow\n            // band instead of advertising a maxMint value that reverts.\n            return 0;\n        }\n        return headroom;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        HOOKS IMPLEMENTATION\n    //////////////////////////////////////////////////////////////*/\n\n    /// @dev Requires exempt receivers to self-deposit and enforces the first-time minimum for non-exempt receivers.\n    function _preDepositHook(uint256 assets, uint256 shares, address receiver) internal override {\n        if (assets == 0 && shares > 0) {\n            assets = TokenizedStrategy.previewMint(shares);\n        }\n\n        // Handle type(uint256).max case - resolve to actual balance\n        if (assets == type(uint256).max) {\n            assets = asset.balanceOf(msg.sender);\n        }\n\n        bool exempt = supplyCapExempt[receiver];\n        require(!exempt || msg.sender == receiver, \"!self\");\n\n        // Enforce minimum deposit only for first-time depositors\n        uint256 currentBalance = TokenizedStrategy.balanceOf(receiver);\n        if (currentBalance == 0 && !exempt) {\n            require(assets >= minDeposit, \"<min\");\n        }\n    }\n\n    /// @dev Accumulates ring-fenced liquidity for conduit self-deposits.\n    function _postDepositHook(uint256 assets, uint256 shares, address receiver) internal override {\n        if (msg.sender == receiver && ringFenceConduit[receiver]) {\n            if (assets == type(uint256).max) assets = TokenizedStrategy.convertToAssets(shares);\n            ringFencedLiquidity += assets;\n            emit RingFencedLiquidityIncreased(receiver, assets, ringFencedLiquidity);\n        }\n\n        _deployDepositedFunds();\n    }\n\n    /**\n     * @notice Report profit and loss with pre-report context for accurate loss absorption\n     * @return profit Amount of profit generated\n     * @return loss Amount of loss incurred\n     */\n    function report() external override returns (uint256 profit, uint256 loss) {\n        uint256 preSupply = TokenizedStrategy.totalSupply();\n        uint256 preAssets = TokenizedStrategy.totalAssets();\n\n        _preReportHook();\n        (profit, loss) = _reportInternal();\n        _postReportHook(loss, preAssets, preSupply);\n    }\n\n    /// @dev Handles loss absorption and post-report rebalancing.\n    function _postReportHook(uint256 loss, uint256 preAssets, uint256 preSupply) internal {\n        if (loss > 0 && sUSD3 != address(0) && preAssets > 0 && preSupply > 0) {\n            // Get sUSD3's current USD3 balance\n            uint256 susd3Balance = TokenizedStrategy.balanceOf(sUSD3);\n\n            if (susd3Balance > 0) {\n                // Total shares required to cover the loss at the pre-report PPS\n                uint256 totalBurnNeeded = loss.mulDiv(preSupply, preAssets, Math.Rounding.Floor);\n\n                // Internal burn from locked shares is reflected in the post-report totalSupply\n                uint256 postSupply = TokenizedStrategy.totalSupply();\n                uint256 lockedBurn = preSupply > postSupply ? preSupply - postSupply : 0;\n\n                // Burn only the remaining shares from sUSD3\n                uint256 sharesToBurn = totalBurnNeeded > lockedBurn ? totalBurnNeeded - lockedBurn : 0;\n\n                // Cap at sUSD3's actual balance - they can't lose more than they have\n                if (sharesToBurn > susd3Balance) {\n                    sharesToBurn = susd3Balance;\n                }\n\n                if (sharesToBurn > 0) {\n                    _burnSharesFromSusd3(sharesToBurn);\n                }\n            }\n        }\n\n        _tend(asset.balanceOf(address(this)));\n    }\n\n    /// @dev Post-transfer hook that rebalances deployment after sUSD3 unstakes.\n    /// When sUSD3 transfers out USD3 shares its subordination backing shrinks, so the\n    /// deployment cap is re-applied (withdraw-only) to pull any excess back from MorphoCredit.\n    /// Skipped during shutdown.\n    /// @param from Address transferring shares\n    /// @param amount Amount of shares being transferred\n    function _postTransferHook(address from, address, uint256 amount, bool success) internal override {\n        if (success && amount > 0 && from == sUSD3 && !TokenizedStrategy.isShutdown()) _applyDeployCap(false);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    INTERNAL HELPER FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Directly burn shares from sUSD3's balance using storage manipulation\n     *\n     * IMPORTANT: Direct storage manipulation is necessary here because TokenizedStrategy\n     * does not expose a public burn function. The only ways to burn shares in\n     * TokenizedStrategy are through withdraw/redeem (which require asset transfers)\n     * or internal profit/loss accounting. Since we need to burn sUSD3's shares\n     * without triggering asset transfers, direct storage manipulation is the only\n     * viable approach.\n     *\n     * @param amount Number of shares to burn from sUSD3\n     */\n    function _burnSharesFromSusd3(uint256 amount) internal {\n        // Calculate storage slots using the library\n        bytes32 totalSupplySlot = TokenizedStrategyStorageLib.totalSupplySlot();\n        bytes32 balanceSlot = TokenizedStrategyStorageLib.balancesSlot(sUSD3);\n\n        // Read current values\n        uint256 currentBalance;\n        uint256 currentTotalSupply;\n        assembly {\n            currentBalance := sload(balanceSlot)\n            currentTotalSupply := sload(totalSupplySlot)\n        }\n\n        // Ensure we don't burn more than available\n        uint256 actualBurn = amount;\n        if (actualBurn > currentBalance) {\n            actualBurn = currentBalance;\n        }\n\n        // Update storage\n        assembly {\n            sstore(balanceSlot, sub(currentBalance, actualBurn))\n            sstore(totalSupplySlot, sub(currentTotalSupply, actualBurn))\n        }\n\n        // Emit Transfer event to address(0) for transparency\n        emit IERC20.Transfer(sUSD3, address(0), actualBurn);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        PUBLIC VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Get the balance of waUSDC held locally (not deployed to MorphoCredit)\n     * @return Amount of waUSDC held in this contract\n     */\n    function balanceOfWaUSDC() public view returns (uint256) {\n        return WAUSDC.balanceOf(address(this));\n    }\n\n    /**\n     * @notice Get the amount of waUSDC supplied to MorphoCredit\n     * @return Amount of waUSDC deployed to the lending market\n     */\n    function suppliedWaUSDC() public view returns (uint256) {\n        return morphoCredit.expectedSupplyAssets(_marketParams, address(this));\n    }\n\n    /// @dev Net asset value of the strategy in USDC terms\n    /// @return Sum of deployed and local waUSDC converted to assets, plus idle USDC held by the strategy\n    function nav() public view returns (uint256) {\n        return WAUSDC.convertToAssets(suppliedWaUSDC() + balanceOfWaUSDC()) + asset.balanceOf(address(this));\n    }\n\n    /**\n     * @notice Get the maximum percentage of funds to deploy to credit markets from ProtocolConfig\n     * @return Maximum deployment ratio in basis points (10000 = 100%)\n     * @dev Returns the value from ProtocolConfig directly. If not configured in ProtocolConfig,\n     *      it returns 0, effectively preventing deployment until explicitly configured.\n     * @dev Below 100%, this is an honest-operation deployment and liquidity-buffer target, not an adversarially\n     *      enforceable exposure boundary. DEBT_CAP is the enforceable boundary: MorphoCredit borrow admission reads\n     *      debt but never supply, so a temporary deposit cannot increase the borrowable total by even one unit.\n     */\n    function maxOnCredit() public view returns (uint256) {\n        IProtocolConfig config = _protocolConfig();\n        return config.getMaxOnCredit();\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        MANAGEMENT FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Set the sUSD3 subordinate strategy address\n     * @param _sUSD3 Address of the sUSD3 strategy\n     * @dev Only callable by management. After calling, also set performance fee recipient.\n     */\n    function setSUSD3(address _sUSD3) external onlyManagement {\n        require(sUSD3 == address(0));\n        require(_sUSD3 != address(0));\n\n        sUSD3 = _sUSD3;\n        emit SUSD3StrategyUpdated(address(0), _sUSD3);\n\n        // NOTE: After calling this, management should also call:\n        // ITokenizedStrategy(usd3Address).setPerformanceFeeRecipient(_sUSD3)\n        // to ensure yield distribution goes to sUSD3\n    }\n\n    /**\n     * @notice Update supply-cap and first-time minimum-deposit exemption status for a receiver.\n     * @dev An exempt receiver may only be deposited to by itself. A third party depositing directly to that exempt\n     * receiver reverts. Helper is the USD3 receiver only on its hop path, and its user-level limit check still applies\n     * the supply cap and borrower restriction before the deposit. Exempting Helper therefore bypasses only the\n     * receiver-level first-time minimum for that path; it does not affect the non-hop path, whose receiver is the user.\n     * @dev Pair this flag operationally with `ringFenceConduit`. When both flags are set, every accepted deposit is a\n     * self-deposit and receives ring-fence credit. Revoking this exemption while leaving the conduit flag set permits\n     * third-party deposits that receive no ring-fence credit. LCC deployment grants both flags atomically; revoke them\n     * atomically as well.\n     * @param _account Receiver address to update.\n     * @param _exempt True to require self-deposits that bypass supply-cap headroom and first-time minimum-deposit\n     * checks; false to allow third-party deposits and apply the ordinary checks.\n     */\n    function setSupplyCapExempt(address _account, bool _exempt) external onlyManagement {\n        supplyCapExempt[_account] = _exempt;\n        emit SupplyCapExemptUpdated(_account, _exempt);\n    }\n\n    /**\n     * @notice Update whether a conduit self-deposit adds to ring-fenced liquidity.\n     * @dev Pair this flag operationally with `supplyCapExempt`. When both flags are set, every accepted deposit is a\n     * self-deposit and receives ring-fence credit. Revoking the exemption while leaving this conduit flag set permits\n     * third-party deposits that receive no ring-fence credit. LCC deployment grants both flags atomically; revoke them\n     * atomically as well.\n     * @param _conduit Receiver address to update.\n     * @param _enabled True to accumulate self-deposits into the ring fence, false to disable accumulation.\n     */\n    function setRingFenceConduit(address _conduit, bool _enabled) external onlyManagement {\n        ringFenceConduit[_conduit] = _enabled;\n        emit RingFenceConduitUpdated(_conduit, _enabled);\n    }\n\n    /**\n     * @notice Release ring-fenced liquidity back into the withdrawable liquidity calculation.\n     * @param _assets Amount of fenced liquidity to release, in USDC asset units.\n     */\n    function releaseRingFence(uint256 _assets) external onlyManagement {\n        require(_assets <= ringFencedLiquidity, \"!fence\");\n        ringFencedLiquidity -= _assets;\n        emit RingFenceReleased(_assets, ringFencedLiquidity);\n    }\n\n    /**\n     * @notice Set minimum deposit amount\n     * @param _minDeposit Minimum amount required for deposits\n     */\n    function setMinDeposit(uint256 _minDeposit) external onlyManagement {\n        minDeposit = _minDeposit;\n        emit MinDepositUpdated(_minDeposit);\n    }\n\n    /// @notice Set the profit unlock time without releasing locked profit ahead of an unreported loss.\n    /// @dev Nonzero updates retain the TokenizedStrategy implementation's behavior.\n    function setProfitMaxUnlockTime(uint256 _profitMaxUnlockTime) external onlyManagement {\n        require(_profitMaxUnlockTime != 0 || !_pendingLoss(), \"!loss\");\n        _delegateCall(msg.data);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        KEEPER FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Sync the tranche share (performance fee) from ProtocolConfig\n     * @dev Reads TRANCHE_SHARE_VARIANT from ProtocolConfig and updates local storage\n     *\n     * IMPORTANT: Direct storage manipulation is necessary here because TokenizedStrategy's\n     * setPerformanceFee() function has a hardcoded MAX_FEE limit of 5000 (50%). Since we\n     * need to support higher fee distributions to sUSD3 (potentially up to 100% for full\n     * subordination scenarios), we must bypass this restriction by directly modifying the\n     * storage slot.\n     *\n     * Storage layout in TokenizedStrategy (slot 9):\n     * - Bits 0-31: profitMaxUnlockTime (uint32)\n     * - Bits 32-47: performanceFee (uint16) <- We modify this\n     * - Bits 48-207: performanceFeeRecipient (address)\n     *\n     * @dev Only callable by keepers to ensure controlled updates\n     */\n    function syncTrancheShare() external onlyKeepers {\n        // Deliberately does not report: operators should report immediately before changing the tranche share variant.\n        // This keeps loss recognition and junior-share burning separate; any repricing is operator-managed.\n\n        // Get the protocol config through MorphoCredit\n        IProtocolConfig config = _protocolConfig();\n\n        // Read the tranche share variant (yield share to sUSD3 in basis points)\n        uint256 trancheShare = config.getTrancheShareVariant();\n        require(trancheShare <= 10_000);\n\n        // Get the storage slot for performanceFee using the library\n        bytes32 targetSlot = TokenizedStrategyStorageLib.profitConfigSlot();\n\n        // Read current slot value\n        uint256 currentSlotValue;\n        assembly {\n            currentSlotValue := sload(targetSlot)\n        }\n\n        // Clear the performanceFee bits (32-47) and set new value\n        uint256 mask = ~(uint256(0xFFFF) << 32);\n        uint256 newSlotValue = (currentSlotValue & mask) | (trancheShare << 32);\n\n        // Write back to storage\n        assembly {\n            sstore(targetSlot, newSlotValue)\n        }\n\n        emit TrancheShareSynced(trancheShare);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        STORAGE GAP\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[37] private __gap;\n}\n"},"src/usd3/base/BaseHooksUpgradeable.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0\npragma solidity >=0.8.18;\n\nimport {BaseStrategyUpgradeable} from \"./BaseStrategyUpgradeable.sol\";\nimport {Hooks} from \"@periphery/Bases/Hooks/Hooks.sol\";\nimport {ITokenizedStrategy} from \"@tokenized-strategy/interfaces/ITokenizedStrategy.sol\";\n\n/**\n * @title BaseHooksUpgradeable\n * @author Yearn's BaseHooks adapted for upgradeable strategies\n * @notice This contract can be inherited by any strategy wishing to implement\n *         pre or post hooks for deposit, withdraw, transfer, or report functions.\n *\n *         This version:\n *         - Inherits from BaseStrategyUpgradeable instead of BaseHealthCheck\n *         - Uses Yearn's Hooks contract for standardized hook interfaces\n *         - Is compatible with upgradeable proxy patterns\n */\nabstract contract BaseHooksUpgradeable is BaseStrategyUpgradeable, Hooks {\n    /*//////////////////////////////////////////////////////////////\n                            CONSTANTS\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal constant MAX_BPS = 10_000;\n\n    /*//////////////////////////////////////////////////////////////\n                        OVERRIDDEN FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Deposit assets and receive shares\n     * @param assets Amount of assets to deposit\n     * @param receiver Address to receive the shares\n     * @return shares Amount of shares minted\n     */\n    function deposit(uint256 assets, address receiver) external virtual returns (uint256 shares) {\n        _preDepositHook(assets, shares, receiver);\n        shares = abi.decode(\n            _delegateCall(abi.encodeCall(ITokenizedStrategy(address(this)).deposit, (assets, receiver))), (uint256)\n        );\n        _postDepositHook(assets, shares, receiver);\n    }\n\n    /**\n     * @notice Mint shares by depositing assets\n     * @param shares Amount of shares to mint\n     * @param receiver Address to receive the shares\n     * @return assets Amount of assets deposited\n     */\n    function mint(uint256 shares, address receiver) external virtual returns (uint256 assets) {\n        _preDepositHook(assets, shares, receiver);\n        assets = abi.decode(\n            _delegateCall(abi.encodeCall(ITokenizedStrategy(address(this)).mint, (shares, receiver))), (uint256)\n        );\n        _postDepositHook(assets, shares, receiver);\n    }\n\n    /**\n     * @notice Withdraw assets by burning shares\n     * @param assets Amount of assets to withdraw\n     * @param receiver Address to receive the assets\n     * @param owner Address whose shares are burned\n     * @return shares Amount of shares burned\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external virtual returns (uint256 shares) {\n        return withdraw(assets, receiver, owner, 0);\n    }\n\n    /**\n     * @notice Withdraw assets with custom max loss\n     * @param assets Amount of assets to withdraw\n     * @param receiver Address to receive the assets\n     * @param owner Address whose shares are burned\n     * @param maxLoss Maximum acceptable loss in basis points\n     * @return shares Amount of shares burned\n     */\n    function withdraw(uint256 assets, address receiver, address owner, uint256 maxLoss)\n        public\n        virtual\n        returns (uint256 shares)\n    {\n        _preWithdrawHook(assets, shares, receiver, owner, maxLoss);\n        shares = abi.decode(\n            _delegateCall(\n                abi.encodeWithSelector(ITokenizedStrategy.withdraw.selector, assets, receiver, owner, maxLoss)\n            ),\n            (uint256)\n        );\n        _postWithdrawHook(assets, shares, receiver, owner, maxLoss);\n    }\n\n    /**\n     * @notice Redeem shares for assets\n     * @param shares Amount of shares to redeem\n     * @param receiver Address to receive the assets\n     * @param owner Address whose shares are burned\n     * @return assets Amount of assets withdrawn\n     */\n    function redeem(uint256 shares, address receiver, address owner) external virtual returns (uint256 assets) {\n        return redeem(shares, receiver, owner, MAX_BPS);\n    }\n\n    /**\n     * @notice Redeem shares with custom max loss\n     * @param shares Amount of shares to redeem\n     * @param receiver Address to receive the assets\n     * @param owner Address whose shares are burned\n     * @param maxLoss Maximum acceptable loss in basis points\n     * @return assets Amount of assets withdrawn\n     */\n    function redeem(uint256 shares, address receiver, address owner, uint256 maxLoss)\n        public\n        virtual\n        returns (uint256 assets)\n    {\n        _preWithdrawHook(assets, shares, receiver, owner, maxLoss);\n        assets = abi.decode(\n            _delegateCall(abi.encodeWithSelector(ITokenizedStrategy.redeem.selector, shares, receiver, owner, maxLoss)),\n            (uint256)\n        );\n        _postWithdrawHook(assets, shares, receiver, owner, maxLoss);\n    }\n\n    /**\n     * @notice Transfer shares to another address\n     * @param to Address to receive the shares\n     * @param amount Amount of shares to transfer\n     * @return success Whether the transfer succeeded\n     */\n    function transfer(address to, uint256 amount) external virtual returns (bool) {\n        _preTransferHook(msg.sender, to, amount);\n        bool success =\n            abi.decode(_delegateCall(abi.encodeCall(ITokenizedStrategy(address(this)).transfer, (to, amount))), (bool));\n        _postTransferHook(msg.sender, to, amount, success);\n        return success;\n    }\n\n    /**\n     * @notice Transfer shares from one address to another\n     * @param from Address to transfer from\n     * @param to Address to transfer to\n     * @param amount Amount of shares to transfer\n     * @return success Whether the transfer succeeded\n     */\n    function transferFrom(address from, address to, uint256 amount) external virtual returns (bool) {\n        _preTransferHook(from, to, amount);\n        bool success = abi.decode(\n            _delegateCall(abi.encodeCall(ITokenizedStrategy(address(this)).transferFrom, (from, to, amount))), (bool)\n        );\n        _postTransferHook(from, to, amount, success);\n        return success;\n    }\n\n    /**\n     * @notice Report profit and loss\n     * @return profit Amount of profit generated\n     * @return loss Amount of loss incurred\n     */\n    function report() external virtual returns (uint256 profit, uint256 loss) {\n        _preReportHook();\n        (profit, loss) = _reportInternal();\n        _postReportHook(profit, loss);\n    }\n\n    /**\n     * @dev Internal report execution hook to centralize delegatecall logic.\n     */\n    function _reportInternal() internal returns (uint256 profit, uint256 loss) {\n        (profit, loss) =\n            abi.decode(_delegateCall(abi.encodeCall(ITokenizedStrategy(address(this)).report, ())), (uint256, uint256));\n    }\n}\n"},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.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    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\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     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\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 cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"},"lib/openzeppelin/contracts/utils/math/Math.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(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 ternary(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 towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n        for (uint256 i = 0; i < byteArray.length; ++i) {\n            if (byteArray[i] != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},"src/interfaces/IMorpho.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.18;\n\ntype Id is bytes32;\n\nstruct MarketParams {\n    address loanToken;\n    address collateralToken;\n    address oracle;\n    address irm;\n    uint256 lltv;\n    address creditLine;\n}\n\n/// @dev Warning: For `feeRecipient`, `supplyShares` does not contain the accrued shares since the last interest\n/// accrual.\nstruct Position {\n    uint256 supplyShares;\n    uint128 borrowShares;\n    uint128 collateral;\n}\n\n/// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual.\n/// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.\n/// @dev Warning: `totalSupplyShares` does not contain the additional shares accrued by `feeRecipient` since the last\n/// interest accrual.\n/// @dev Warning: `totalMarkdownAmount` may be stale as markdowns are only updated when borrowers are touched.\nstruct Market {\n    uint128 totalSupplyAssets;\n    uint128 totalSupplyShares;\n    uint128 totalBorrowAssets;\n    uint128 totalBorrowShares;\n    uint128 lastUpdate;\n    uint128 fee;\n    uint128 totalMarkdownAmount; // Running tally of all borrower markdowns\n}\n\n/// @notice Per-borrower premium tracking\n/// @param lastAccrualTime Timestamp of the last premium accrual for this borrower\n/// @param rate Current risk premium rate per second (scaled by WAD)\n/// @param borrowAssetsAtLastAccrual Snapshot of borrow position at last premium accrual\nstruct BorrowerPremium {\n    uint128 lastAccrualTime;\n    uint128 rate;\n    uint128 borrowAssetsAtLastAccrual;\n}\n\n/// @notice Repayment tracking structures\nenum RepaymentStatus {\n    Current,\n    GracePeriod,\n    Delinquent,\n    Default\n}\n\nstruct PaymentCycle {\n    uint256 endDate;\n}\n\nstruct RepaymentObligation {\n    uint128 paymentCycleId;\n    uint128 amountDue;\n    uint128 endingBalance;\n}\n\n/// @notice Markdown state for tracking defaulted debt value reduction\n/// @param lastCalculatedMarkdown Markdown currently applied to the market for this borrower; may be less than the\n/// requested markdown when the supply-share price floor truncated the increase\n/// @param inDefault Default-entry latch: 1 once the borrower's default entry has been processed, 0 otherwise.\n/// State written before this field existed carries 0 while in default, so a nonzero applied markdown also counts\n/// as a processed entry\nstruct MarkdownState {\n    uint128 lastCalculatedMarkdown;\n    uint128 inDefault;\n}\n\nstruct Authorization {\n    address authorizer;\n    address authorized;\n    bool isAuthorized;\n    uint256 nonce;\n    uint256 deadline;\n}\n\nstruct Signature {\n    uint8 v;\n    bytes32 r;\n    bytes32 s;\n}\n\n/// @dev This interface is used for factorizing IMorphoStaticTyping and IMorpho.\n/// @dev Consider using the IMorpho interface instead of this one.\ninterface IMorphoBase {\n    /// @notice The EIP-712 domain separator.\n    /// @dev Warning: Every EIP-712 signed message based on this domain separator can be reused on chains sharing the\n    /// same chain id and on forks because the domain separator would be the same.\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n    /// @notice The owner of the contract.\n    /// @dev It has the power to change the owner.\n    /// @dev It has the power to set fees on markets and set the fee recipient.\n    /// @dev It has the power to enable but not disable IRMs and LLTVs.\n    function owner() external view returns (address);\n\n    /// @notice The fee recipient of all markets.\n    /// @dev The recipient receives the fees of a given market through a supply position on that market.\n    function feeRecipient() external view returns (address);\n\n    /// @notice Whether the `irm` is enabled.\n    function isIrmEnabled(address irm) external view returns (bool);\n\n    /// @notice Whether the `lltv` is enabled.\n    function isLltvEnabled(uint256 lltv) external view returns (bool);\n\n    /// @notice The `authorizer`'s current nonce. Used to prevent replay attacks with EIP-712 signatures.\n    function nonce(address authorizer) external view returns (uint256);\n\n    /// @notice Sets `newOwner` as `owner` of the contract.\n    /// @dev Warning: No two-step transfer ownership.\n    /// @dev Warning: The owner can be set to the zero address.\n    function setOwner(address newOwner) external;\n\n    /// @notice Enables `irm` as a possible IRM for market creation.\n    /// @dev Warning: It is not possible to disable an IRM.\n    function enableIrm(address irm) external;\n\n    /// @notice Enables `lltv` as a possible LLTV for market creation.\n    /// @dev Warning: It is not possible to disable a LLTV.\n    function enableLltv(uint256 lltv) external;\n\n    /// @notice Sets the `newFee` for the given market `marketParams`.\n    /// @param newFee The new fee, scaled by WAD.\n    /// @dev Warning: The recipient can be the zero address.\n    function setFee(MarketParams memory marketParams, uint256 newFee) external;\n\n    /// @notice Sets `newFeeRecipient` as `feeRecipient` of the fee.\n    /// @dev Warning: If the fee recipient is set to the zero address, fees will accrue there and will be lost.\n    /// @dev Modifying the fee recipient will allow the new recipient to claim any pending fees not yet accrued. To\n    /// ensure that the current recipient receives all due fees, accrue interest manually prior to making any changes.\n    function setFeeRecipient(address newFeeRecipient) external;\n\n    /// @notice Creates the market `marketParams`.\n    /// @dev Here is the list of assumptions on the market's dependencies (tokens, IRM and oracle) that guarantees\n    /// Morpho behaves as expected:\n    /// - The token should be ERC-20 compliant, except that it can omit return values on `transfer` and `transferFrom`.\n    /// - The token balance of Morpho should only decrease on `transfer` and `transferFrom`. In particular, tokens with\n    /// burn functions are not supported.\n    /// - The token should not re-enter Morpho on `transfer` nor `transferFrom`.\n    /// - The token balance of the sender (resp. receiver) should decrease (resp. increase) by exactly the given amount\n    /// on `transfer` and `transferFrom`. In particular, tokens with fees on transfer are not supported.\n    /// - The IRM should not re-enter Morpho.\n    /// - The oracle should return a price with the correct scaling.\n    /// @dev Here is a list of assumptions on the market's dependencies which, if broken, could break Morpho's liveness\n    /// properties (funds could get stuck):\n    /// - The token should not revert on `transfer` and `transferFrom` if balances and approvals are right.\n    /// - The amount of assets supplied and borrowed should not go above ~1e35 (otherwise the computation of\n    /// `toSharesUp` and `toSharesDown` can overflow).\n    /// - The IRM should not revert on `borrowRate`.\n    /// - The IRM should not return a very high borrow rate (otherwise the computation of `interest` in\n    /// `_accrueInterest` can overflow).\n    /// - The oracle should not revert `price`.\n    /// - The oracle should not return a very high price (otherwise the computation of `maxBorrow` in `_isHealthy` or of\n    /// `assetsRepaid` in `liquidate` can overflow).\n    /// @dev The borrow share price of a market with less than 1e4 assets borrowed can be decreased by manipulations, to\n    /// the point where `totalBorrowShares` is very large and borrowing overflows.\n    function createMarket(MarketParams memory marketParams) external;\n\n    /// @notice Supplies `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's\n    /// `onMorphoSupply` function with the given `data`.\n    /// @dev Either `assets` or `shares` should be zero. Most use cases should rely on `assets` as an input so the\n    /// caller is guaranteed to have `assets` tokens pulled from their balance, but the possibility to mint a specific\n    /// amount of shares is given for full compatibility and precision.\n    /// @dev Supplying a large amount can revert for overflow.\n    /// @dev Supplying an amount of shares may lead to supply more or fewer assets than expected due to slippage.\n    /// Consider using the `assets` parameter to avoid this.\n    /// @param marketParams The market to supply assets to.\n    /// @param assets The amount of assets to supply.\n    /// @param shares The amount of shares to mint.\n    /// @param onBehalf The address that will own the increased supply position.\n    /// @param data Arbitrary data to pass to the `onMorphoSupply` callback. Pass empty data if not needed.\n    /// @return assetsSupplied The amount of assets supplied.\n    /// @return sharesSupplied The amount of shares minted.\n    function supply(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        bytes memory data\n    ) external returns (uint256 assetsSupplied, uint256 sharesSupplied);\n\n    /// @notice Withdraws `assets` or `shares` on behalf of `onBehalf` and sends the assets to `receiver`.\n    /// @dev Either `assets` or `shares` should be zero. To withdraw max, pass the `shares`'s balance of `onBehalf`.\n    /// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.\n    /// @dev Withdrawing an amount corresponding to more shares than supplied will revert for underflow.\n    /// @dev It is advised to use the `shares` input when withdrawing the full position to avoid reverts due to\n    /// conversion roundings between shares and assets.\n    /// @param marketParams The market to withdraw assets from.\n    /// @param assets The amount of assets to withdraw.\n    /// @param shares The amount of shares to burn.\n    /// @param onBehalf The address of the owner of the supply position.\n    /// @param receiver The address that will receive the withdrawn assets.\n    /// @return assetsWithdrawn The amount of assets withdrawn.\n    /// @return sharesWithdrawn The amount of shares burned.\n    function withdraw(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        address receiver\n    ) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);\n\n    /// @notice Borrows `assets` or `shares` on behalf of `onBehalf` and sends the assets to `receiver`.\n    /// @dev Either `assets` or `shares` should be zero. Most use cases should rely on `assets` as an input so the\n    /// caller is guaranteed to borrow `assets` of tokens, but the possibility to mint a specific amount of shares is\n    /// given for full compatibility and precision.\n    /// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.\n    /// @dev Borrowing a large amount can revert for overflow.\n    /// @dev Borrowing an amount of shares may lead to borrow fewer assets than expected due to slippage.\n    /// Consider using the `assets` parameter to avoid this.\n    /// @param marketParams The market to borrow assets from.\n    /// @param assets The amount of assets to borrow.\n    /// @param shares The amount of shares to mint.\n    /// @param onBehalf The address that will own the increased borrow position.\n    /// @param receiver The address that will receive the borrowed assets.\n    /// @return assetsBorrowed The amount of assets borrowed.\n    /// @return sharesBorrowed The amount of shares minted.\n    function borrow(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        address receiver\n    ) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed);\n\n    /// @notice Repays `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's\n    /// `onMorphoRepay` function with the given `data`.\n    /// @dev Either `assets` or `shares` should be zero. To repay max, pass the `shares`'s balance of `onBehalf`.\n    /// @dev Repaying an amount corresponding to more shares than borrowed will revert for underflow.\n    /// @dev It is advised to use the `shares` input when repaying the full position to avoid reverts due to conversion\n    /// roundings between shares and assets.\n    /// @dev An attacker can front-run a repay with a small repay making the transaction revert for underflow.\n    /// @param marketParams The market to repay assets to.\n    /// @param assets The amount of assets to repay.\n    /// @param shares The amount of shares to burn.\n    /// @param onBehalf The address of the owner of the debt position.\n    /// @param data Arbitrary data to pass to the `onMorphoRepay` callback. Pass empty data if not needed.\n    /// @return assetsRepaid The amount of assets repaid.\n    /// @return sharesRepaid The amount of shares burned.\n    function repay(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        bytes memory data\n    ) external returns (uint256 assetsRepaid, uint256 sharesRepaid);\n\n    /// @notice Accrues interest for the given market `marketParams`.\n    function accrueInterest(MarketParams memory marketParams) external;\n\n    /// @notice Returns the data stored on the different `slots`.\n    function extSloads(bytes32[] memory slots) external view returns (bytes32[] memory);\n}\n\n/// @dev This interface is inherited by Morpho so that function signatures are checked by the compiler.\n/// @dev Consider using the IMorpho interface instead of this one.\ninterface IMorphoStaticTyping is IMorphoBase {\n    /// @notice The state of the position of `user` on the market corresponding to `id`.\n    /// @dev Warning: For `feeRecipient`, `supplyShares` does not contain the accrued shares since the last interest\n    /// accrual.\n    function position(Id id, address user)\n        external\n        view\n        returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral);\n\n    /// @notice The state of the market corresponding to `id`.\n    /// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual.\n    /// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.\n    /// @dev Warning: `totalSupplyShares` does not contain the accrued shares by `feeRecipient` since the last interest\n    /// accrual.\n    function market(Id id)\n        external\n        view\n        returns (\n            uint128 totalSupplyAssets,\n            uint128 totalSupplyShares,\n            uint128 totalBorrowAssets,\n            uint128 totalBorrowShares,\n            uint128 lastUpdate,\n            uint128 fee,\n            uint128 totalMarkdownAmount\n        );\n\n    /// @notice The market params corresponding to `id`.\n    /// @dev This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer\n    /// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.\n    function idToMarketParams(Id id)\n        external\n        view\n        returns (\n            address loanToken,\n            address collateralToken,\n            address oracle,\n            address irm,\n            uint256 lltv,\n            address creditLine\n        );\n}\n\n/// @title IMorpho\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @dev Use this interface for Morpho to have access to all the functions with the appropriate function signatures.\ninterface IMorpho is IMorphoBase {\n    /// @notice The state of the position of `user` on the market corresponding to `id`.\n    /// @dev Warning: For `feeRecipient`, `p.supplyShares` does not contain the accrued shares since the last interest\n    /// accrual.\n    function position(Id id, address user) external view returns (Position memory p);\n\n    /// @notice The state of the market corresponding to `id`.\n    /// @dev Warning: `m.totalSupplyAssets` does not contain the accrued interest since the last interest accrual.\n    /// @dev Warning: `m.totalBorrowAssets` does not contain the accrued interest since the last interest accrual.\n    /// @dev Warning: `m.totalSupplyShares` does not contain the accrued shares by `feeRecipient` since the last\n    /// interest accrual.\n    function market(Id id) external view returns (Market memory m);\n\n    /// @notice The market params corresponding to `id`.\n    /// @dev This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer\n    /// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.\n    function idToMarketParams(Id id) external view returns (MarketParams memory);\n}\n\n/// @title IMorphoCredit\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @dev Use this interface for Morpho to have access to all the functions with the appropriate function signatures.\ninterface IMorphoCredit {\n    /// @notice The helper of the contract.\n    function helper() external view returns (address);\n\n    /// @notice The usd3 contract\n    function usd3() external view returns (address);\n\n    /// @notice The protocol config of the contract.\n    function protocolConfig() external view returns (address);\n\n    /// @notice Sets `helper` as `helper` of the contract.\n    /// @param newHelper The new helper address\n    function setHelper(address newHelper) external;\n\n    /// @notice Sets `usd3` as `usd3` of the contract.\n    /// @param newUsd3 The new usd3 address\n    function setUsd3(address newUsd3) external;\n\n    /// @notice Clears wind-down once `S + V <= R * (T + 1) / 2`, providing 2x margin to the floor.\n    /// @dev Only callable by the governance owner.\n    /// @param id The market ID\n    function clearMarketWindDown(Id id) external;\n\n    /// @notice Sets the credit line and premium rate for a borrower\n    /// @param id The market ID\n    /// @param borrower The borrower address\n    /// @param credit The credit line amount\n    /// @param drp The drp per second in WAD\n    function setCreditLine(Id id, address borrower, uint256 credit, uint128 drp) external;\n\n    /// @notice Returns the premium data for a specific borrower in a market\n    /// @param id The market ID\n    /// @param borrower The borrower address\n    /// @return lastAccrualTime Timestamp of the last premium accrual\n    /// @return rate Current risk premium rate per second (scaled by WAD)\n    /// @return borrowAssetsAtLastAccrual Snapshot of borrow position at last premium accrual\n    function borrowerPremium(Id id, address borrower)\n        external\n        view\n        returns (uint128 lastAccrualTime, uint128 rate, uint128 borrowAssetsAtLastAccrual);\n\n    /// @notice Batch accrue premiums for multiple borrowers\n    /// @param id Market ID\n    /// @param borrowers Array of borrower addresses\n    /// @dev Gas usage scales linearly with array size. Callers should manage batch sizes based on block gas limits.\n    function accruePremiumsForBorrowers(Id id, address[] calldata borrowers) external;\n\n    /// @notice Close a payment cycle and post obligations for multiple borrowers\n    /// @param id Market ID\n    /// @param endDate Cycle end date\n    /// @param borrowers Array of borrower addresses\n    /// @param repaymentBps Array of repayment basis points (e.g., 500 = 5%)\n    /// @param endingBalances Array of ending balances for penalty calculations\n    function closeCycleAndPostObligations(\n        Id id,\n        uint256 endDate,\n        address[] calldata borrowers,\n        uint256[] calldata repaymentBps,\n        uint256[] calldata endingBalances\n    ) external;\n\n    /// @notice Add obligations to the latest payment cycle\n    /// @param id Market ID\n    /// @param borrowers Array of borrower addresses\n    /// @param repaymentBps Array of repayment basis points (e.g., 500 = 5%)\n    /// @param endingBalances Array of ending balances\n    function addObligationsToLatestCycle(\n        Id id,\n        address[] calldata borrowers,\n        uint256[] calldata repaymentBps,\n        uint256[] calldata endingBalances\n    ) external;\n\n    /// @notice Get repayment obligation for a borrower\n    /// @param id Market ID\n    /// @param borrower Borrower address\n    /// @return cycleId The payment cycle ID\n    /// @return amountDue The amount due\n    /// @return endingBalance The ending balance for penalty calculations\n    function repaymentObligation(Id id, address borrower)\n        external\n        view\n        returns (uint128 cycleId, uint128 amountDue, uint128 endingBalance);\n\n    /// @notice Get payment cycle end date\n    /// @param id Market ID\n    /// @param cycleId Cycle ID\n    /// @return endDate The cycle end date\n    function paymentCycle(Id id, uint256 cycleId) external view returns (uint256 endDate);\n\n    /// @notice Settle a borrower's account by writing off all remaining debt\n    /// @dev Only callable by credit line contract\n    /// @dev Should be called after any partial repayments have been made\n    /// @param marketParams The market parameters\n    /// @param borrower The borrower whose account to settle\n    /// @return writtenOffAssets Amount of assets written off\n    /// @return writtenOffShares Amount of shares written off\n    function settleAccount(MarketParams memory marketParams, address borrower)\n        external\n        returns (uint256 writtenOffAssets, uint256 writtenOffShares);\n\n    /// @notice Get markdown state for a borrower\n    /// @param id Market ID\n    /// @param borrower Borrower address\n    /// @return lastCalculatedMarkdown Markdown currently applied to the market for this borrower\n    function markdownState(Id id, address borrower) external view returns (uint128 lastCalculatedMarkdown);\n\n    /// @notice Whether a supply-share floor truncated a market's markdown or settlement loss.\n    /// @dev Wind-down blocks new supply and borrowing while permitting withdrawal, repayment, and settlement. It can\n    /// only be cleared by governance through `clearMarketWindDown` once `S + V <= R * (T + 1) / 2`.\n    function marketInWindDown(Id id) external view returns (bool);\n}\n"},"src/libraries/periphery/MorphoLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IMorpho, Id} from \"../../interfaces/IMorpho.sol\";\nimport {MorphoStorageLib} from \"./MorphoStorageLib.sol\";\n\n/// @title MorphoLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Helper library to access Morpho storage variables.\n/// @dev Warning: Supply and borrow getters may return outdated values that do not include accrued interest.\nlibrary MorphoLib {\n    function supplyShares(IMorpho morpho, Id id, address user) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.positionSupplySharesSlot(id, user));\n        return uint256(morpho.extSloads(slot)[0]);\n    }\n\n    function borrowShares(IMorpho morpho, Id id, address user) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.positionBorrowSharesAndCollateralSlot(id, user));\n        return uint128(uint256(morpho.extSloads(slot)[0]));\n    }\n\n    function collateral(IMorpho morpho, Id id, address user) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.positionBorrowSharesAndCollateralSlot(id, user));\n        return uint256(morpho.extSloads(slot)[0] >> 128);\n    }\n\n    function totalSupplyAssets(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketTotalSupplyAssetsAndSharesSlot(id));\n        return uint128(uint256(morpho.extSloads(slot)[0]));\n    }\n\n    function totalSupplyShares(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketTotalSupplyAssetsAndSharesSlot(id));\n        return uint256(morpho.extSloads(slot)[0] >> 128);\n    }\n\n    function totalBorrowAssets(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketTotalBorrowAssetsAndSharesSlot(id));\n        return uint128(uint256(morpho.extSloads(slot)[0]));\n    }\n\n    function totalBorrowShares(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketTotalBorrowAssetsAndSharesSlot(id));\n        return uint256(morpho.extSloads(slot)[0] >> 128);\n    }\n\n    function lastUpdate(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketLastUpdateAndFeeSlot(id));\n        return uint128(uint256(morpho.extSloads(slot)[0]));\n    }\n\n    function fee(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketLastUpdateAndFeeSlot(id));\n        return uint256(morpho.extSloads(slot)[0] >> 128);\n    }\n\n    function _array(bytes32 x) private pure returns (bytes32[] memory) {\n        bytes32[] memory res = new bytes32[](1);\n        res[0] = x;\n        return res;\n    }\n}\n"},"src/libraries/periphery/MorphoBalancesLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {Id, MarketParams, Market, IMorpho} from \"../../interfaces/IMorpho.sol\";\nimport {IIrm} from \"../../interfaces/IIrm.sol\";\n\nimport {MathLib} from \"../MathLib.sol\";\nimport {UtilsLib} from \"../UtilsLib.sol\";\nimport {MorphoLib} from \"./MorphoLib.sol\";\nimport {SharesMathLib} from \"../SharesMathLib.sol\";\nimport {MarketParamsLib} from \"../MarketParamsLib.sol\";\n\n/// @title MorphoBalancesLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Helper library exposing getters with the expected value after interest accrual.\n/// @dev This library is not used in Morpho itself and is intended to be used by integrators.\n/// @dev The getter to retrieve the expected total borrow shares is not exposed because interest accrual does not apply\n/// to it. The value can be queried directly on Morpho using `totalBorrowShares`.\nlibrary MorphoBalancesLib {\n    using MathLib for uint256;\n    using MathLib for uint128;\n    using UtilsLib for uint256;\n    using MorphoLib for IMorpho;\n    using SharesMathLib for uint256;\n    using MarketParamsLib for MarketParams;\n\n    /// @notice Returns the expected market balances of a market after having accrued interest.\n    /// @return The expected total supply assets.\n    /// @return The expected total supply shares.\n    /// @return The expected total borrow assets.\n    /// @return The expected total borrow shares.\n    function expectedMarketBalances(IMorpho morpho, MarketParams memory marketParams)\n        internal\n        view\n        returns (uint256, uint256, uint256, uint256)\n    {\n        Id id = marketParams.id();\n        Market memory market = morpho.market(id);\n\n        uint256 elapsed = block.timestamp - market.lastUpdate;\n\n        // Skipped if elapsed == 0 or totalBorrowAssets == 0 because interest would be null, or if irm == address(0).\n        if (elapsed != 0 && market.totalBorrowAssets != 0 && marketParams.irm != address(0)) {\n            uint256 borrowRate = IIrm(marketParams.irm).borrowRateView(marketParams, market);\n            uint256 interest = market.totalBorrowAssets.wMulDown(borrowRate.wTaylorCompounded(elapsed));\n            market.totalBorrowAssets += interest.toUint128();\n            market.totalSupplyAssets += interest.toUint128();\n\n            if (market.fee != 0) {\n                uint256 feeAmount = interest.wMulDown(market.fee);\n                // The fee amount is subtracted from the total supply in this calculation to compensate for the fact\n                // that total supply is already updated.\n                uint256 feeShares =\n                    feeAmount.toSharesDown(market.totalSupplyAssets - feeAmount, market.totalSupplyShares);\n                market.totalSupplyShares += feeShares.toUint128();\n            }\n        }\n\n        return (market.totalSupplyAssets, market.totalSupplyShares, market.totalBorrowAssets, market.totalBorrowShares);\n    }\n\n    /// @notice Returns the expected total supply assets of a market after having accrued interest.\n    function expectedTotalSupplyAssets(IMorpho morpho, MarketParams memory marketParams)\n        internal\n        view\n        returns (uint256 totalSupplyAssets)\n    {\n        (totalSupplyAssets,,,) = expectedMarketBalances(morpho, marketParams);\n    }\n\n    /// @notice Returns the expected total borrow assets of a market after having accrued interest.\n    function expectedTotalBorrowAssets(IMorpho morpho, MarketParams memory marketParams)\n        internal\n        view\n        returns (uint256 totalBorrowAssets)\n    {\n        (,, totalBorrowAssets,) = expectedMarketBalances(morpho, marketParams);\n    }\n\n    /// @notice Returns the expected total supply shares of a market after having accrued interest.\n    function expectedTotalSupplyShares(IMorpho morpho, MarketParams memory marketParams)\n        internal\n        view\n        returns (uint256 totalSupplyShares)\n    {\n        (, totalSupplyShares,,) = expectedMarketBalances(morpho, marketParams);\n    }\n\n    /// @notice Returns the expected supply assets balance of `user` on a market after having accrued interest.\n    /// @dev Warning: Wrong for `feeRecipient` because their supply shares increase is not taken into account.\n    /// @dev Warning: Withdrawing using the expected supply assets can lead to a revert due to conversion roundings from\n    /// assets to shares.\n    function expectedSupplyAssets(IMorpho morpho, MarketParams memory marketParams, address user)\n        internal\n        view\n        returns (uint256)\n    {\n        Id id = marketParams.id();\n        uint256 supplyShares = morpho.supplyShares(id, user);\n        (uint256 totalSupplyAssets, uint256 totalSupplyShares,,) = expectedMarketBalances(morpho, marketParams);\n\n        return supplyShares.toAssetsDown(totalSupplyAssets, totalSupplyShares);\n    }\n\n    /// @notice Returns the expected borrow assets balance of `user` on a market after having accrued interest.\n    /// @dev Warning: The expected balance is rounded up, so it may be greater than the market's expected total borrow\n    /// assets.\n    function expectedBorrowAssets(IMorpho morpho, MarketParams memory marketParams, address user)\n        internal\n        view\n        returns (uint256)\n    {\n        Id id = marketParams.id();\n        uint256 borrowShares = morpho.borrowShares(id, user);\n        (,, uint256 totalBorrowAssets, uint256 totalBorrowShares) = expectedMarketBalances(morpho, marketParams);\n\n        return borrowShares.toAssetsUp(totalBorrowAssets, totalBorrowShares);\n    }\n}\n"},"src/libraries/SharesMathLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {MathLib} from \"./MathLib.sol\";\n\n/// @title SharesMathLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Shares management library.\n/// @dev This implementation mitigates share price manipulations, using OpenZeppelin's method of virtual shares:\n/// https://docs.openzeppelin.com/contracts/4.x/erc4626#inflation-attack.\nlibrary SharesMathLib {\n    using MathLib for uint256;\n\n    /// @dev The number of virtual shares has been chosen low enough to prevent overflows, and high enough to ensure\n    /// high precision computations.\n    /// @dev Virtual shares can never be redeemed for the assets they are entitled to, but it is assumed the share price\n    /// stays low enough not to inflate these assets to a significant value.\n    /// @dev Warning: The assets to which virtual borrow shares are entitled behave like unrealizable bad debt.\n    uint256 internal constant VIRTUAL_SHARES = 1e6;\n\n    /// @dev A number of virtual assets of 1 enforces a conversion rate between shares and assets when a market is\n    /// empty.\n    uint256 internal constant VIRTUAL_ASSETS = 1;\n\n    /// @dev Calculates the value of `assets` quoted in shares, rounding down.\n    function toSharesDown(uint256 assets, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {\n        return assets.mulDivDown(totalShares + VIRTUAL_SHARES, totalAssets + VIRTUAL_ASSETS);\n    }\n\n    /// @dev Calculates the value of `shares` quoted in assets, rounding down.\n    function toAssetsDown(uint256 shares, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {\n        return shares.mulDivDown(totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES);\n    }\n\n    /// @dev Calculates the value of `assets` quoted in shares, rounding up.\n    function toSharesUp(uint256 assets, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {\n        return assets.mulDivUp(totalShares + VIRTUAL_SHARES, totalAssets + VIRTUAL_ASSETS);\n    }\n\n    /// @dev Calculates the value of `shares` quoted in assets, rounding up.\n    function toAssetsUp(uint256 shares, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {\n        return shares.mulDivUp(totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES);\n    }\n}\n"},"lib/openzeppelin/contracts/interfaces/IERC4626.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC-4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n    event Withdraw(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}\n"},"lib/openzeppelin/contracts/utils/Pausable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../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    bool private _paused;\n\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    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\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        _requireNotPaused();\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        _requirePaused();\n        _;\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 Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\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"},"lib/tokenized-strategy-periphery/src/libraries/TokenizedStrategyStorageLib.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0\npragma solidity >=0.8.18;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * @title TokenizedStrategy Storage Library\n * @author yearn.finance\n * @notice Library for accessing storage slots of TokenizedStrategy contracts\n * @dev This library provides helper functions to compute storage slot locations\n * for TokenizedStrategy state variables. This is useful for off-chain tools,\n * monitoring systems, and contracts that need direct storage access.\n *\n * Based on the pattern used by Morpho's MorphoStorageLib.\n */\nlibrary TokenizedStrategyStorageLib {\n    /**\n     * @dev The main storage slot for the StrategyData struct.\n     * This matches the BASE_STRATEGY_STORAGE constant in TokenizedStrategy.sol\n     */\n    bytes32 internal constant BASE_STRATEGY_STORAGE =\n        bytes32(uint256(keccak256(\"yearn.base.strategy.storage\")) - 1);\n\n    /**\n     * @dev The StrategyData struct that holds all storage for TokenizedStrategy v3.0.4.\n     * This must match the exact layout in TokenizedStrategy.sol to ensure compatibility.\n     */\n    struct StrategyData {\n        // Slot 0: ERC20 asset (160 bits) + decimals (8 bits) + 88 bits unused\n        ERC20 asset;\n        uint8 decimals;\n        // Slot 1: string name (dynamic storage)\n        string name;\n        // Slot 2: uint256 totalSupply\n        uint256 totalSupply;\n        // Slot 3: mapping nonces\n        mapping(address => uint256) nonces;\n        // Slot 4: mapping balances\n        mapping(address => uint256) balances;\n        // Slot 5: mapping allowances\n        mapping(address => mapping(address => uint256)) allowances;\n        // Slot 6: uint256 totalAssets\n        uint256 totalAssets;\n        // Slot 7: uint256 profitUnlockingRate\n        uint256 profitUnlockingRate;\n        // Slot 8: uint96 fullProfitUnlockDate (96 bits) + address keeper (160 bits)\n        uint96 fullProfitUnlockDate;\n        address keeper;\n        // Slot 9: uint32 profitMaxUnlockTime + uint16 performanceFee + address performanceFeeRecipient (208 bits total)\n        uint32 profitMaxUnlockTime;\n        uint16 performanceFee;\n        address performanceFeeRecipient;\n        // Slot 10: uint96 lastReport + address management\n        uint96 lastReport;\n        address management;\n        // Slot 11: address pendingManagement\n        address pendingManagement;\n        // Slot 12: address emergencyAdmin\n        address emergencyAdmin;\n        // Slot 13: uint8 entered + bool shutdown\n        uint8 entered;\n        bool shutdown;\n    }\n\n    /**\n     * @notice Get the main storage slot for the StrategyData struct\n     * @return slot The storage slot where StrategyData is stored\n     */\n    function strategyStorageSlot() internal pure returns (bytes32 slot) {\n        return BASE_STRATEGY_STORAGE;\n    }\n\n    /**\n     * @notice Get the storage slot for asset and decimals (packed)\n     * @return slot The storage slot containing asset (20 bytes) and decimals (1 byte)\n     */\n    function assetSlot() internal pure returns (bytes32 slot) {\n        return BASE_STRATEGY_STORAGE;\n    }\n\n    /**\n     * @notice Get the storage slot for the strategy name\n     * @return slot The storage slot for the name string\n     */\n    function nameSlot() internal pure returns (bytes32 slot) {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 1);\n    }\n\n    /**\n     * @notice Get the storage slot for totalSupply\n     * @return slot The storage slot for totalSupply\n     */\n    function totalSupplySlot() internal pure returns (bytes32 slot) {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 2);\n    }\n\n    /**\n     * @notice Get the storage slot for totalAssets\n     * @return slot The storage slot for totalAssets\n     */\n    function totalAssetsSlot() internal pure returns (bytes32 slot) {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 6);\n    }\n\n    /**\n     * @notice Get the storage slot for profitUnlockingRate\n     * @return slot The storage slot for profitUnlockingRate\n     */\n    function profitUnlockingRateSlot() internal pure returns (bytes32 slot) {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 7);\n    }\n\n    /**\n     * @notice Get the storage slot for fullProfitUnlockDate and keeper (packed)\n     * @return slot The storage slot containing fullProfitUnlockDate (uint96) and keeper (address)\n     */\n    function fullProfitUnlockDateAndKeeperSlot()\n        internal\n        pure\n        returns (bytes32 slot)\n    {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 8);\n    }\n\n    /**\n     * @notice Get the storage slot for profitMaxUnlockTime, performanceFee, and performanceFeeRecipient (packed)\n     * @return slot The storage slot containing profitMaxUnlockTime (uint32), performanceFee (uint16), and performanceFeeRecipient (address)\n     */\n    function profitConfigSlot() internal pure returns (bytes32 slot) {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 9);\n    }\n\n    /**\n     * @notice Get the storage slot for lastReport and management (packed)\n     * @return slot The storage slot containing lastReport (uint96) and management (address)\n     */\n    function lastReportAndManagementSlot()\n        internal\n        pure\n        returns (bytes32 slot)\n    {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 10);\n    }\n\n    /**\n     * @notice Get the storage slot for pendingManagement\n     * @return slot The storage slot for pendingManagement address\n     */\n    function pendingManagementSlot() internal pure returns (bytes32 slot) {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 11);\n    }\n\n    /**\n     * @notice Get the storage slot for emergencyAdmin\n     * @return slot The storage slot for emergencyAdmin address\n     */\n    function emergencyAdminSlot() internal pure returns (bytes32 slot) {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 12);\n    }\n\n    /**\n     * @notice Get the storage slot for entered and shutdown (packed)\n     * @return slot The storage slot containing entered (uint8) and shutdown (bool)\n     */\n    function statusSlot() internal pure returns (bytes32 slot) {\n        return bytes32(uint256(BASE_STRATEGY_STORAGE) + 13);\n    }\n\n    /**\n     * @notice Calculate the storage slot for a specific nonce\n     * @param owner The address to get the nonce slot for\n     * @return slot The storage slot for the owner's nonce\n     */\n    function noncesSlot(address owner) internal pure returns (bytes32 slot) {\n        // nonces mapping is at slot position 3 from BASE_STRATEGY_STORAGE\n        bytes32 noncesPosition = bytes32(uint256(BASE_STRATEGY_STORAGE) + 3);\n        return keccak256(abi.encode(owner, noncesPosition));\n    }\n\n    /**\n     * @notice Calculate the storage slot for a specific balance\n     * @param account The address to get the balance slot for\n     * @return slot The storage slot for the account's balance\n     */\n    function balancesSlot(\n        address account\n    ) internal pure returns (bytes32 slot) {\n        // balances mapping is at slot position 4 from BASE_STRATEGY_STORAGE\n        bytes32 balancesPosition = bytes32(uint256(BASE_STRATEGY_STORAGE) + 4);\n        return keccak256(abi.encode(account, balancesPosition));\n    }\n\n    /**\n     * @notice Calculate the storage slot for a specific allowance\n     * @param owner The address that owns the tokens\n     * @param spender The address that can spend the tokens\n     * @return slot The storage slot for the allowance\n     */\n    function allowancesSlot(\n        address owner,\n        address spender\n    ) internal pure returns (bytes32 slot) {\n        // allowances mapping is at slot position 5 from BASE_STRATEGY_STORAGE\n        bytes32 allowancesPosition = bytes32(\n            uint256(BASE_STRATEGY_STORAGE) + 5\n        );\n        // For nested mappings: keccak256(spender . keccak256(owner . slot))\n        bytes32 ownerSlot = keccak256(abi.encode(owner, allowancesPosition));\n        return keccak256(abi.encode(spender, ownerSlot));\n    }\n\n    /**\n     * @notice Helper to load the StrategyData struct from storage\n     * @dev This can be used in external contracts to load the full struct\n     * @return S The StrategyData struct from storage\n     */\n    function getStrategyStorage()\n        internal\n        pure\n        returns (StrategyData storage S)\n    {\n        bytes32 slot = BASE_STRATEGY_STORAGE;\n        assembly {\n            S.slot := slot\n        }\n    }\n}\n"},"src/interfaces/IProtocolConfig.sol":{"content":"// SPDX-License-Identifier: GPL-20later\npragma solidity ^0.8.18;\n\n/// @notice Interface for the ProtocolConfig contract\n\n// Struct to hold market parameters\nstruct MarketConfig {\n    uint256 gracePeriod; // Duration of grace period after cycle end\n    uint256 delinquencyPeriod; // Duration of delinquency period before default\n    uint256 minBorrow; // Minimum outstanding loan balance to prevent dust\n    uint256 irp; // Penalty rate per second for delinquent borrowers\n}\n\n// Struct to hold credit line parameters\nstruct CreditLineConfig {\n    uint256 maxLTV;\n    uint256 maxVV;\n    uint256 maxCreditLine;\n    uint256 minCreditLine;\n    uint256 maxDRP;\n}\n\n// Struct to hold IRM parameters\nstruct IRMConfig {\n    uint256 curveSteepness;\n    uint256 adjustmentSpeed;\n    uint256 targetUtilization;\n    uint256 initialRateAtTarget;\n    uint256 minRateAtTarget;\n    uint256 maxRateAtTarget;\n}\n\n/// @notice Struct to hold IRM parameters with int256 types for internal calculations\nstruct IRMConfigTyped {\n    int256 curveSteepness;\n    int256 adjustmentSpeed;\n    int256 targetUtilization;\n    int256 initialRateAtTarget;\n    int256 minRateAtTarget;\n    int256 maxRateAtTarget;\n}\n\ninterface IProtocolConfig {\n    /// @dev Initialize the contract with the owner\n    /// @param newOwner The address of the new owner\n    function initialize(address newOwner) external;\n\n    /// @dev Set a configuration value\n    /// @param key The configuration key\n    /// @param value The configuration value\n    function setConfig(bytes32 key, uint256 value) external;\n\n    /// @dev Set emergency configuration with binary constraints\n    /// @param key The configuration key (IS_PAUSED, DEBT_CAP, MAX_ON_CREDIT, USD3_SUPPLY_CAP)\n    /// @param value The configuration value (binary constraints enforced)\n    function setEmergencyConfig(bytes32 key, uint256 value) external;\n\n    // Credit Line getters\n    /// @dev Get the credit line parameters\n    /// @return The credit line parameters\n    function getCreditLineConfig() external view returns (CreditLineConfig memory);\n\n    // Market getters\n    /// @dev Get the pause status\n    /// @return The pause status value\n    function getIsPaused() external view returns (uint256);\n\n    /// @dev Get the maximum on credit\n    /// @return The max on credit value\n    function getMaxOnCredit() external view returns (uint256);\n\n    /// @dev Get the market parameters\n    /// @return The market parameters\n    function getMarketConfig() external view returns (MarketConfig memory);\n\n    /// @dev Get the cycle duration for payment cycles\n    /// @return The cycle duration in seconds\n    function getCycleDuration() external view returns (uint256);\n\n    // IRM getters\n    /// @dev Get the IRM parameters\n    /// @return The IRM parameters\n    function getIRMConfig() external view returns (IRMConfig memory);\n\n    // USD3 & sUSD3 getters\n    /// @dev Get the tranche ratio\n    /// @return The tranche ratio value\n    function getTrancheRatio() external view returns (uint256);\n\n    /// @dev Get the tranche share variant\n    /// @return The tranche share variant value\n    function getTrancheShareVariant() external view returns (uint256);\n\n    /// @dev Get the SUSD3 lock duration\n    /// @return The SUSD3 lock duration value\n    function getSusd3LockDuration() external view returns (uint256);\n\n    /// @dev Get the SUSD3 cooldown period\n    /// @return The SUSD3 cooldown period value\n    function getSusd3CooldownPeriod() external view returns (uint256);\n\n    /// @dev Get the USD3 commitment time\n    /// @return The lock period in seconds\n    function getUsd3CommitmentTime() external view returns (uint256);\n\n    /// @dev Get the sUSD3 withdrawal window\n    /// @return The withdrawal window duration in seconds after cooldown\n    function getSusd3WithdrawalWindow() external view returns (uint256);\n\n    /// @dev Get the USD3 supply cap\n    /// @return The supply cap in asset units\n    function getUsd3SupplyCap() external view returns (uint256);\n\n    /// @dev Get configuration value by key\n    /// @param key The configuration key\n    /// @return The configuration value\n    function config(bytes32 key) external view returns (uint256);\n}\n"},"src/libraries/ProtocolConfigLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\n/// @title ProtocolConfigLib\n/// @notice Library containing all configuration keys for ProtocolConfig\n/// @dev Centralizes all configuration keys to avoid magic strings and improve maintainability\nlibrary ProtocolConfigLib {\n    // Market Control Keys\n    bytes32 internal constant IS_PAUSED = keccak256(\"IS_PAUSED\");\n    bytes32 internal constant MAX_ON_CREDIT = keccak256(\"MAX_ON_CREDIT\");\n    bytes32 internal constant DEBT_CAP = keccak256(\"DEBT_CAP\");\n\n    // Credit Line Keys\n    bytes32 internal constant MIN_LOAN_DURATION = keccak256(\"MIN_LOAN_DURATION\");\n    bytes32 internal constant LATE_REPAYMENT_THRESHOLD = keccak256(\"LATE_REPAYMENT_THRESHOLD\");\n    bytes32 internal constant DEFAULT_THRESHOLD = keccak256(\"DEFAULT_THRESHOLD\");\n    bytes32 internal constant GRACE_PERIOD = keccak256(\"GRACE_PERIOD\");\n\n    // Interest Rate Keys\n    bytes32 internal constant CURVE_STEEPNESS = keccak256(\"CURVE_STEEPNESS\");\n    bytes32 internal constant ADJUSTMENT_SPEED = keccak256(\"ADJUSTMENT_SPEED\");\n    bytes32 internal constant TARGET_UTILIZATION = keccak256(\"TARGET_UTILIZATION\");\n    bytes32 internal constant INITIAL_RATE_AT_TARGET = keccak256(\"INITIAL_RATE_AT_TARGET\");\n    bytes32 internal constant MIN_RATE_AT_TARGET = keccak256(\"MIN_RATE_AT_TARGET\");\n    bytes32 internal constant MAX_RATE_AT_TARGET = keccak256(\"MAX_RATE_AT_TARGET\");\n\n    // Tranche Keys (USD3 & sUSD3)\n    bytes32 internal constant TRANCHE_RATIO = keccak256(\"TRANCHE_RATIO\");\n    bytes32 internal constant TRANCHE_SHARE_VARIANT = keccak256(\"TRANCHE_SHARE_VARIANT\");\n    bytes32 internal constant MIN_SUSD3_BACKING_RATIO = keccak256(\"MIN_SUSD3_BACKING_RATIO\");\n    bytes32 internal constant SUSD3_NOMINAL_BACKING_FLOOR = keccak256(\"SUSD3_NOMINAL_BACKING_FLOOR\");\n\n    // Timing Keys\n    bytes32 internal constant SUSD3_LOCK_DURATION = keccak256(\"SUSD3_LOCK_DURATION\");\n    bytes32 internal constant SUSD3_COOLDOWN_PERIOD = keccak256(\"SUSD3_COOLDOWN_PERIOD\");\n    bytes32 internal constant USD3_COMMITMENT_TIME = keccak256(\"USD3_COMMITMENT_TIME\");\n    bytes32 internal constant SUSD3_WITHDRAWAL_WINDOW = keccak256(\"SUSD3_WITHDRAWAL_WINDOW\");\n\n    // Supply Cap Keys\n    bytes32 internal constant USD3_SUPPLY_CAP = keccak256(\"USD3_SUPPLY_CAP\");\n    /// @notice Hard USD3 redemption ring-fence in asset units; set this whenever a fixed amount must remain reserved.\n    bytes32 internal constant USD3_REDEMPTION_FLOOR = keccak256(\"USD3_REDEMPTION_FLOOR\");\n    /// @notice USD3 redemption scaling floor in bps; drains geometrically toward the nominal floor across redemptions.\n    bytes32 internal constant USD3_REDEMPTION_FLOOR_BPS = keccak256(\"USD3_REDEMPTION_FLOOR_BPS\");\n\n    // Tend Keys\n    bytes32 internal constant TEND_DRIFT_THRESHOLD = keccak256(\"TEND_DRIFT_THRESHOLD\");\n\n    // Markdown Keys\n    bytes32 internal constant FULL_MARKDOWN_DURATION = keccak256(\"FULL_MARKDOWN_DURATION\");\n}\n"},"src/usd3/base/BaseStrategyUpgradeable.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0\npragma solidity >=0.8.18;\n\nimport {Initializable} from \"../../../lib/openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n// TokenizedStrategy interface used for internal view delegateCalls.\nimport {ITokenizedStrategy, ERC20} from \"@tokenized-strategy/interfaces/ITokenizedStrategy.sol\";\n\n/**\n * @title BaseStrategyUpgradeable\n * @author Modified from yearn.finance BaseStrategy for upgradeability\n * @notice\n *  BaseStrategyUpgradeable is a fork of Yearn V3's BaseStrategy that works\n *  with upgradeable proxy patterns. The main change is replacing immutable\n *  variables with storage variables and constructor with initializer.\n *\n *  It maintains full compatibility with TokenizedStrategy singleton pattern\n *  while allowing the strategy to be deployed behind a proxy.\n */\nabstract contract BaseStrategyUpgradeable is Initializable {\n    /*//////////////////////////////////////////////////////////////\n                            MODIFIERS\n    //////////////////////////////////////////////////////////////*/\n    /**\n     * @dev Used on TokenizedStrategy callback functions to make sure it is post\n     * a delegateCall from this address to the TokenizedStrategy.\n     */\n    modifier onlySelf() {\n        _onlySelf();\n        _;\n    }\n\n    /**\n     * @dev Use to assure that the call is coming from the strategies management.\n     */\n    modifier onlyManagement() {\n        TokenizedStrategy.requireManagement(msg.sender);\n        _;\n    }\n\n    /**\n     * @dev Use to assure that the call is coming from either the strategies\n     * management or the keeper.\n     */\n    modifier onlyKeepers() {\n        TokenizedStrategy.requireKeeperOrManagement(msg.sender);\n        _;\n    }\n\n    /**\n     * @dev Use to assure that the call is coming from either the strategies\n     * management or the emergency admin.\n     */\n    modifier onlyEmergencyAuthorized() {\n        TokenizedStrategy.requireEmergencyAuthorized(msg.sender);\n        _;\n    }\n\n    /**\n     * @dev Require that the msg.sender is this address.\n     */\n    function _onlySelf() internal view {\n        require(msg.sender == address(this), \"!self\");\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            CONSTANTS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev This is the address of the TokenizedStrategy implementation\n     * contract that will be used by all strategies to handle the\n     * accounting, logic, storage etc.\n     *\n     * Any external calls to the that don't hit one of the functions\n     * defined in this base or the strategy will end up being forwarded\n     * through the fallback function, which will delegateCall this address.\n     *\n     * This address should be the same for every strategy, never be adjusted\n     * and always be checked before any integration with the Strategy.\n     */\n    address public constant tokenizedStrategyAddress = 0xD377919FA87120584B21279a491F82D5265A139c;\n\n    /*//////////////////////////////////////////////////////////////\n                            STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Underlying asset the Strategy is earning yield on.\n     * Stored here for cheap retrievals within the strategy.\n     */\n    ERC20 internal asset;\n\n    /**\n     * @dev This variable is set to ITokenizedStrategy(address(this)) during initialization.\n     *\n     * This provides a convenient way to call TokenizedStrategy functions\n     * using clean syntax like TokenizedStrategy.totalAssets()\n     */\n    ITokenizedStrategy internal TokenizedStrategy;\n\n    /**\n     * @dev Storage gap for future upgrades\n     */\n    uint256[48] private __gap;\n\n    /*//////////////////////////////////////////////////////////////\n                            INITIALIZATION\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Initialize the BaseStrategy.\n     *\n     * @param _asset Address of the underlying asset.\n     * @param _name Name the strategy will use.\n     * @param _management Address to set as management.\n     * @param _performanceFeeRecipient Address to receive performance fees.\n     * @param _keeper Address allowed to call tend() and report().\n     */\n    function __BaseStrategy_init(\n        address _asset,\n        string memory _name,\n        address _management,\n        address _performanceFeeRecipient,\n        address _keeper\n    ) internal onlyInitializing {\n        asset = ERC20(_asset);\n        TokenizedStrategy = ITokenizedStrategy(address(this));\n\n        // Initialize the strategy's storage variables via delegatecall.\n        _delegateCall(\n            abi.encodeCall(\n                ITokenizedStrategy.initialize, (_asset, _name, _management, _performanceFeeRecipient, _keeper)\n            )\n        );\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                NEEDED TO BE OVERRIDDEN BY STRATEGIST\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Can deploy up to '_amount' of 'asset' in the yield source.\n     *\n     * This function is called at the end of a {deposit} or {mint}\n     * call. Meaning that unless a whitelist is implemented it will\n     * be entirely permissionless and thus can be sandwiched or otherwise\n     * manipulated.\n     *\n     * @param _amount The amount of 'asset' that the strategy can attempt\n     * to deposit in the yield source.\n     */\n    function _deployFunds(uint256 _amount) internal virtual;\n\n    /**\n     * @dev Should attempt to free the '_amount' of 'asset'.\n     *\n     * NOTE: The amount of 'asset' that is already loose has already\n     * been accounted for.\n     *\n     * This function is called during {withdraw} and {redeem} calls.\n     * Meaning that unless a whitelist is implemented it will be\n     * entirely permissionless and thus can be sandwiched or otherwise\n     * manipulated.\n     *\n     * Should not rely on asset.balanceOf(address(this)) calls other than\n     * for diff accounting purposes.\n     *\n     * Any difference between `_amount` and what is actually freed will be\n     * counted as a loss and passed on to the withdrawer. This means\n     * care should be taken in times of illiquidity. It may be better to revert\n     * if withdraws are simply illiquid so not to realize incorrect losses.\n     *\n     * @param _amount, The amount of 'asset' to be freed.\n     */\n    function _freeFunds(uint256 _amount) internal virtual;\n\n    /**\n     * @dev Internal function to harvest all rewards, redeploy any idle\n     * funds and return an accurate accounting of all funds currently\n     * held by the Strategy.\n     *\n     * This should do any needed harvesting, rewards selling, accrual,\n     * redepositing etc. to get the most accurate view of current assets.\n     *\n     * NOTE: All applicable assets including loose assets should be\n     * accounted for in this function.\n     *\n     * Care should be taken when relying on oracles or swap values rather\n     * than actual amounts as all Strategy profit/loss accounting will\n     * be done based on this returned value.\n     *\n     * This can still be called post a shutdown, a strategist can check\n     * `TokenizedStrategy.isShutdown()` to decide if funds should be\n     * redeployed or simply realize any profits/losses.\n     *\n     * @return _totalAssets A trusted and accurate account for the total\n     * amount of 'asset' the strategy currently holds including idle funds.\n     */\n    function _harvestAndReport() internal virtual returns (uint256 _totalAssets);\n\n    /*//////////////////////////////////////////////////////////////\n                    OPTIONAL TO OVERRIDE BY STRATEGIST\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Optional function for strategist to override that can\n     *  be called in between reports.\n     *\n     * If '_tend' is used tendTrigger() will also need to be overridden.\n     *\n     * This call can only be called by a permissioned role so may be\n     * through protected relays.\n     *\n     * This can be used to harvest and compound rewards, deposit idle funds,\n     * perform needed position maintenance or anything else that doesn't need\n     * a full report for.\n     *\n     *   EX: A strategy that can not deposit funds without getting\n     *       sandwiched can use the tend when a certain threshold\n     *       of idle to totalAssets has been reached.\n     *\n     * This will have no effect on PPS of the strategy till report() is called.\n     *\n     * @param _totalIdle The current amount of idle funds that are available to deploy.\n     */\n    function _tend(uint256 _totalIdle) internal virtual {}\n\n    /**\n     * @dev Optional trigger to override if tend() will be used by the strategy.\n     * This must be implemented if the strategy hopes to invoke _tend().\n     *\n     * @return . Should return true if tend() should be called by keeper or false if not.\n     */\n    function _tendTrigger() internal view virtual returns (bool) {\n        return false;\n    }\n\n    /**\n     * @notice Returns if tend() should be called by a keeper.\n     *\n     * @return . Should return true if tend() should be called by keeper or false if not.\n     * @return . Calldata for the tend call.\n     */\n    function tendTrigger() external view virtual returns (bool, bytes memory) {\n        return (\n            // Return the status of the tend trigger.\n            _tendTrigger(),\n            // And the needed calldata either way.\n            abi.encodeWithSelector(ITokenizedStrategy.tend.selector)\n        );\n    }\n\n    /**\n     * @notice Gets the max amount of `asset` that an address can deposit.\n     * @dev Defaults to an unlimited amount for any address. But can\n     * be overridden by strategists.\n     *\n     * This function will be called before any deposit or mints to enforce\n     * any limits desired by the strategist. This can be used for either a\n     * traditional deposit limit or for implementing a whitelist etc.\n     *\n     *   EX:\n     *      if(isAllowed[_owner]) return super.availableDepositLimit(_owner);\n     *\n     * This does not need to take into account any conversion rates\n     * from shares to assets. But should know that any non max uint256\n     * amounts may be converted to shares. So it is recommended to keep\n     * custom amounts low enough as not to cause overflow when multiplied\n     * by `totalSupply`.\n     *\n     * @param . The address that is depositing into the strategy.\n     * @return . The available amount the `_owner` can deposit in terms of `asset`\n     */\n    function availableDepositLimit(\n        address /*_owner*/\n    )\n        public\n        view\n        virtual\n        returns (uint256)\n    {\n        return type(uint256).max;\n    }\n\n    /**\n     * @notice Gets the max amount of `asset` that can be withdrawn.\n     * @dev Defaults to an unlimited amount for any address. But can\n     * be overridden by strategists.\n     *\n     * This function will be called before any withdraw or redeem to enforce\n     * any limits desired by the strategist. This can be used for illiquid\n     * or sandwichable strategies. It should never be lower than `totalIdle`.\n     *\n     *   EX:\n     *       return TokenIzedStrategy.totalIdle();\n     *\n     * This does not need to take into account the `_owner`'s share balance\n     * or conversion rates from shares to assets.\n     *\n     * @param . The address that is withdrawing from the strategy.\n     * @return . The available amount that can be withdrawn in terms of `asset`\n     */\n    function availableWithdrawLimit(\n        address /*_owner*/\n    )\n        public\n        view\n        virtual\n        returns (uint256)\n    {\n        return type(uint256).max;\n    }\n\n    /**\n     * @dev Optional function for a strategist to override that will\n     * allow management to manually withdraw deployed funds from the\n     * yield source if a strategy is shutdown.\n     *\n     * This should attempt to free `_amount`, noting that `_amount` may\n     * be more than is currently deployed.\n     *\n     * NOTE: This will not realize any profits or losses. A separate\n     * {report} will be needed in order to record any profit/loss. If\n     * a report may need to be called after a shutdown it is important\n     * to check if the strategy is shutdown during {_harvestAndReport}\n     * so that it does not simply re-deploy all funds that had been freed.\n     *\n     * EX:\n     *   if(freeAsset > 0 && !TokenizedStrategy.isShutdown()) {\n     *       depositFunds...\n     *    }\n     *\n     * @param _amount The amount of asset to attempt to free.\n     */\n    function _emergencyWithdraw(uint256 _amount) internal virtual {}\n\n    /*//////////////////////////////////////////////////////////////\n                        TokenizedStrategy HOOKS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Can deploy up to '_amount' of 'asset' in yield source.\n     * @dev Callback for the TokenizedStrategy to call during a {deposit}\n     * or {mint} to tell the strategy it can deploy funds.\n     *\n     * Since this can only be called after a {deposit} or {mint}\n     * delegateCall to the TokenizedStrategy msg.sender == address(this).\n     *\n     * Unless a whitelist is implemented this will be entirely permissionless\n     * and thus can be sandwiched or otherwise manipulated.\n     *\n     * @param _amount The amount of 'asset' that the strategy can\n     * attempt to deposit in the yield source.\n     */\n    function deployFunds(uint256 _amount) external virtual onlySelf {\n        _deployFunds(_amount);\n    }\n\n    /**\n     * @notice Should attempt to free the '_amount' of 'asset'.\n     * @dev Callback for the TokenizedStrategy to call during a withdraw\n     * or redeem to free the needed funds to service the withdraw.\n     *\n     * This can only be called after a 'withdraw' or 'redeem' delegateCall\n     * to the TokenizedStrategy so msg.sender == address(this).\n     *\n     * @param _amount The amount of 'asset' that the strategy should attempt to free up.\n     */\n    function freeFunds(uint256 _amount) external virtual onlySelf {\n        _freeFunds(_amount);\n    }\n\n    /**\n     * @notice Returns the accurate amount of all funds currently\n     * held by the Strategy.\n     * @dev Callback for the TokenizedStrategy to call during a report to\n     * get an accurate accounting of assets the strategy controls.\n     *\n     * This can only be called after a report() delegateCall to the\n     * TokenizedStrategy so msg.sender == address(this).\n     *\n     * @return . A trusted and accurate account for the total amount\n     * of 'asset' the strategy currently holds including idle funds.\n     */\n    function harvestAndReport() external virtual onlySelf returns (uint256) {\n        return _harvestAndReport();\n    }\n\n    /**\n     * @notice Will call the internal '_tend' when a keeper tends the strategy.\n     * @dev Callback for the TokenizedStrategy to initiate a _tend call in the strategy.\n     *\n     * This can only be called after a tend() delegateCall to the TokenizedStrategy\n     * so msg.sender == address(this).\n     *\n     * We name the function `tendThis` so that `tend` calls are forwarded to\n     * the TokenizedStrategy.\n     *\n     * @param _totalIdle The amount of current idle funds that can be\n     * deployed during the tend\n     */\n    function tendThis(uint256 _totalIdle) external virtual onlySelf {\n        _tend(_totalIdle);\n    }\n\n    /**\n     * @notice Will call the internal '_emergencyWithdraw' function.\n     * @dev Callback for the TokenizedStrategy during an emergency withdraw.\n     *\n     * This can only be called after a emergencyWithdraw() delegateCall to\n     * the TokenizedStrategy so msg.sender == address(this).\n     *\n     * We name the function `shutdownWithdraw` so that `emergencyWithdraw`\n     * calls are forwarded to the TokenizedStrategy.\n     *\n     * @param _amount The amount of asset to attempt to free.\n     */\n    function shutdownWithdraw(uint256 _amount) external virtual onlySelf {\n        _emergencyWithdraw(_amount);\n    }\n\n    /**\n     * @dev Function used to delegate call the TokenizedStrategy with\n     * certain `_calldata` and return any return values.\n     *\n     * This is used to setup the initial storage of the strategy, and\n     * can be used by strategist to forward any other call to the\n     * TokenizedStrategy implementation.\n     *\n     * @param _calldata The abi encoded calldata to use in delegatecall.\n     * @return . The return value if the call was successful in bytes.\n     */\n    function _delegateCall(bytes memory _calldata) internal returns (bytes memory) {\n        // Delegate call the tokenized strategy with provided calldata.\n        (bool success, bytes memory result) = tokenizedStrategyAddress.delegatecall(_calldata);\n\n        // If the call reverted. Return the error.\n        if (!success) {\n            assembly {\n                let ptr := mload(0x40)\n                let size := returndatasize()\n                returndatacopy(ptr, 0, size)\n                revert(ptr, size)\n            }\n        }\n\n        // Return the result.\n        return result;\n    }\n\n    /**\n     * @dev Execute a function on the TokenizedStrategy and return any value.\n     *\n     * This fallback function will be executed when any of the standard functions\n     * defined in the TokenizedStrategy are called since they wont be defined in\n     * this contract.\n     *\n     * It will delegatecall the TokenizedStrategy implementation with the exact\n     * calldata and return any relevant values.\n     *\n     */\n    fallback() external {\n        // load our target address\n        address _tokenizedStrategyAddress = tokenizedStrategyAddress;\n        // Execute external function using delegatecall and return any value.\n        assembly {\n            // Copy function selector and any arguments.\n            calldatacopy(0, 0, calldatasize())\n            // Execute function delegatecall.\n            let result := delegatecall(gas(), _tokenizedStrategyAddress, 0, calldatasize(), 0, 0)\n            // Get any return value\n            returndatacopy(0, 0, returndatasize())\n            // Return any return value or error back to the caller\n            switch result\n            case 0 { revert(0, returndatasize()) }\n            default { return(0, returndatasize()) }\n        }\n    }\n}\n"},"lib/tokenized-strategy-periphery/src/Bases/Hooks/Hooks.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0\npragma solidity >=0.8.18;\n\ncontract DepositHooks {\n    function _preDepositHook(\n        uint256 assets,\n        uint256 shares,\n        address receiver\n    ) internal virtual {}\n\n    function _postDepositHook(\n        uint256 assets,\n        uint256 shares,\n        address receiver\n    ) internal virtual {}\n}\n\ncontract WithdrawHooks {\n    function _preWithdrawHook(\n        uint256 assets,\n        uint256 shares,\n        address receiver,\n        address owner,\n        uint256 maxLoss\n    ) internal virtual {}\n\n    function _postWithdrawHook(\n        uint256 assets,\n        uint256 shares,\n        address receiver,\n        address owner,\n        uint256 maxLoss\n    ) internal virtual {}\n}\n\ncontract TransferHooks {\n    function _preTransferHook(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    function _postTransferHook(\n        address from,\n        address to,\n        uint256 amount,\n        bool success\n    ) internal virtual {}\n}\n\ncontract ReportHooks {\n    function _preReportHook() internal virtual {}\n\n    function _postReportHook(uint256 profit, uint256 loss) internal virtual {}\n}\n\ncontract Hooks is DepositHooks, WithdrawHooks, TransferHooks, ReportHooks {}\n"},"lib/tokenized-strategy/src/interfaces/ITokenizedStrategy.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0\npragma solidity >=0.8.18;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {IERC4626} from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport {IERC20Permit} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\";\n\n// Interface that implements the 4626 standard and the implementation functions\ninterface ITokenizedStrategy is IERC4626, IERC20Permit {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event StrategyShutdown();\n\n    event NewTokenizedStrategy(\n        address indexed strategy,\n        address indexed asset,\n        string apiVersion\n    );\n\n    event Reported(\n        uint256 profit,\n        uint256 loss,\n        uint256 protocolFees,\n        uint256 performanceFees\n    );\n\n    event UpdatePerformanceFeeRecipient(\n        address indexed newPerformanceFeeRecipient\n    );\n\n    event UpdateKeeper(address indexed newKeeper);\n\n    event UpdatePerformanceFee(uint16 newPerformanceFee);\n\n    event UpdateManagement(address indexed newManagement);\n\n    event UpdateEmergencyAdmin(address indexed newEmergencyAdmin);\n\n    event UpdateProfitMaxUnlockTime(uint256 newProfitMaxUnlockTime);\n\n    event UpdatePendingManagement(address indexed newPendingManagement);\n\n    /*//////////////////////////////////////////////////////////////\n                           INITIALIZATION\n    //////////////////////////////////////////////////////////////*/\n\n    function initialize(\n        address _asset,\n        string memory _name,\n        address _management,\n        address _performanceFeeRecipient,\n        address _keeper\n    ) external;\n\n    /*//////////////////////////////////////////////////////////////\n                    NON-STANDARD 4626 OPTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function withdraw(\n        uint256 assets,\n        address receiver,\n        address owner,\n        uint256 maxLoss\n    ) external returns (uint256);\n\n    function redeem(\n        uint256 shares,\n        address receiver,\n        address owner,\n        uint256 maxLoss\n    ) external returns (uint256);\n\n    function maxWithdraw(\n        address owner,\n        uint256 /*maxLoss*/\n    ) external view returns (uint256);\n\n    function maxRedeem(\n        address owner,\n        uint256 /*maxLoss*/\n    ) external view returns (uint256);\n\n    /*//////////////////////////////////////////////////////////////\n                        MODIFIER HELPERS\n    //////////////////////////////////////////////////////////////*/\n\n    function requireManagement(address _sender) external view;\n\n    function requireKeeperOrManagement(address _sender) external view;\n\n    function requireEmergencyAuthorized(address _sender) external view;\n\n    /*//////////////////////////////////////////////////////////////\n                        KEEPERS FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function tend() external;\n\n    function report() external returns (uint256 _profit, uint256 _loss);\n\n    /*//////////////////////////////////////////////////////////////\n                        CONSTANTS\n    //////////////////////////////////////////////////////////////*/\n\n    function MAX_FEE() external view returns (uint16);\n\n    function FACTORY() external view returns (address);\n\n    /*//////////////////////////////////////////////////////////////\n                            GETTERS\n    //////////////////////////////////////////////////////////////*/\n\n    function apiVersion() external view returns (string memory);\n\n    function pricePerShare() external view returns (uint256);\n\n    function management() external view returns (address);\n\n    function pendingManagement() external view returns (address);\n\n    function keeper() external view returns (address);\n\n    function emergencyAdmin() external view returns (address);\n\n    function performanceFee() external view returns (uint16);\n\n    function performanceFeeRecipient() external view returns (address);\n\n    function fullProfitUnlockDate() external view returns (uint256);\n\n    function profitUnlockingRate() external view returns (uint256);\n\n    function profitMaxUnlockTime() external view returns (uint256);\n\n    function lastReport() external view returns (uint256);\n\n    function isShutdown() external view returns (bool);\n\n    function unlockedShares() external view returns (uint256);\n\n    /*//////////////////////////////////////////////////////////////\n                            SETTERS\n    //////////////////////////////////////////////////////////////*/\n\n    function setPendingManagement(address) external;\n\n    function acceptManagement() external;\n\n    function setKeeper(address _keeper) external;\n\n    function setEmergencyAdmin(address _emergencyAdmin) external;\n\n    function setPerformanceFee(uint16 _performanceFee) external;\n\n    function setPerformanceFeeRecipient(\n        address _performanceFeeRecipient\n    ) external;\n\n    function setProfitMaxUnlockTime(uint256 _profitMaxUnlockTime) external;\n\n    function setName(string calldata _newName) external;\n\n    function shutdownStrategy() external;\n\n    function emergencyWithdraw(uint256 _amount) external;\n}\n"},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/utils/Address.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, \"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(address target, bytes memory data, uint256 value) 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        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or 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            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\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            /// @solidity memory-safe-assembly\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"},"lib/openzeppelin/contracts/utils/Panic.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"},"lib/openzeppelin/contracts/utils/math/SafeCast.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool 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 */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev An uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\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        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(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        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(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        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(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        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(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        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(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        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\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        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\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        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\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    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\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    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\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    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\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    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\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    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\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        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n\n    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"},"src/libraries/periphery/MorphoStorageLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {Id} from \"../../interfaces/IMorpho.sol\";\n\n/// @title MorphoStorageLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Helper library exposing getters to access Morpho storage variables' slot.\n/// @dev This library is not used in Morpho itself and is intended to be used by integrators.\nlibrary MorphoStorageLib {\n    /* SLOTS */\n\n    uint256 internal constant OWNER_SLOT = 0;\n    uint256 internal constant FEE_RECIPIENT_SLOT = 1;\n    uint256 internal constant POSITION_SLOT = 2;\n    uint256 internal constant MARKET_SLOT = 3;\n    uint256 internal constant IS_IRM_ENABLED_SLOT = 4;\n    uint256 internal constant IS_LLTV_ENABLED_SLOT = 5;\n    uint256 internal constant NONCE_SLOT = 6;\n    uint256 internal constant ID_TO_MARKET_PARAMS_SLOT = 7;\n\n    /* SLOT OFFSETS */\n\n    uint256 internal constant LOAN_TOKEN_OFFSET = 0;\n    uint256 internal constant COLLATERAL_TOKEN_OFFSET = 1;\n    uint256 internal constant ORACLE_OFFSET = 2;\n    uint256 internal constant IRM_OFFSET = 3;\n    uint256 internal constant LLTV_OFFSET = 4;\n    uint256 internal constant CREDIT_LINE_OFFSET = 5;\n\n    uint256 internal constant SUPPLY_SHARES_OFFSET = 0;\n    uint256 internal constant BORROW_SHARES_AND_COLLATERAL_OFFSET = 1;\n\n    uint256 internal constant TOTAL_SUPPLY_ASSETS_AND_SHARES_OFFSET = 0;\n    uint256 internal constant TOTAL_BORROW_ASSETS_AND_SHARES_OFFSET = 1;\n    uint256 internal constant LAST_UPDATE_AND_FEE_OFFSET = 2;\n\n    /* GETTERS */\n\n    function ownerSlot() internal pure returns (bytes32) {\n        return bytes32(OWNER_SLOT);\n    }\n\n    function feeRecipientSlot() internal pure returns (bytes32) {\n        return bytes32(FEE_RECIPIENT_SLOT);\n    }\n\n    function positionSupplySharesSlot(Id id, address user) internal pure returns (bytes32) {\n        return\n            bytes32(\n                uint256(keccak256(abi.encode(user, keccak256(abi.encode(id, POSITION_SLOT))))) + SUPPLY_SHARES_OFFSET\n            );\n    }\n\n    function positionBorrowSharesAndCollateralSlot(Id id, address user) internal pure returns (bytes32) {\n        return bytes32(\n            uint256(keccak256(abi.encode(user, keccak256(abi.encode(id, POSITION_SLOT)))))\n                + BORROW_SHARES_AND_COLLATERAL_OFFSET\n        );\n    }\n\n    function marketTotalSupplyAssetsAndSharesSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + TOTAL_SUPPLY_ASSETS_AND_SHARES_OFFSET);\n    }\n\n    function marketTotalBorrowAssetsAndSharesSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + TOTAL_BORROW_ASSETS_AND_SHARES_OFFSET);\n    }\n\n    function marketLastUpdateAndFeeSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + LAST_UPDATE_AND_FEE_OFFSET);\n    }\n\n    function isIrmEnabledSlot(address irm) internal pure returns (bytes32) {\n        return keccak256(abi.encode(irm, IS_IRM_ENABLED_SLOT));\n    }\n\n    function isLltvEnabledSlot(uint256 lltv) internal pure returns (bytes32) {\n        return keccak256(abi.encode(lltv, IS_LLTV_ENABLED_SLOT));\n    }\n\n    function nonceSlot(address authorizer) internal pure returns (bytes32) {\n        return keccak256(abi.encode(authorizer, NONCE_SLOT));\n    }\n\n    function idToLoanTokenSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + LOAN_TOKEN_OFFSET);\n    }\n\n    function idToCollateralTokenSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + COLLATERAL_TOKEN_OFFSET);\n    }\n\n    function idToOracleSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + ORACLE_OFFSET);\n    }\n\n    function idToIrmSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + IRM_OFFSET);\n    }\n\n    function idToLltvSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + LLTV_OFFSET);\n    }\n\n    function idToCreditLineSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + CREDIT_LINE_OFFSET);\n    }\n}\n"},"src/interfaces/IIrm.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.18;\n\nimport {MarketParams, Market} from \"./IMorpho.sol\";\n\n/// @title IIrm\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Interface that Interest Rate Models (IRMs) used by Morpho must implement.\ninterface IIrm {\n    /// @notice Returns the borrow rate per second (scaled by WAD) of the market `marketParams`.\n    /// @dev Assumes that `market` corresponds to `marketParams`.\n    function borrowRate(MarketParams memory marketParams, Market memory market) external returns (uint256);\n\n    /// @notice Returns the borrow rate per second (scaled by WAD) of the market `marketParams` without modifying any\n    /// storage.\n    /// @dev Assumes that `market` corresponds to `marketParams`.\n    function borrowRateView(MarketParams memory marketParams, Market memory market) external view returns (uint256);\n}\n"},"src/libraries/MathLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nuint256 constant WAD = 1e18;\n\n/// @title MathLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Library to manage fixed-point arithmetic.\nlibrary MathLib {\n    /// @dev Returns (`x` * `y`) / `WAD` rounded down.\n    function wMulDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, y, WAD);\n    }\n\n    /// @dev Returns (`x` * `WAD`) / `y` rounded down.\n    function wDivDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, WAD, y);\n    }\n\n    /// @dev Returns (`x` * `WAD`) / `y` rounded up.\n    function wDivUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, WAD, y);\n    }\n\n    /// @dev Returns (`x` * `y`) / `d` rounded down.\n    function mulDivDown(uint256 x, uint256 y, uint256 d) internal pure returns (uint256) {\n        return (x * y) / d;\n    }\n\n    /// @dev Returns (`x` * `y`) / `d` rounded up.\n    function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256) {\n        return (x * y + (d - 1)) / d;\n    }\n\n    /// @dev Returns the sum of the first three non-zero terms of a Taylor expansion of e^(nx) - 1, to approximate a\n    /// continuous compound interest rate.\n    function wTaylorCompounded(uint256 x, uint256 n) internal pure returns (uint256) {\n        uint256 firstTerm = x * n;\n        uint256 secondTerm = mulDivDown(firstTerm, firstTerm, 2 * WAD);\n        uint256 thirdTerm = mulDivDown(secondTerm, firstTerm, 3 * WAD);\n\n        return firstTerm + secondTerm + thirdTerm;\n    }\n\n    /// @dev Computes the inverse of wTaylorCompounded, finding the rate that produces the given growth factor.\n    /// Uses a 3-term Taylor series approximation of ln(x) to solve for rate in the compound interest formula.\n    /// Formula: rate = ln(x) / n ≈ [(x-1) - (x-1)²/2 + (x-1)³/3] / n\n    ///\n    /// Accuracy notes:\n    /// - The Taylor approximation of ln(x) is most accurate for x close to 1\n    /// - At growth factor x = 1.69*WAD (69% growth), approximation error < 2%\n    /// - At growth factor x = 2*WAD (100% growth, where ln(2) ≈ 0.69), approximation error < 5%\n    /// - Accuracy decreases for larger growth factors; not recommended for x > 2.5*WAD (150% growth)\n    ///\n    /// Example: If debt grew from 1000 to 1105 over 1 year (10.5% growth):\n    /// - x = 1.105*WAD (growth factor)\n    /// - n = 365 days (time period)\n    /// - Returns ~10% APR as rate per second\n    ///\n    /// @param x The growth factor scaled by WAD (e.g., 1.1*WAD for 10% growth). Must be >= WAD.\n    /// @param n The time period over which the growth occurred (in seconds)\n    /// @return The continuously compounded rate per second that would produce this growth (scaled by WAD)\n    function wInverseTaylorCompounded(uint256 x, uint256 n) internal pure returns (uint256) {\n        require(x >= WAD, \"ln undefined\");\n\n        uint256 firstTerm = x - WAD;\n        uint256 secondTerm = wMulDown(firstTerm, firstTerm);\n        uint256 thirdTerm = wMulDown(secondTerm, firstTerm);\n\n        uint256 series = firstTerm - secondTerm / 2 + thirdTerm / 3;\n\n        return series / n;\n    }\n}\n"},"src/libraries/UtilsLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {ErrorsLib} from \"../libraries/ErrorsLib.sol\";\n\n/// @title UtilsLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Library exposing helpers.\n/// @dev Inspired by https://github.com/morpho-org/morpho-utils.\nlibrary UtilsLib {\n    /// @dev Returns true if there is exactly one zero among `x` and `y`.\n    function exactlyOneZero(uint256 x, uint256 y) internal pure returns (bool z) {\n        assembly {\n            z := xor(iszero(x), iszero(y))\n        }\n    }\n\n    /// @dev Returns the min of `x` and `y`.\n    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        assembly {\n            z := xor(x, mul(xor(x, y), lt(y, x)))\n        }\n    }\n\n    /// @dev Returns `x` safely cast to uint128.\n    function toUint128(uint256 x) internal pure returns (uint128) {\n        if (x > type(uint128).max) revert ErrorsLib.MaxUint128Exceeded();\n        return uint128(x);\n    }\n\n    /// @dev Returns max(0, x - y).\n    function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        assembly {\n            z := mul(gt(x, y), sub(x, y))\n        }\n    }\n}\n"},"src/libraries/MarketParamsLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {Id, MarketParams} from \"../interfaces/IMorpho.sol\";\n\n/// @title MarketParamsLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Library to convert a market to its id.\nlibrary MarketParamsLib {\n    /// @notice The length of the data used to compute the id of a market.\n    /// @dev The length is 6 * 32 because `MarketParams` has 6 variables of 32 bytes each.\n    uint256 internal constant MARKET_PARAMS_BYTES_LENGTH = 6 * 32;\n\n    /// @notice Returns the id of the market `marketParams`.\n    function id(MarketParams memory marketParams) internal pure returns (Id marketParamsId) {\n        assembly (\"memory-safe\") {\n            marketParamsId := keccak256(marketParams, MARKET_PARAMS_BYTES_LENGTH)\n        }\n    }\n}\n"},"lib/openzeppelin/contracts/token/ERC20/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\n}\n"},"lib/openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\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"},"lib/openzeppelin/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\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    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\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     * 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 default value returned by this function, unless\n     * it's 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(address from, address to, uint256 amount) 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, allowance(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 = allowance(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 `from` to `to`.\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(address from, address to, uint256 amount) 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            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\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        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\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            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\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(address owner, address spender, uint256 amount) 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 Updates `owner` s allowance for `spender` based on spent `amount`.\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(address owner, address spender, uint256 amount) 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(address from, address to, uint256 amount) 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(address from, address to, uint256 amount) internal virtual {}\n}\n"},"lib/openzeppelin/contracts/proxy/utils/Initializable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reinitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\n     *\n     * NOTE: Consider following the ERC-7201 formula to derive storage locations.\n     */\n    function _initializableStorageSlot() internal pure virtual returns (bytes32) {\n        return INITIALIZABLE_STORAGE;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        bytes32 slot = _initializableStorageSlot();\n        assembly {\n            $.slot := slot\n        }\n    }\n}\n"},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\nimport \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n *\n * _Available since v4.7._\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n    event Withdraw(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}\n"},"src/libraries/ErrorsLib.sol":{"content":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\n/// @title ErrorsLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Library exposing custom errors.\nlibrary ErrorsLib {\n    /// @notice Thrown when the caller is not the owner.\n    error NotOwner();\n\n    /// @notice Thrown when the caller is not the market's credit line.\n    error NotCreditLine();\n\n    /// @notice Thrown when the caller is not the market's helper.\n    error NotHelper();\n\n    /// @notice Thrown when the caller is not the market's usd3.\n    error NotUsd3();\n\n    /// @notice Thrown when the caller is not the owner or ozd.\n    error NotOwnerOrOzd();\n\n    /// @notice Thrown when the user is unverified.\n    error Unverified();\n\n    /// @notice Thrown when the LLTV to enable exceeds the maximum LLTV.\n    error MaxLltvExceeded();\n\n    /// @notice Thrown when the LTV to enable exceeds the maximum LTV.\n    error MaxLtvExceeded();\n\n    /// @notice Thrown when the VV to enable exceeds the maximum VV.\n    error MaxVvExceeded();\n\n    /// @notice Thrown when the credit to enable exceeds the maximum credit.\n    error MaxCreditLineExceeded();\n\n    /// @notice Thrown when the credit to enable is below the minimum credit.\n    error MinCreditLineExceeded();\n\n    /// @notice Thrown when the fee to set exceeds the maximum fee.\n    error MaxFeeExceeded();\n\n    /// @notice Thrown when the value is already set.\n    error AlreadySet();\n\n    /// @notice Thrown when trying to renounce the owner role.\n    error CannotRenounceOwnerRole();\n\n    /// @notice Thrown when the IRM is not enabled at market creation.\n    error IrmNotEnabled();\n\n    /// @notice Thrown when the LLTV is not enabled at market creation.\n    error LltvNotEnabled();\n\n    /// @notice Thrown when the market is already created.\n    error MarketAlreadyCreated();\n\n    /// @notice Thrown when a token to transfer doesn't have code.\n    error NoCode();\n\n    /// @notice Thrown when the market is not created.\n    error MarketNotCreated();\n\n    /// @notice Thrown when not exactly one of the input amount is zero.\n    error InconsistentInput();\n\n    /// @notice Thrown when zero assets is passed as input.\n    error ZeroAssets();\n\n    /// @notice Thrown when a zero address is passed as input.\n    error ZeroAddress();\n\n    /// @notice Thrown when an array has an invalid length.\n    error InvalidArrayLength();\n\n    /// @notice Thrown when the caller is not authorized to conduct an action.\n    error Unauthorized();\n\n    /// @notice Thrown when the collateral is insufficient to `borrow` or `withdrawCollateral`.\n    error InsufficientCollateral();\n\n    /// @notice Thrown when the liquidity is insufficient to `withdraw` or `borrow`.\n    error InsufficientLiquidity();\n\n    /// @notice Thrown when borrowing shares would result in borrowing zero assets.\n    error InsufficientBorrowAmount();\n\n    /// @notice Thrown when a token transfer reverted.\n    error TransferReverted();\n\n    /// @notice Thrown when a token transfer returned false.\n    error TransferReturnedFalse();\n\n    /// @notice Thrown when a token transferFrom reverted.\n    error TransferFromReverted();\n\n    /// @notice Thrown when a token transferFrom returned false\n    error TransferFromReturnedFalse();\n\n    /// @notice Thrown when the maximum uint128 is exceeded.\n    error MaxUint128Exceeded();\n\n    /// @notice Thrown when the premium rate exceeds the maximum allowed.\n    error MaxDrpExceeded();\n\n    /// @notice Thrown when the borrower has outstanding repayment obligations.\n    error OutstandingRepayment();\n\n    /// @notice Thrown when the protocol is paused.\n    error Paused();\n\n    /// @notice Thrown when trying to close a future cycle.\n    error CannotCloseFutureCycle();\n\n    /// @notice Thrown when cycle duration is invalid.\n    error InvalidCycleDuration();\n\n    /// @notice Thrown when no payment cycles exist.\n    error NoCyclesExist();\n\n    /// @notice Thrown when cycle ID is invalid.\n    error InvalidCycleId();\n\n    /// @notice Thrown when partial payment is attempted but full obligation payment is required.\n    error MustPayFullObligation();\n\n    /// @notice Thrown when repayment basis points exceed 100%.\n    error RepaymentExceedsHundredPercent();\n\n    /// @notice Thrown when an invalid markdown manager is set.\n    error InvalidMarkdownManager();\n\n    /// @notice Thrown when trying to settle non-existent debt.\n    error NoAccountToSettle();\n\n    /// @notice Thrown when the cover amount exceeds the assets amount.\n    error InvalidCoverAmount();\n\n    /// @notice Thrown when attempting operations on a frozen market.\n    error MarketFrozen();\n\n    /// @notice Thrown when a borrow would exceed the protocol debt cap.\n    error DebtCapExceeded();\n\n    /// @notice Thrown when borrow or repay would result in debt below minimum borrow amount.\n    error BelowMinimumBorrow();\n\n    /// @notice Thrown when supply shares exceed the maximum ratio to supply assets.\n    error SupplySharePriceBelowFloor();\n\n    /// @notice Thrown when new lending is attempted in a market that is winding down.\n    error MarketInWindDown();\n}\n"},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/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"},"lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (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    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"}},"compilation":{"language":"Solidity","compiler":"solc","compilerVersion":"0.8.22+commit.4fc1097e","compilerSettings":{"viaIR":true,"metadata":{"appendCBOR":true,"bytecodeHash":"none","useLiteralContent":false},"optimizer":{"runs":999999,"enabled":true},"evmVersion":"shanghai","remappings":["forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/halmos-cheatcodes/src/","@tokenized-strategy/=lib/tokenized-strategy/src/","@periphery/=lib/tokenized-strategy-periphery/src/","@openzeppelin/=lib/tokenized-strategy-periphery/lib/openzeppelin-contracts/","@yearn-vaults/=lib/tokenized-strategy-periphery/lib/yearn-vaults-v3/contracts/","ds-test/=lib/tokenized-strategy-periphery/lib/forge-std/lib/ds-test/src/","erc4626-tests/=lib/tokenized-strategy/lib/erc4626-tests/","openzeppelin-contracts/=lib/tokenized-strategy/lib/openzeppelin-contracts/","openzeppelin/=lib/openzeppelin/","tokenized-strategy-periphery/=lib/tokenized-strategy-periphery/","tokenized-strategy/=lib/tokenized-strategy/","yearn-vaults-v3/=lib/tokenized-strategy-periphery/lib/yearn-vaults-v3/"]},"name":"USD3","fullyQualifiedName":"src/usd3/USD3.sol:USD3"},"matchId":"51267648","creationMatch":"match","runtimeMatch":"match","verifiedAt":"2026-09-18T20:46:24Z","match":"match","chainId":"1","address":"0xd1F1c3F485063712873285BF4ef25ab068f13893"}