{"status":"1","message":"OK","result":[{"SourceCode":"{{\"language\":\"Solidity\",\"sources\":{\"src/PSM.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/interfaces/IERC4626.sol\\\";\\nimport {PSMFed} from \\\"src/PSMFed.sol\\\";\\n\\ninterface IController {\\n    function onBuy(address user, address to, uint256 amount) external returns (bool);\\n    function onSell(address user, address to, uint256 amount) external returns (bool);\\n}\\n\\ncontract PSM {\\n    using SafeERC20 for IERC20;\\n\\n    IERC20 public immutable collateral;\\n    IERC20 public immutable DOLA;\\n    address public immutable fed; // PSMFed contract address\\n\\n    address public gov;\\n    address public pendingGov;\\n    IController public controller; // Controller contract address\\n    uint256 public buyFeeBps; // e.g., 50 = 0.5%\\n    uint256 public sellFeeBps; // e.g., 50 = 0.5%\\n    uint256 public constant BPS_DENOMINATOR = 10_000;\\n    uint256 public supply; // Collateral supplied in the PSM (excluding fees and profit)\\n    IERC4626 public vault;\\n    uint256 public minTotalSupply;\\n\\n    event GovChanged(address indexed oldGov, address indexed newGov);\\n    event PendingGovUpdated(address indexed pendingGov);\\n    event ControllerChanged(address indexed oldController, address indexed newController);\\n    event VaultMigrated(address indexed oldVault, address indexed newVault);\\n    event BuyFeeUpdated(uint256 oldFee, uint256 newFee);\\n    event SellFeeUpdated(uint256 oldFee, uint256 newFee);\\n    event SupplyCapUpdated(uint256 newSupplyCap);\\n    event Buy(address indexed user, uint256 purchased, uint256 spent);\\n    event Sell(address indexed user, uint256 sold, uint256 received);\\n    event ProfitTaken(uint256 profit);\\n    event MinTotalSupplyUpdated(uint256 oldMinTotalSupply, uint256 newMinTotalSupply);\\n\\n    constructor(address _collateral, address _vault, address _DOLA, address _gov, address _controller, address _chair) {\\n        collateral = IERC20(_collateral);\\n        vault = IERC4626(_vault);\\n        DOLA = IERC20(_DOLA);\\n        gov = _gov;\\n        controller = IController(_controller);\\n        fed = address(new PSMFed(address(this), _gov, _chair, _DOLA));\\n        DOLA.approve(fed, type(uint256).max);\\n    }\\n\\n    modifier onlyGov() {\\n        require(msg.sender == gov, \\\"Not gov\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice Allows to buy DOLA minus fee using collateral.\\n     * @param collateralAmountIn Amount of collateral to sell for DOLA.\\n     */\\n    function buy(uint256 collateralAmountIn) external {\\n        buy(msg.sender, collateralAmountIn);\\n    }\\n\\n    /**\\n     * @notice Allows to buy DOLA minus fee using collateral.\\n     * @param to DOLA receiver.\\n     * @param collateralAmountIn Amount of collateral to sell for DOLA.\\n     */\\n    function buy(address to, uint256 collateralAmountIn) public {\\n        require(collateralAmountIn > 0, \\\"Amount must be > 0\\\");\\n        require(vault.totalSupply() >= minTotalSupply, \\\"Min total supply not met\\\");\\n        require(controller.onBuy(msg.sender, to, collateralAmountIn), \\\"Denied by controller\\\");\\n        uint256 amountOut = collateralAmountIn;\\n\\n        if (buyFeeBps > 0) {\\n            uint256 fee = (collateralAmountIn * buyFeeBps) / BPS_DENOMINATOR;\\n            amountOut -= fee;\\n        }\\n        supply += amountOut;\\n\\n        collateral.safeTransferFrom(msg.sender, address(this), collateralAmountIn);\\n        collateral.approve(address(vault), collateralAmountIn);\\n        uint256 shares = vault.deposit(collateralAmountIn, address(this));\\n        require(shares > 0, \\\"Deposit failed\\\");\\n        DOLA.safeTransfer(to, amountOut);\\n        emit Buy(msg.sender, amountOut, collateralAmountIn);\\n    }\\n\\n    /**\\n     * @notice Allows to sell DOLA for collateral minus fee.\\n     * @param dolaAmountIn Amount of DOLA to sell.\\n     */\\n    function sell(uint256 dolaAmountIn) external {\\n        sell(msg.sender, dolaAmountIn);\\n    }\\n\\n    /**\\n     * @notice Allows to sell DOLA for collateral minus fee.\\n     * @param to Address to receive the collateral.\\n     * @param dolaAmountIn Amount of DOLA to sell.\\n     */\\n    function sell(address to, uint256 dolaAmountIn) public {\\n        require(dolaAmountIn > 0, \\\"Amount must be > 0\\\");\\n        require(controller.onSell(msg.sender, to, dolaAmountIn), \\\"Denied by controller\\\");\\n        supply -= dolaAmountIn;\\n        DOLA.safeTransferFrom(msg.sender, address(this), dolaAmountIn);\\n\\n        uint256 amountOut = dolaAmountIn;\\n\\n        if (sellFeeBps > 0) {\\n            uint256 fee = (dolaAmountIn * sellFeeBps) / BPS_DENOMINATOR;\\n            amountOut -= fee;\\n        }\\n\\n        vault.withdraw(amountOut, to, address(this));\\n        emit Sell(msg.sender, dolaAmountIn, amountOut);\\n    }\\n\\n    /**\\n     * @notice Takes profit from the vault and transfers it to the governance address.\\n     * @dev Can be called by anyone to transfer profits and fees to governance.\\n     */\\n    function takeProfit() public {\\n        uint256 profit = getProfit();\\n        if (profit > 0) {\\n            vault.withdraw(profit, gov, address(this));\\n        }\\n        emit ProfitTaken(profit);\\n    }\\n\\n    /**\\n     * @notice Returns the total collateral reserves in the vault, including profit and fees.\\n     * @return Total reserves in the vault.\\n     */\\n    function getTotalReserves() public view returns (uint256) {\\n        return vault.previewRedeem(vault.balanceOf(address(this)));\\n    }\\n\\n    /**\\n     * @notice Returns the total profit made by the PSM.\\n     * @return Total profit in the PSM.\\n     */\\n    function getProfit() public view returns (uint256) {\\n        uint256 totalReserves = getTotalReserves();\\n        return totalReserves > supply ? totalReserves - supply : 0;\\n    }\\n\\n    /**\\n     * @notice Returns the amount of DOLA that can be obtained for a given amount of collateral.\\n     * @param collateralIn Amount of collateral to convert to DOLA.\\n     * @return Amount of DOLA that will be received after fees.\\n     */\\n    function getDolaOut(uint256 collateralIn) external view returns (uint256) {\\n        uint256 fee = (collateralIn * buyFeeBps) / BPS_DENOMINATOR;\\n        return collateralIn - fee;\\n    }\\n\\n    /**\\n     * @notice Returns the amount of collateral that can be obtained for a given amount of DOLA.\\n     * @param dolaIn Amount of DOLA to convert to collateral.\\n     * @return Amount of collateral that will be received after fees.\\n     */\\n    function getCollateralOut(uint256 dolaIn) external view returns (uint256) {\\n        uint256 fee = (dolaIn * sellFeeBps) / BPS_DENOMINATOR;\\n        return dolaIn - fee;\\n    }\\n\\n    /**\\n     * @notice Migrate the vault to a new IERC4626 vault.\\n     * @dev Can only be called by governance and will take profit before migration.\\n     * @param newVault Address of the new vault to migrate to.\\n     * @param minCollateralAmount Minimum amount of collateral to be deposited in the new vault.\\n     * @param minSharesOut Minimum amount of shares to receive from the new vault.\\n     */\\n    function migrate(address newVault, uint256 minCollateralAmount, uint256 minSharesOut) external onlyGov {\\n        require(newVault != address(0), \\\"Zero address\\\");\\n        require(IERC4626(newVault).asset() == address(collateral), \\\"New vault must accept collateral\\\");\\n\\n        takeProfit();\\n\\n        if (vault.balanceOf(address(this)) != 0) {\\n            vault.redeem(vault.balanceOf(address(this)), address(this), address(this));\\n        }\\n\\n        address oldVault = address(vault);\\n        vault = IERC4626(newVault);\\n        require(vault.totalSupply() >= minTotalSupply, \\\"New vault does not meet min total supply\\\");\\n\\n        uint256 collateralBalance = collateral.balanceOf(address(this));\\n        require(collateralBalance >= minCollateralAmount, \\\"Insufficient collateral balance for migration\\\");\\n        if (collateralBalance > 0) {\\n            collateral.approve(address(vault), collateralBalance);\\n            uint256 sharesOut = vault.deposit(collateralBalance, address(this));\\n            require(sharesOut >= minSharesOut, \\\"Insufficient shares received from new vault\\\");\\n        }\\n        emit VaultMigrated(oldVault, newVault);\\n    }\\n\\n    /**\\n     * @notice Allows governance to sweep any ERC20 tokens from the contract.\\n     * @dev Can only be called by governance.\\n     * @param token The ERC20 token to sweep.\\n     */\\n    function sweep(IERC20 token) external onlyGov {\\n        token.safeTransfer(gov, token.balanceOf(address(this)));\\n    }\\n\\n    /**\\n     * @notice Allows governance to set the buy fee.\\n     * @dev The fee is specified in basis points (bps), where 100 bps = 1%.\\n     */\\n    function setBuyFeeBps(uint256 newFee) external onlyGov {\\n        require(newFee <= BPS_DENOMINATOR, \\\"Fee too high\\\");\\n        emit BuyFeeUpdated(buyFeeBps, newFee);\\n        buyFeeBps = newFee;\\n    }\\n\\n    /**\\n     * @notice Allows governance to set the sell fee.\\n     * @dev The fee is specified in basis points (bps), where 100 bps = 1%.\\n     */\\n    function setSellFeeBps(uint256 newFee) external onlyGov {\\n        require(newFee <= BPS_DENOMINATOR, \\\"Fee too high\\\");\\n        emit SellFeeUpdated(sellFeeBps, newFee);\\n        sellFeeBps = newFee;\\n    }\\n\\n    /**\\n     * @notice Allows governance to set the minimum vault total supply.\\n     * @dev This is used to ensure that the vault has enough shares before allowing buy operations.\\n     * @param _minTotalSupply Minimum total supply that must have been already minted in the vault.\\n     */\\n    function setMinTotalSupply(uint256 _minTotalSupply) external onlyGov {\\n        require(_minTotalSupply > 0, \\\"Min total supply must be > 0\\\");\\n        emit MinTotalSupplyUpdated(minTotalSupply, _minTotalSupply);\\n        minTotalSupply = _minTotalSupply;\\n    }\\n\\n    /**\\n     * @notice Allows governance to set a new pending governance.\\n     * @dev The pending governance must accept the role.\\n     * @param _pendingGov Address of the new pending governance.\\n     */\\n    function setPendingGov(address _pendingGov) external onlyGov {\\n        pendingGov = _pendingGov;\\n        emit PendingGovUpdated(_pendingGov);\\n    }\\n\\n    /**\\n     * @notice Allows the pending governance to claim the governance role.\\n     * @dev Can only be called by the pending governance.\\n     */\\n    function claimPendingGov() external {\\n        require(msg.sender == pendingGov, \\\"Not pending gov\\\");\\n        emit GovChanged(gov, pendingGov);\\n        gov = pendingGov;\\n        pendingGov = address(0);\\n    }\\n\\n    /**\\n     * @notice Allows governance to set a new controller.\\n     * @dev The new controller must not be the zero address.\\n     * @param newController Address of the new controller.\\n     */\\n    function setController(address newController) external onlyGov {\\n        require(newController != address(0), \\\"Zero address\\\");\\n        emit ControllerChanged(address(controller), newController);\\n        controller = IController(newController);\\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/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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    /**\\n     * @dev An operation with an ERC-20 token failed.\\n     */\\n    error SafeERC20FailedOperation(address token);\\n\\n    /**\\n     * @dev Indicates a failed `decreaseAllowance` request.\\n     */\\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\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.encodeCall(token.transfer, (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.encodeCall(token.transferFrom, (from, to, value)));\\n    }\\n\\n    /**\\n     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n     */\\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n    }\\n\\n    /**\\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n     */\\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, 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     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n     * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n     */\\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 oldAllowance = token.allowance(address(this), spender);\\n        forceApprove(token, spender, oldAllowance + value);\\n    }\\n\\n    /**\\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n     * value, non-reverting calls are assumed to be successful.\\n     *\\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n     * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n     */\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n        unchecked {\\n            uint256 currentAllowance = token.allowance(address(this), spender);\\n            if (currentAllowance < requestedDecrease) {\\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n            }\\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\\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     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n     * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n     * set here.\\n     */\\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n        if (!_callOptionalReturnBool(token, approvalCall)) {\\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n            _callOptionalReturn(token, approvalCall);\\n        }\\n    }\\n\\n    /**\\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n     * targeting contracts.\\n     *\\n     * Reverts if the returned value is other than `true`.\\n     */\\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n        if (to.code.length == 0) {\\n            safeTransfer(token, to, value);\\n        } else if (!token.transferAndCall(to, value, data)) {\\n            revert SafeERC20FailedOperation(address(token));\\n        }\\n    }\\n\\n    /**\\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n     * targeting contracts.\\n     *\\n     * Reverts if the returned value is other than `true`.\\n     */\\n    function transferFromAndCallRelaxed(\\n        IERC1363 token,\\n        address from,\\n        address to,\\n        uint256 value,\\n        bytes memory data\\n    ) internal {\\n        if (to.code.length == 0) {\\n            safeTransferFrom(token, from, to, value);\\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\\n            revert SafeERC20FailedOperation(address(token));\\n        }\\n    }\\n\\n    /**\\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n     * targeting contracts.\\n     *\\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n     * once without retrying, and relies on the returned value to be true.\\n     *\\n     * Reverts if the returned value is other than `true`.\\n     */\\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n        if (to.code.length == 0) {\\n            forceApprove(token, to, value);\\n        } else if (!token.approveAndCall(to, value, data)) {\\n            revert SafeERC20FailedOperation(address(token));\\n        }\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     * @param token The token targeted by the call.\\n     * @param data The call data (encoded using abi.encode or one of its variants).\\n     *\\n     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n     */\\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n        uint256 returnSize;\\n        uint256 returnValue;\\n        assembly (\\\"memory-safe\\\") {\\n            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n            // bubble errors\\n            if iszero(success) {\\n                let ptr := mload(0x40)\\n                returndatacopy(ptr, 0, returndatasize())\\n                revert(ptr, returndatasize())\\n            }\\n            returnSize := returndatasize()\\n            returnValue := mload(0)\\n        }\\n\\n        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n            revert SafeERC20FailedOperation(address(token));\\n        }\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     * @param token The token targeted by the call.\\n     * @param data The call data (encoded using abi.encode or one of its variants).\\n     *\\n     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n     */\\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n        bool success;\\n        uint256 returnSize;\\n        uint256 returnValue;\\n        assembly (\\\"memory-safe\\\") {\\n            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n            returnSize := returndatasize()\\n            returnValue := mload(0)\\n        }\\n        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\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\"},\"src/PSMFed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IDOLA is IERC20 {\\n    function mint(address to, uint256 amount) external;\\n    function burn(uint256 amount) external;\\n}\\n\\ncontract PSMFed {\\n    address public immutable psm;\\n    IDOLA public immutable DOLA;\\n\\n    address public gov;\\n    address public pendingGov;\\n    address public chair;\\n    uint256 public supply; // Current DOLA amount supplied to the PSM\\n    uint256 public supplyCap; // Maximum DOLA supply allowed in the PSM\\n\\n    event GovChanged(address indexed oldGov, address indexed newGov);\\n    event PendingGovUpdated(address indexed pendingGov);\\n    event ChairChanged(address indexed oldChair, address indexed newChair);\\n    event SupplyCapUpdated(uint256 oldSupplyCap, uint256 newSupplyCap);\\n\\n    constructor(address _psm, address _gov, address _chair, address _dola) {\\n        psm = _psm;\\n        gov = _gov;\\n        chair = _chair;\\n        DOLA = IDOLA(_dola);\\n    }\\n\\n    modifier onlyGov() {\\n        require(msg.sender == gov, \\\"Not governance\\\");\\n        _;\\n    }\\n\\n    modifier onlyChair() {\\n        require(msg.sender == chair, \\\"Not chair\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice Allows the chair to expand the supply of DOLA in the PSM.\\n     * @dev This function increases the supply of DOLA in the PSM and mints\\n     * the specified amount of DOLA.\\n     * @dev The amount must be greater than zero and cannot exceed the supply cap.\\n     * @param amount The amount of DOLA to expand.\\n     */\\n    function expansion(uint256 amount) external onlyChair {\\n        require(amount > 0, \\\"Amount must be > 0\\\");\\n        require(amount + supply <= supplyCap, \\\"Supply cap exceeded\\\");\\n        supply += amount;\\n        DOLA.mint(psm, amount);\\n    }\\n\\n    /**\\n     * @notice Allows the chair to contract the supply of DOLA in the PSM.\\n     * @dev This function reduces the supply of DOLA in the PSM and burns the\\n     * specified amount of DOLA.\\n     * @dev The amount must be greater than zero and cannot exceed the current supply.\\n     * @param amount The amount of DOLA to contract.\\n     */\\n    function contraction(uint256 amount) external onlyChair {\\n        require(amount > 0, \\\"Amount must be > 0\\\");\\n        supply -= amount;\\n        DOLA.transferFrom(psm, address(this), amount);\\n        DOLA.burn(amount);\\n    }\\n\\n    /**\\n     * @notice Allows governance to set a new supply cap.\\n     * @param newSupplyCap The new supply cap for DOLA in the PSM.\\n     */\\n    function setSupplyCap(uint256 newSupplyCap) external onlyGov {\\n        uint256 oldSupplyCap = supplyCap;\\n        supplyCap = newSupplyCap;\\n        emit SupplyCapUpdated(oldSupplyCap, newSupplyCap);\\n    }\\n\\n    /**\\n     * @notice Allows governance to set a new chair.\\n     * @dev The new chair must not be the zero address.\\n     * @param newChair Address of the new chair.\\n     */\\n    function setChair(address newChair) external onlyGov {\\n        address oldChair = chair;\\n        chair = newChair;\\n        emit ChairChanged(oldChair, newChair);\\n    }\\n\\n    /**\\n     * @notice Allows the current chair to resign.\\n     * @dev The chair can resign, leaving the chair address as zero.\\n     */\\n    function resign() external onlyChair {\\n        address oldChair = chair;\\n        chair = address(0);\\n        emit ChairChanged(oldChair, address(0));\\n    }\\n\\n    /**\\n     * @notice Allows governance to set a new pending governance.\\n     * @dev The pending governance must accept the role.\\n     * @param _pendingGov Address of the new pending governance.\\n     */\\n    function setPendingGov(address _pendingGov) external onlyGov {\\n        pendingGov = _pendingGov;\\n        emit PendingGovUpdated(_pendingGov);\\n    }\\n\\n    /**\\n     * @notice Allows the pending governance to claim the governance role.\\n     * @dev Can only be called by the pending governance.\\n     */\\n    function claimPendingGov() external {\\n        require(msg.sender == pendingGov, \\\"Not pending gov\\\");\\n        emit GovChanged(gov, pendingGov);\\n        gov = pendingGov;\\n        pendingGov = address(0);\\n    }\\n}\\n\"},\"lib/openzeppelin/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n    /*\\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n     * 0xb0202a11 ===\\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n     */\\n\\n    /**\\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n     * @param to The address which you want to transfer to.\\n     * @param value The amount of tokens to be transferred.\\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\\n     */\\n    function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n    /**\\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n     * @param to The address which you want to transfer to.\\n     * @param value The amount of tokens to be transferred.\\n     * @param data Additional data with no specified format, sent in call to `to`.\\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\\n     */\\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n    /**\\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n     * @param from The address which you want to send tokens from.\\n     * @param to The address which you want to transfer to.\\n     * @param value The amount of tokens to be transferred.\\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\\n     */\\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n    /**\\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n     * @param from The address which you want to send tokens from.\\n     * @param to The address which you want to transfer to.\\n     * @param value The amount of tokens to be transferred.\\n     * @param data Additional data with no specified format, sent in call to `to`.\\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\\n     */\\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n    /**\\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n     * @param spender The address which will spend the funds.\\n     * @param value The amount of tokens to be spent.\\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\\n     */\\n    function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n    /**\\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n     * @param spender The address which will spend the funds.\\n     * @param value The amount of tokens to be spent.\\n     * @param data Additional data with no specified format, sent in call to `spender`.\\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\\n     */\\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\"},\"lib/openzeppelin/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\"},\"lib/openzeppelin/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\"},\"lib/openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"}},\"settings\":{\"remappings\":[\"@openzeppelin/contracts/=lib/openzeppelin/contracts/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin/=lib/openzeppelin/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":10000},\"metadata\":{\"useLiteralContent\":false,\"bytecodeHash\":\"ipfs\",\"appendCBOR\":true},\"outputSelection\":{\"src/PSM.sol\":{\"PSM\":[\"*\"]},\"*\":{\"*\":[\"abi\",\"evm.bytecode\",\"evm.deployedBytecode\",\"evm.methodIdentifiers\",\"metadata\",\"devdoc\",\"userdoc\",\"storageLayout\",\"evm.gasEstimates\"],\"\":[\"ast\"]}},\"evmVersion\":\"shanghai\",\"viaIR\":false}}}","ABI":"[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_collateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vault\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_DOLA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_gov\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_controller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_chair\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"purchased\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"spent\",\"type\":\"uint256\"}],\"name\":\"Buy\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFee\",\"type\":\"uint256\"}],\"name\":\"BuyFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldController\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newController\",\"type\":\"address\"}],\"name\":\"ControllerChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldGov\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGov\",\"type\":\"address\"}],\"name\":\"GovChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinTotalSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinTotalSupply\",\"type\":\"uint256\"}],\"name\":\"MinTotalSupplyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"pendingGov\",\"type\":\"address\"}],\"name\":\"PendingGovUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"profit\",\"type\":\"uint256\"}],\"name\":\"ProfitTaken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"sold\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"received\",\"type\":\"uint256\"}],\"name\":\"Sell\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFee\",\"type\":\"uint256\"}],\"name\":\"SellFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSupplyCap\",\"type\":\"uint256\"}],\"name\":\"SupplyCapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldVault\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newVault\",\"type\":\"address\"}],\"name\":\"VaultMigrated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BPS_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOLA\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"collateralAmountIn\",\"type\":\"uint256\"}],\"name\":\"buy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"collateralAmountIn\",\"type\":\"uint256\"}],\"name\":\"buy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"buyFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimPendingGov\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"collateral\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"controller\",\"outputs\":[{\"internalType\":\"contract IController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fed\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dolaIn\",\"type\":\"uint256\"}],\"name\":\"getCollateralOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"collateralIn\",\"type\":\"uint256\"}],\"name\":\"getDolaOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getProfit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gov\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newVault\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minCollateralAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSharesOut\",\"type\":\"uint256\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingGov\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"dolaAmountIn\",\"type\":\"uint256\"}],\"name\":\"sell\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dolaAmountIn\",\"type\":\"uint256\"}],\"name\":\"sell\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sellFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFee\",\"type\":\"uint256\"}],\"name\":\"setBuyFeeBps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newController\",\"type\":\"address\"}],\"name\":\"setController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minTotalSupply\",\"type\":\"uint256\"}],\"name\":\"setMinTotalSupply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pendingGov\",\"type\":\"address\"}],\"name\":\"setPendingGov\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFee\",\"type\":\"uint256\"}],\"name\":\"setSellFeeBps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"sweep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"takeProfit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vault\",\"outputs\":[{\"internalType\":\"contract IERC4626\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]","ContractName":"PSM","CompilerVersion":"v0.8.20+commit.a1b79de6","OptimizationUsed":"1","Runs":"10000","ConstructorArguments":"0x000000000000000000000000dc035d45d973e3ec169d2276ddab16f1e407384f000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000926df14a23be491164dcf93f4c468a50ef659d5b000000000000000000000000e3475728673eabaec90a37aa3ae2ced9f0db5ff20000000000000000000000008f97cca30dbe80e7a8b462f1dd1a51c32accdfc8","EVMVersion":"shanghai","Library":"","LicenseType":"","Proxy":"0","Implementation":"","SwarmSource":""}]}