creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/access/Ownable2Step.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        if (pendingOwner() != sender) {\n            revert OwnableUnauthorizedAccount(sender);\n        }\n        _transferOwnership(sender);\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\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 or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\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    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\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    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) 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 FailedInnerCall();\n        }\n    }\n}\n"
      },
      "@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"
      },
      "contracts/BitcoinSafeOwner.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.25;\n\nimport {ERC1271} from \"./ERC1271.sol\";\nimport {LegacyERC1271} from \"./LegacyERC1271.sol\";\nimport {EmergencyGovernance} from \"./EmergencyGovernance.sol\";\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/// @title BitcoinSafeOwner\n/// @notice A contract to validate Bitcoin transaction signatures against an\n///         Ethereum address derived from a Bitcoin public key.\n/// @dev This contract implements ERC1271 and LegacyERC1271 to validate signatures\n///      for Bitcoin messages, accommodating both current and legacy versions of\n///      Safe contracts.\ncontract BitcoinSafeOwner is ERC1271, LegacyERC1271 {\n    // Singleton always has to be the first declared variable to ensure the same\n    // location as in the Proxy contract. It should also always be ensured the\n    // address is stored alone (uses a full word). We add a one word gap to be\n    // absolutely sure about it, no matter what fields will come next.\n    // slither-disable-start constable-states\n    // slither-disable-start unused-state\n    address internal singleton;\n    bytes32 internal __gap;\n    // slither-disable-end constable-states\n    // slither-disable-end unused-state\n\n    /// @notice Version of the contract.\n    /// @dev Must be increased for each new contract version to ensure off-chain\n    ///      upgrade signatures can be used only one time.\n    string public version;\n\n    /// @notice Represents the main part of a decoded Bitcoin address, excluding\n    ///         the network byte and checksum.\n    /// @dev It captures the RIPEMD-160 hash of the SHA-256 hash of the public\n    ///      key or redeem script hash, which is derived from a Bitcoin address\n    ///      after removing its network byte and checksum.\n    ///      This value is used for Bitcoin message signatures validation from\n    ///      the Bitcoin account associated with this contract.\n    bytes20 public truncatedBitcoinAddress;\n\n    /// @notice Indicates if the setup function was already called for the contract.\n    // slither-disable-next-line immutable-states\n    bool public initialized;\n\n    /// @notice Reference to the emergency governance contract holding the\n    ///         emergency upgrader address that can execute upgrades of the\n    ///         singleton address if the emergency upgrades were not disabled.\n    EmergencyGovernance public emergencyGovernance;\n\n    /// @notice Magic value for an invalid signature, indicating a failed validation.\n    bytes4 internal constant INVALID_SIGNATURE_VALUE = 0xffffffff;\n\n    /// @notice Typehash of a message signed off-chain to upgrade the singleton.\n    bytes32 public constant UPGRADE_SINGLETON_TYPEHASH =\n        keccak256(\"UpgradeSingleton(address newSingleton,bytes initData)\");\n\n    event SingletonUpgraded(address oldSingleton, address newSingleton);\n\n    /// Reverts when the contract was already initialized and another\n    /// initialization attempt is made.\n    error ContractAlreadyInitialized();\n\n    /// Reverts when truncated Bitcoin address is incorrect.\n    error InvalidTruncatedBitcoinAddress();\n\n    /// Reverts when emergency governance contract address is zero.\n    error EmergencyGovernanceAddressZero();\n\n    /// Reverts when provided signature is not 65-bytes long.\n    error InvalidSignatureLength(uint256 actualLength);\n\n    /// Reverts when the singleton was already upgraded to the given new version.\n    error SingletonAlreadyUpgraded();\n\n    /// Reverts when the new singleton address is incorrect.\n    error InvalidNewSingletonAddress();\n\n    /// Reverts when the upgrade order signature was incorrect.\n    error InvalidUpgradeSignature();\n\n    /// Reverts if the new version init data provided in the upgrade order\n    /// are empty.\n    error InvalidUpgradeInitData();\n\n    /// Reverts when the address calling the function is not the authorized\n    /// emergency governance upgrader.\n    error InvalidEmergencyGovernanceCaller();\n\n    constructor() {\n        // Prevent singleton contract initialization.\n        initialized = true;\n    }\n\n    /// @notice Initializes the BitcoinSafeOwner contract with the Ethereum\n    ///         address derived from a Bitcoin public key and the address\n    ///         of the contract holding the emergency governance settings.\n    function setup(\n        bytes20 _truncatedBitcoinAddress,\n        address _emergencyGovernance\n    ) external {\n        if (initialized) {\n            revert ContractAlreadyInitialized();\n        }\n\n        if (_truncatedBitcoinAddress == bytes20(0)) {\n            revert InvalidTruncatedBitcoinAddress();\n        }\n\n        if (_emergencyGovernance == address(0)) {\n            revert EmergencyGovernanceAddressZero();\n        }\n\n        initialized = true;\n        emergencyGovernance = EmergencyGovernance(_emergencyGovernance);\n        truncatedBitcoinAddress = _truncatedBitcoinAddress;\n\n        // IMPORTANT: The contract version is a part of the DOMAIN_SEPARATOR.\n        // The new singleton implementation MUST increase the version number\n        // to protect against replaying signatures.\n        version = \"v1.0.0\";\n    }\n\n    /// @notice Returns the hash of EIP712 domain separator struct. Used to\n    ///         verify off-chain signatures to this contract, such as the\n    ///         signature for upgrading the singleton.\n    function DOMAIN_SEPARATOR() public view returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    keccak256(\n                        \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n                    ),\n                    keccak256(bytes(\"BitcoinSafeOwner\")),\n                    keccak256(bytes(version)),\n                    block.chainid,\n                    address(this)\n                )\n            );\n    }\n\n    /// @notice Upgrades the singleton address based on the signature of the\n    ///         upgrade order prepared off-chain.\n    /// @dev IMPORTANT: The contract version is a part of the DOMAIN_SEPARATOR.\n    ///      The new singleton implementation MUST increase the version number\n    ///      to protect against replaying signatures.\n    /// @param newSingleton The new singleton contract address.\n    /// @param initData Encoded call to the setup function that will be called\n    ///        on the proxy after switching the singleton.\n    /// @param signature The signature from the Bitcoin signer attesting the\n    ///        upgrade order.\n    function upgradeSingleton(\n        address newSingleton,\n        bytes memory initData,\n        bytes memory signature\n    ) external {\n        if (newSingleton == address(0) || newSingleton == address(this)) {\n            revert InvalidNewSingletonAddress();\n        }\n        if (singleton == newSingleton) {\n            revert SingletonAlreadyUpgraded();\n        }\n\n        bytes32 digest = keccak256(\n            abi.encodePacked(\n                \"\\x19\\x01\",\n                DOMAIN_SEPARATOR(),\n                keccak256(\n                    abi.encode(\n                        UPGRADE_SINGLETON_TYPEHASH,\n                        newSingleton,\n                        initData\n                    )\n                )\n            )\n        );\n\n        if (!validateSignature(digest, signature)) {\n            revert InvalidUpgradeSignature();\n        }\n\n        emit SingletonUpgraded(singleton, newSingleton);\n\n        singleton = newSingleton;\n\n        if (initData.length == 0) {\n            revert InvalidUpgradeInitData();\n        }\n        // The init function should return no data.\n        // slither-disable-next-line unused-return\n        Address.functionCall(address(this), initData);\n    }\n\n    /// @notice Upgrades the singleton address in an emergency mode.\n    /// @dev Only callable by the governance upgrader set in the\n    ///      EmergencyGovernance contract.\n    /// @param newSingleton The new singleton contract address.\n    /// @param initData Encoded call to the setup function that will be called\n    ///        on the proxy after switching the singleton.\n    function emergencyUpgradeSingleton(\n        address newSingleton,\n        bytes memory initData\n    ) external {\n        if (newSingleton == address(0) || newSingleton == address(this)) {\n            revert InvalidNewSingletonAddress();\n        }\n        if (singleton == newSingleton) {\n            revert SingletonAlreadyUpgraded();\n        }\n\n        if (msg.sender != emergencyGovernance.emergencyUpgrader()) {\n            revert InvalidEmergencyGovernanceCaller();\n        }\n\n        emit SingletonUpgraded(singleton, newSingleton);\n\n        singleton = newSingleton;\n\n        if (initData.length == 0) {\n            revert InvalidUpgradeInitData();\n        }\n        // The init function should return no data.\n        // slither-disable-next-line unused-return\n        Address.functionCall(address(this), initData);\n    }\n\n    /// @notice Validates a signature against a hash digest, adhering to the latest\n    ///         ERC-1271 standard.\n    /// @param digest The hash of the data that was signed.\n    /// @param signature The signature bytes to be validated.\n    /// @return magicValue A magic value indicating the result of the validation.\n    /// @dev This method is intended to comply with the most recent version of\n    ///      Safe contracts.\n    function isValidSignature(\n        bytes32 digest,\n        bytes memory signature\n    ) external view returns (bytes4 magicValue) {\n        return\n            validateSignature(digest, signature)\n                ? ERC1271_MAGIC_VALUE\n                : INVALID_SIGNATURE_VALUE;\n    }\n\n    /// @notice Validates a signature against data bytes, following the legacy\n    ///         Safe contract expectations.\n    /// @param data Arbitrary length data that was signed.\n    /// @param signature The signature bytes to be validated.\n    /// @return magicValue A magic value indicating the result of the validation.\n    /// @dev This method is compatible with Safe contracts up to version 1.4.1.\n    function isValidSignature(\n        bytes memory data,\n        bytes memory signature\n    ) public view override returns (bytes4 magicValue) {\n        bytes32 digest = keccak256(data);\n\n        return\n            validateSignature(digest, signature)\n                ? LEGACY_SAFE_ERC1271_MAGIC_VALUE\n                : INVALID_SIGNATURE_VALUE;\n    }\n\n    /// @notice Internal function to validate a signature against a digest.\n    /// @dev By adjusting the recovery byte (`v`) it supports various types of\n    ///      Bitcoin truncated addresses that this contract could be initialized\n    ///      with, including uncompressed P2PKH, compressed P2PKH, compressed\n    ///      P2WPKH, and compressed P2SH-P2WPKH.\n    ///      The function returns `true` if the signature is successfully verified\n    ///      against the `digest` and the `truncatedBitcoinAddress` stored in the\n    ///      contract.\n    /// @param digest The hash of the data that was signed.\n    /// @param signature The signature bytes to be validated, which must be 129\n    ///        bytes long and include the `v`, `r`, `s` values of the\n    ///        ECDSA signature, and the `x`, `y` coordinates of the public key\n    ///        used for signing. The `v` value should be adjusted to indicate\n    ///        which signature validation function should be executed for the given\n    ///        truncated Bitcoin address type.\n    /// @return A boolean indicating whether the signature is valid.\n    function validateSignature(\n        bytes32 digest,\n        bytes memory signature\n    ) internal view returns (bool) {\n        if (truncatedBitcoinAddress == bytes20(0))\n            revert InvalidTruncatedBitcoinAddress();\n\n        if (signature.length != 129)\n            revert InvalidSignatureLength(signature.length);\n\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n        bytes32 x;\n        bytes32 y;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // first 32 bytes, after the length prefix.\n            r := mload(add(signature, 32))\n            // second 32 bytes.\n            s := mload(add(signature, 64))\n            // 65th byte (first byte of the next 32 bytes).\n            v := byte(0, mload(add(signature, 96)))\n            // next 32 bytes starting from 65\n            x := mload(add(signature, 97))\n            // last 32 bytes\n            y := mload(add(signature, 129))\n        }\n\n        bytes32 signedMessage = sha256(\n            abi.encodePacked(\n                sha256(\n                    abi.encodePacked(\n                        \"\\x18Bitcoin Signed Message:\\n\",\n                        uint8(32),\n                        digest\n                    )\n                )\n            )\n        );\n\n        // The v value must be 27 or 28 for ECRECOVER to accept the signatures.\n        // In the case of uncompressed P2PKH addresses this is achieved as long\n        // as the signature's r value is less than the curve order n.\n        // When the v value is used to encode a different signature type,\n        // we need to subtract the difference to get 27 or 28.\n        // Signatures with r greater than n, corresponding to the v values\n        // 29, 30, 33, 34, 37, 38, 41 or 42 cannot be accepted by ECRECOVER.\n        // Signature's V value is used to determine signature verification path\n        // according to BIP-137.\n        if (v == 27 || v == 28) {\n            // v is either 27 or 28, so pass it straight to ECRECOVER\n            return validateUncompressedP2PKH(signedMessage, v, r, s, x, y);\n        } else if (v == 31 || v == 32) {\n            // v is either 31 or 32, so subtract 4 to get 27 or 28\n            return validateCompressedP2PKH(signedMessage, v - 4, r, s, x, y);\n        } else if (v == 35 || v == 36) {\n            // v is either 35 or 36, so subtract 8 to get 27 or 28\n            return validateP2SH_P2WPKH(signedMessage, v - 8, r, s, x, y);\n        } else if (v == 39 || v == 40) {\n            // v is either 39 or 40, so subtract 12 to get 27 or 28\n            return validateP2WPKH(signedMessage, v - 12, r, s, x, y);\n        } else {\n            return false;\n        }\n    }\n\n    /// @notice Validates a signature for truncated Bitcoin address derived from\n    ///         a P2PKH address of an uncompressed public key.\n    /// @param signedMessage The SHA-256 hash of the message that was signed,\n    ///        prefixed according to the Bitcoin signed message standard.\n    /// @param v The recovery byte.\n    /// @param r The first component of the ECDSA signature.\n    /// @param s The second component of the ECDSA signature.\n    /// @param x The x-coordinate of the public key.\n    /// @param y The y-coordinate of the public key.\n    /// @return A boolean indicating whether the signature is valid.\n    function validateUncompressedP2PKH(\n        bytes32 signedMessage,\n        uint8 v,\n        bytes32 r,\n        bytes32 s,\n        bytes32 x,\n        bytes32 y\n    ) internal view returns (bool) {\n        uint8 prefix = uint8(4);\n        bytes20 publicKeyHash = hash160(abi.encodePacked(prefix, x, y));\n\n        return\n            ecrecover(signedMessage, v, r, s) ==\n            publicKeyToEthereumAddress(x, y) &&\n            truncatedBitcoinAddress == publicKeyHash;\n    }\n\n    /// @notice Validates a signature for truncated Bitcoin address derived from\n    ///         a P2PKH address of a compressed public key.\n    /// @param signedMessage The SHA-256 hash of the message that was signed,\n    ///        prefixed according to the Bitcoin signed message standard.\n    /// @param v The recovery byte.\n    /// @param r The first component of the ECDSA signature.\n    /// @param s The second component of the ECDSA signature.\n    /// @param x The x-coordinate of the public key.\n    /// @param y The y-coordinate of the public key.\n    /// @return A boolean indicating whether the signature is valid.\n    function validateCompressedP2PKH(\n        bytes32 signedMessage,\n        uint8 v,\n        bytes32 r,\n        bytes32 s,\n        bytes32 x,\n        bytes32 y\n    ) internal view returns (bool) {\n        uint8 prefix = uint8(uint256(y) & 1) + uint8(2);\n        bytes20 publicKeyHash = hash160(abi.encodePacked(prefix, x));\n\n        return\n            ecrecover(signedMessage, v, r, s) ==\n            publicKeyToEthereumAddress(x, y) &&\n            truncatedBitcoinAddress == publicKeyHash;\n    }\n\n    /// @notice Validates a signature for truncated Bitcoin address derived from\n    ///         a P2SH-P2WPKH address of a compressed public key.\n    /// @param signedMessage The SHA-256 hash of the message that was signed,\n    ///        prefixed according to the Bitcoin signed message standard.\n    /// @param v The recovery byte.\n    /// @param r The first component of the ECDSA signature.\n    /// @param s The second component of the ECDSA signature.\n    /// @param x The x-coordinate of the public key.\n    /// @param y The y-coordinate of the public key.\n    /// @return A boolean indicating whether the signature is valid.\n    function validateP2SH_P2WPKH(\n        bytes32 signedMessage,\n        uint8 v,\n        bytes32 r,\n        bytes32 s,\n        bytes32 x,\n        bytes32 y\n    ) internal view returns (bool) {\n        uint8 prefix = uint8(uint256(y) & 1) + uint8(2);\n        bytes20 publicKeyHash = hash160(abi.encodePacked(prefix, x));\n\n        bytes20 redeemScriptHash = hash160(\n            abi.encodePacked(bytes2(hex\"0014\"), publicKeyHash)\n        );\n\n        return\n            ecrecover(signedMessage, v, r, s) ==\n            publicKeyToEthereumAddress(x, y) &&\n            truncatedBitcoinAddress == redeemScriptHash;\n    }\n\n    /// @notice Validates a signature for truncated Bitcoin address derived from\n    ///         a PW2PKH address of a compressed public key.\n    /// @param signedMessage The SHA-256 hash of the message that was signed,\n    ///        prefixed according to the Bitcoin signed message standard.\n    /// @param v The recovery byte.\n    /// @param r The first component of the ECDSA signature.\n    /// @param s The second component of the ECDSA signature.\n    /// @param x The x-coordinate of the public key.\n    /// @param y The y-coordinate of the public key.\n    /// @return A boolean indicating whether the signature is valid.\n    function validateP2WPKH(\n        bytes32 signedMessage,\n        uint8 v,\n        bytes32 r,\n        bytes32 s,\n        bytes32 x,\n        bytes32 y\n    ) internal view returns (bool) {\n        uint8 prefix = uint8(uint256(y) & 1) + uint8(2);\n        bytes20 publicKeyHash = hash160(abi.encodePacked(prefix, x));\n\n        return\n            ecrecover(signedMessage, v, r, s) ==\n            publicKeyToEthereumAddress(x, y) &&\n            truncatedBitcoinAddress == publicKeyHash;\n    }\n\n    /// @notice Converts a public key (x, y coordinates) to an Ethereum address\n    /// @dev Computes the Ethereum address by performing a keccak256 hash on the\n    ///      concatenated x and y coordinates of the public key, then taking the\n    ///      last 20 bytes of the hash (as per Ethereum's address format).\n    /// @param x The x-coordinate of the public key.\n    /// @param y The y-coordinate of the public key.\n    /// @return The Ethereum address derived from the public key.\n    function publicKeyToEthereumAddress(\n        bytes32 x,\n        bytes32 y\n    ) internal pure returns (address) {\n        return address(uint160(uint256(keccak256(abi.encodePacked(x, y)))));\n    }\n\n    /// @notice Calculate hash160 for the given input bytes.\n    /// @dev This function combines SHA-256 and RIPEMD-160 hashing to produce a\n    ///      hash commonly used in Bitcoin addressing.\n    /// @param input The bytes array to be hashed.\n    /// @return The hash160 (RIPEMD-160 of a SHA-256 hash) of the input.\n    function hash160(bytes memory input) internal pure returns (bytes20) {\n        return ripemd160(abi.encodePacked(sha256(input)));\n    }\n}\n"
      },
      "contracts/EmergencyGovernance.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts/access/Ownable2Step.sol\";\n\n/// @title Emergency Governance\n/// @notice This contract holds the emergency upgrader address responsible for\n///         executing emergency governance actions in case of unforeseen\n///         circumstances. Only the contract owner can set or change the\n///         emergency upgrader address. This contract will STOP working after\n///         the governance decides to disable emergency upgrades.\ncontract EmergencyGovernance is Ownable2Step {\n    bool public disabled;\n    address internal _emergencyUpgrader;\n\n    event Disabled();\n\n    /// @notice Event fired when the emergency upgrader address is changed.\n    event EmergencyUpgraderChanged(\n        address oldEmergencyUpgrader,\n        address newEmergencyUpgrader\n    );\n\n    /// @notice Error thrown when an invalid emergency upgrader address is\n    ///         provided.\n    error InvalidEmergencyUpgraderAddress(address addr);\n\n    error EmergencyUpgradesDisabled();\n\n    constructor(\n        address emergencyUpgraderAddress\n    ) Ownable(emergencyUpgraderAddress) {\n        _setEmergencyUpgrader(emergencyUpgraderAddress);\n    }\n\n    modifier whenEnabled() {\n        if (disabled) {\n            revert EmergencyUpgradesDisabled();\n        }\n        _;\n    }\n\n    /// @notice Returns the emergency upgrader address.\n    function emergencyUpgrader() external view whenEnabled returns (address) {\n        return _emergencyUpgrader;\n    }\n\n    function disable() external onlyOwner whenEnabled {\n        emit Disabled();\n        disabled = true;\n    }\n\n    /// @notice Sets the emergency upgrader address.\n    /// @dev Only callable by the contract owner.\n    /// @param newEmergencyUpgrader The address of the new emergency upgrader.\n    function setEmergencyUpgrader(\n        address newEmergencyUpgrader\n    ) external onlyOwner whenEnabled {\n        _setEmergencyUpgrader(newEmergencyUpgrader);\n    }\n\n    function _setEmergencyUpgrader(address newEmergencyUpgrader) internal {\n        if (newEmergencyUpgrader == address(0)) {\n            revert InvalidEmergencyUpgraderAddress(newEmergencyUpgrader);\n        }\n\n        emit EmergencyUpgraderChanged(_emergencyUpgrader, newEmergencyUpgrader);\n        _emergencyUpgrader = newEmergencyUpgrader;\n    }\n}\n"
      },
      "contracts/ERC1271.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.25;\n\n/// @title ERC-1271 Signature Validation Standard Interface\n/// @dev Interface of the ERC-1271 standard for signature validation by contracts.\n///      This standard allows contracts to implement a function to validate signatures\n///      in a generic way, facilitating interactions with external contracts that\n///      expect a contract to sign messages or transactions.\n///      The standard is defined in EIP-1271, which can be found at https://eips.ethereum.org/EIPS/eip-1271.\ninterface IERC1271 {\n    /// @notice Validates a signature for a given data hash.\n    /// @dev This method returns a magic value if the signature is valid for the\n    ///      provided data hash and signature.\n    ///      Contracts implementing this interface can use this function to provide\n    ///      custom signature validation logic.\n    /// @param hash The hash of the data that was signed.\n    /// @param signature The signature bytes that need to be validated against the\n    ///        data hash.\n    /// @return magicValue A constant magic value (`0x1626ba7e`) if the signature\n    ///         is valid, indicating compliance with the ERC-1271 standard.\n    function isValidSignature(\n        bytes32 hash,\n        bytes memory signature\n    ) external view returns (bytes4 magicValue);\n}\n\n/// @title ERC-1271 Signature Validation Standard Abstract Contract\n/// @dev Provides a basic implementation of the ERC-1271 standard, including the\n///      magic value constant.\n///      This abstract contract can be extended to create custom implementations\n///      of the ERC-1271 standard, defining the specific logic required to validate\n///      signatures in the context of the extending contract.\nabstract contract ERC1271 is IERC1271 {\n    /// @notice The magic value to be returned by `isValidSignature` when the\n    ///         signature is valid.\n    /// @dev This constant represents `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\")`.\n    ///      It is used to indicate that a signature is valid according to the\n    ///      ERC-1271 standard.\n    bytes4 internal constant ERC1271_MAGIC_VALUE = 0x1626ba7e;\n}\n"
      },
      "contracts/LegacyERC1271.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.25;\n\n// This file contains Legacy ERC-1271 signatures validator that assumes `isValidSignature`\n// function to require data bytes, which is incompatible with the standard which\n// expects bytes32 hash digest.\n// This validator is used by Safe contract up to version v1.4.1.\n//\n// The abstract contract was build with the ISignatureValidator taken from\n// Safe's v1.4.1-build.0:\n// https://github.com/safe-global/safe-smart-account/blob/192c7dc67290940fcbc75165522bb86a37187069/contracts/interfaces/ISignatureValidator.sol\n\n/// @title LegacyERC1271\n/// @notice Abstract contract for legacy Safe signature validation.\n/// @dev This contract implements Safe's v1.4.1 `ISignatureValidator` without\n///      adding additional functionality, serving as a base for specific legacy\n///      Safe-compatible signature validation implementations.\nabstract contract LegacyERC1271 {\n    // bytes4(keccak256(\"isValidSignature(bytes,bytes)\")\n    bytes4 internal constant LEGACY_SAFE_ERC1271_MAGIC_VALUE = 0x20c13b0b;\n\n    /**\n     * @notice Legacy EIP1271 method to validate a signature.\n     * @param _data Arbitrary length data signed on the behalf of address(this).\n     * @param _signature Signature byte array associated with _data.\n     *\n     * MUST return the bytes4 magic value 0x20c13b0b when function passes.\n     * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)\n     * MUST allow external calls\n     */\n    function isValidSignature(\n        bytes memory _data,\n        bytes memory _signature\n    ) public view virtual returns (bytes4);\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}