import { SolcMetadata } from "@owlprotocol/viem-utils";

export const StakeManager: SolcMetadata = {
    compiler: {
        version: "0.8.23+commit.f704f362",
    },
    language: "Solidity",
    output: {
        abi: [
            {
                anonymous: false,
                inputs: [
                    {
                        indexed: true,
                        internalType: "address",
                        name: "account",
                        type: "address",
                    },
                    {
                        indexed: false,
                        internalType: "uint256",
                        name: "totalDeposit",
                        type: "uint256",
                    },
                ],
                name: "Deposited",
                type: "event",
            },
            {
                anonymous: false,
                inputs: [
                    {
                        indexed: true,
                        internalType: "address",
                        name: "account",
                        type: "address",
                    },
                    {
                        indexed: false,
                        internalType: "uint256",
                        name: "totalStaked",
                        type: "uint256",
                    },
                    {
                        indexed: false,
                        internalType: "uint256",
                        name: "unstakeDelaySec",
                        type: "uint256",
                    },
                ],
                name: "StakeLocked",
                type: "event",
            },
            {
                anonymous: false,
                inputs: [
                    {
                        indexed: true,
                        internalType: "address",
                        name: "account",
                        type: "address",
                    },
                    {
                        indexed: false,
                        internalType: "uint256",
                        name: "withdrawTime",
                        type: "uint256",
                    },
                ],
                name: "StakeUnlocked",
                type: "event",
            },
            {
                anonymous: false,
                inputs: [
                    {
                        indexed: true,
                        internalType: "address",
                        name: "account",
                        type: "address",
                    },
                    {
                        indexed: false,
                        internalType: "address",
                        name: "withdrawAddress",
                        type: "address",
                    },
                    {
                        indexed: false,
                        internalType: "uint256",
                        name: "amount",
                        type: "uint256",
                    },
                ],
                name: "StakeWithdrawn",
                type: "event",
            },
            {
                anonymous: false,
                inputs: [
                    {
                        indexed: true,
                        internalType: "address",
                        name: "account",
                        type: "address",
                    },
                    {
                        indexed: false,
                        internalType: "address",
                        name: "withdrawAddress",
                        type: "address",
                    },
                    {
                        indexed: false,
                        internalType: "uint256",
                        name: "amount",
                        type: "uint256",
                    },
                ],
                name: "Withdrawn",
                type: "event",
            },
            {
                inputs: [
                    {
                        internalType: "uint32",
                        name: "unstakeDelaySec",
                        type: "uint32",
                    },
                ],
                name: "addStake",
                outputs: [],
                stateMutability: "payable",
                type: "function",
            },
            {
                inputs: [
                    {
                        internalType: "address",
                        name: "account",
                        type: "address",
                    },
                ],
                name: "balanceOf",
                outputs: [
                    {
                        internalType: "uint256",
                        name: "",
                        type: "uint256",
                    },
                ],
                stateMutability: "view",
                type: "function",
            },
            {
                inputs: [
                    {
                        internalType: "address",
                        name: "account",
                        type: "address",
                    },
                ],
                name: "depositTo",
                outputs: [],
                stateMutability: "payable",
                type: "function",
            },
            {
                inputs: [
                    {
                        internalType: "address",
                        name: "",
                        type: "address",
                    },
                ],
                name: "deposits",
                outputs: [
                    {
                        internalType: "uint256",
                        name: "deposit",
                        type: "uint256",
                    },
                    {
                        internalType: "bool",
                        name: "staked",
                        type: "bool",
                    },
                    {
                        internalType: "uint112",
                        name: "stake",
                        type: "uint112",
                    },
                    {
                        internalType: "uint32",
                        name: "unstakeDelaySec",
                        type: "uint32",
                    },
                    {
                        internalType: "uint48",
                        name: "withdrawTime",
                        type: "uint48",
                    },
                ],
                stateMutability: "view",
                type: "function",
            },
            {
                inputs: [
                    {
                        internalType: "address",
                        name: "account",
                        type: "address",
                    },
                ],
                name: "getDepositInfo",
                outputs: [
                    {
                        components: [
                            {
                                internalType: "uint256",
                                name: "deposit",
                                type: "uint256",
                            },
                            {
                                internalType: "bool",
                                name: "staked",
                                type: "bool",
                            },
                            {
                                internalType: "uint112",
                                name: "stake",
                                type: "uint112",
                            },
                            {
                                internalType: "uint32",
                                name: "unstakeDelaySec",
                                type: "uint32",
                            },
                            {
                                internalType: "uint48",
                                name: "withdrawTime",
                                type: "uint48",
                            },
                        ],
                        internalType: "struct IStakeManager.DepositInfo",
                        name: "info",
                        type: "tuple",
                    },
                ],
                stateMutability: "view",
                type: "function",
            },
            {
                inputs: [],
                name: "unlockStake",
                outputs: [],
                stateMutability: "nonpayable",
                type: "function",
            },
            {
                inputs: [
                    {
                        internalType: "address payable",
                        name: "withdrawAddress",
                        type: "address",
                    },
                ],
                name: "withdrawStake",
                outputs: [],
                stateMutability: "nonpayable",
                type: "function",
            },
            {
                inputs: [
                    {
                        internalType: "address payable",
                        name: "withdrawAddress",
                        type: "address",
                    },
                    {
                        internalType: "uint256",
                        name: "withdrawAmount",
                        type: "uint256",
                    },
                ],
                name: "withdrawTo",
                outputs: [],
                stateMutability: "nonpayable",
                type: "function",
            },
            {
                stateMutability: "payable",
                type: "receive",
            },
        ],
        devdoc: {
            kind: "dev",
            methods: {
                "addStake(uint32)": {
                    params: {
                        unstakeDelaySec: "The new lock duration before the deposit can be withdrawn.",
                    },
                },
                "balanceOf(address)": {
                    params: {
                        account: "- The account to query.",
                    },
                    returns: {
                        _0: "- The deposit (for gas payment) of the account.",
                    },
                },
                "depositTo(address)": {
                    params: {
                        account: "- The account to add to.",
                    },
                },
                "getDepositInfo(address)": {
                    params: {
                        account: "- The account to query.",
                    },
                    returns: {
                        info: "  - Full deposit information of given account.",
                    },
                },
                "withdrawStake(address)": {
                    params: {
                        withdrawAddress: "- The address to send withdrawn value.",
                    },
                },
                "withdrawTo(address,uint256)": {
                    params: {
                        withdrawAddress: "- The address to send withdrawn value.",
                        withdrawAmount: "- The amount to withdraw.",
                    },
                },
            },
            version: 1,
        },
        userdoc: {
            kind: "user",
            methods: {
                "addStake(uint32)": {
                    notice: "Add to the account's stake - amount and delay any pending unstake is first cancelled.",
                },
                "balanceOf(address)": {
                    notice: "Get account balance.",
                },
                "depositTo(address)": {
                    notice: "Add to the deposit of the given account.",
                },
                "deposits(address)": {
                    notice: "maps paymaster to their deposits and stakes",
                },
                "getDepositInfo(address)": {
                    notice: "Get deposit info.",
                },
                "unlockStake()": {
                    notice: "Attempt to unlock the stake. The value can be withdrawn (using withdrawStake) after the unstake delay.",
                },
                "withdrawStake(address)": {
                    notice: "Withdraw from the (unlocked) stake. Must first call unlockStake and wait for the unstakeDelay to pass.",
                },
                "withdrawTo(address,uint256)": {
                    notice: "Withdraw from the deposit.",
                },
            },
            notice: 'Manage deposits and stakes. Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account). Stake is value locked for at least "unstakeDelay" by a paymaster.',
            version: 1,
        },
    },
    settings: {
        compilationTarget: {
            "@account-abstraction/contracts/core/StakeManager.sol": "StakeManager",
        },
        evmVersion: "paris",
        libraries: {},
        metadata: {
            bytecodeHash: "ipfs",
            useLiteralContent: true,
        },
        optimizer: {
            enabled: true,
            runs: 1000000,
        },
        remappings: [],
        viaIR: true,
    },
    sources: {
        "@account-abstraction/contracts/core/StakeManager.sol": {
            content:
                '// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.23;\n\nimport "../interfaces/IStakeManager.sol";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n\n/**\n * Manage deposits and stakes.\n * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).\n * Stake is value locked for at least "unstakeDelay" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n    /// maps paymaster to their deposits and stakes\n    mapping(address => DepositInfo) public deposits;\n\n    /// @inheritdoc IStakeManager\n    function getDepositInfo(\n        address account\n    ) public view returns (DepositInfo memory info) {\n        return deposits[account];\n    }\n\n    /**\n     * Internal method to return just the stake info.\n     * @param addr - The account to query.\n     */\n    function _getStakeInfo(\n        address addr\n    ) internal view returns (StakeInfo memory info) {\n        DepositInfo storage depositInfo = deposits[addr];\n        info.stake = depositInfo.stake;\n        info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n    }\n\n    /// @inheritdoc IStakeManager\n    function balanceOf(address account) public view returns (uint256) {\n        return deposits[account].deposit;\n    }\n\n    receive() external payable {\n        depositTo(msg.sender);\n    }\n\n    /**\n     * Increments an account\'s deposit.\n     * @param account - The account to increment.\n     * @param amount  - The amount to increment by.\n     * @return the updated deposit of this account\n     */\n    function _incrementDeposit(address account, uint256 amount) internal returns (uint256) {\n        DepositInfo storage info = deposits[account];\n        uint256 newAmount = info.deposit + amount;\n        info.deposit = newAmount;\n        return newAmount;\n    }\n\n    /**\n     * Add to the deposit of the given account.\n     * @param account - The account to add to.\n     */\n    function depositTo(address account) public virtual payable {\n        uint256 newDeposit = _incrementDeposit(account, msg.value);\n        emit Deposited(account, newDeposit);\n    }\n\n    /**\n     * Add to the account\'s stake - amount and delay\n     * any pending unstake is first cancelled.\n     * @param unstakeDelaySec The new lock duration before the deposit can be withdrawn.\n     */\n    function addStake(uint32 unstakeDelaySec) public payable {\n        DepositInfo storage info = deposits[msg.sender];\n        require(unstakeDelaySec > 0, "must specify unstake delay");\n        require(\n            unstakeDelaySec >= info.unstakeDelaySec,\n            "cannot decrease unstake time"\n        );\n        uint256 stake = info.stake + msg.value;\n        require(stake > 0, "no stake specified");\n        require(stake <= type(uint112).max, "stake overflow");\n        deposits[msg.sender] = DepositInfo(\n            info.deposit,\n            true,\n            uint112(stake),\n            unstakeDelaySec,\n            0\n        );\n        emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n    }\n\n    /**\n     * Attempt to unlock the stake.\n     * The value can be withdrawn (using withdrawStake) after the unstake delay.\n     */\n    function unlockStake() external {\n        DepositInfo storage info = deposits[msg.sender];\n        require(info.unstakeDelaySec != 0, "not staked");\n        require(info.staked, "already unstaking");\n        uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n        info.withdrawTime = withdrawTime;\n        info.staked = false;\n        emit StakeUnlocked(msg.sender, withdrawTime);\n    }\n\n    /**\n     * Withdraw from the (unlocked) stake.\n     * Must first call unlockStake and wait for the unstakeDelay to pass.\n     * @param withdrawAddress - The address to send withdrawn value.\n     */\n    function withdrawStake(address payable withdrawAddress) external {\n        DepositInfo storage info = deposits[msg.sender];\n        uint256 stake = info.stake;\n        require(stake > 0, "No stake to withdraw");\n        require(info.withdrawTime > 0, "must call unlockStake() first");\n        require(\n            info.withdrawTime <= block.timestamp,\n            "Stake withdrawal is not due"\n        );\n        info.unstakeDelaySec = 0;\n        info.withdrawTime = 0;\n        info.stake = 0;\n        emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n        (bool success,) = withdrawAddress.call{value: stake}("");\n        require(success, "failed to withdraw stake");\n    }\n\n    /**\n     * Withdraw from the deposit.\n     * @param withdrawAddress - The address to send withdrawn value.\n     * @param withdrawAmount  - The amount to withdraw.\n     */\n    function withdrawTo(\n        address payable withdrawAddress,\n        uint256 withdrawAmount\n    ) external {\n        DepositInfo storage info = deposits[msg.sender];\n        require(withdrawAmount <= info.deposit, "Withdraw amount too large");\n        info.deposit = info.deposit - withdrawAmount;\n        emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n        (bool success,) = withdrawAddress.call{value: withdrawAmount}("");\n        require(success, "failed to withdraw");\n    }\n}\n',
            keccak256: "0x673eb19600058d8642605ca409c9e1d4cab13735564b856270b92c330ffb1b8d",
            license: "GPL-3.0-only",
        },
        "@account-abstraction/contracts/interfaces/IStakeManager.sol": {
            content:
                "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity >=0.7.5;\n\n/**\n * Manage deposits and stakes.\n * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).\n * Stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n    event Deposited(address indexed account, uint256 totalDeposit);\n\n    event Withdrawn(\n        address indexed account,\n        address withdrawAddress,\n        uint256 amount\n    );\n\n    // Emitted when stake or unstake delay are modified.\n    event StakeLocked(\n        address indexed account,\n        uint256 totalStaked,\n        uint256 unstakeDelaySec\n    );\n\n    // Emitted once a stake is scheduled for withdrawal.\n    event StakeUnlocked(address indexed account, uint256 withdrawTime);\n\n    event StakeWithdrawn(\n        address indexed account,\n        address withdrawAddress,\n        uint256 amount\n    );\n\n    /**\n     * @param deposit         - The entity's deposit.\n     * @param staked          - True if this entity is staked.\n     * @param stake           - Actual amount of ether staked for this entity.\n     * @param unstakeDelaySec - Minimum delay to withdraw the stake.\n     * @param withdrawTime    - First block timestamp where 'withdrawStake' will be callable, or zero if already locked.\n     * @dev Sizes were chosen so that deposit fits into one cell (used during handleOp)\n     *      and the rest fit into a 2nd cell (used during stake/unstake)\n     *      - 112 bit allows for 10^15 eth\n     *      - 48 bit for full timestamp\n     *      - 32 bit allows 150 years for unstake delay\n     */\n    struct DepositInfo {\n        uint256 deposit;\n        bool staked;\n        uint112 stake;\n        uint32 unstakeDelaySec;\n        uint48 withdrawTime;\n    }\n\n    // API struct used by getStakeInfo and simulateValidation.\n    struct StakeInfo {\n        uint256 stake;\n        uint256 unstakeDelaySec;\n    }\n\n    /**\n     * Get deposit info.\n     * @param account - The account to query.\n     * @return info   - Full deposit information of given account.\n     */\n    function getDepositInfo(\n        address account\n    ) external view returns (DepositInfo memory info);\n\n    /**\n     * Get account balance.\n     * @param account - The account to query.\n     * @return        - The deposit (for gas payment) of the account.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * Add to the deposit of the given account.\n     * @param account - The account to add to.\n     */\n    function depositTo(address account) external payable;\n\n    /**\n     * Add to the account's stake - amount and delay\n     * any pending unstake is first cancelled.\n     * @param _unstakeDelaySec - The new lock duration before the deposit can be withdrawn.\n     */\n    function addStake(uint32 _unstakeDelaySec) external payable;\n\n    /**\n     * Attempt to unlock the stake.\n     * The value can be withdrawn (using withdrawStake) after the unstake delay.\n     */\n    function unlockStake() external;\n\n    /**\n     * Withdraw from the (unlocked) stake.\n     * Must first call unlockStake and wait for the unstakeDelay to pass.\n     * @param withdrawAddress - The address to send withdrawn value.\n     */\n    function withdrawStake(address payable withdrawAddress) external;\n\n    /**\n     * Withdraw from the deposit.\n     * @param withdrawAddress - The address to send withdrawn value.\n     * @param withdrawAmount  - The amount to withdraw.\n     */\n    function withdrawTo(\n        address payable withdrawAddress,\n        uint256 withdrawAmount\n    ) external;\n}\n",
            keccak256: "0xbe5ca9e7f254d031687419e7b96ef48c9c63e9398bbe992dc72ffc6dc14e0a04",
            license: "GPL-3.0-only",
        },
    },
    version: 1,
};
