{"language": "Solidity", "sources": {"contracts/GMContractCustody.sol": {"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\ninterface IERC20BalanceTransfer {\n    function balanceOf(address account) external view returns (uint256);\n    function transfer(address to, uint256 amount) external returns (bool);\n}\n\ninterface IPonsV2FeeEscrowClaim {\n    function balanceOfToken(address recipient, address token) external view returns (uint256);\n    function claimToken(address token) external returns (uint256 amount);\n}\n\n/** Immutable boundary that validates a drand signature and returns its canonical randomness. */\ninterface IGMDrawVerifier {\n    function currentRound() external view returns (uint64);\n    function verifyBeacon(uint64 futureRandomnessRound, bytes calldata signature)\n        external view returns (bytes32 randomness);\n}\n\n/**\n * Minimal GM fee custody checkpoint. Pons pays this contract directly, so no\n * fee-recipient key or intermediate payout wallet exists. Claim and settlement\n * are permissionless, but only the immutable Pi executor may commit a draw.\n * No caller can choose a payee: the winner is derived from verifier-returned\n * drand randomness and a committed holder range tree. No caller can change a\n * destination, move an arbitrary amount, or invoke an arbitrary target.\n *\n * The committer can bias snapshot contents, although it commits before the\n * future drand result is knowable. Production therefore requires independently\n * authenticated snapshot provenance, an attestation, or a zero-knowledge proof;\n * snapshot holdings are not trustless merely because their hash and root are\n * committed onchain.\n *\n * A committed draw can never be recovered into another draw. If settlement is\n * blocked operationally, the recovery Safe pauses, repairs the verifier or\n * surrounding operation, unpauses, and retries the same immutable draw.\n *\n * This source is not deployed and has not been audited. Constructor bindings,\n * the range-tree builder, snapshot provenance, and the verifier remain\n * deployment review gates.\n */\ncontract GMContractCustody {\n    /**\n     * Minimum escrow credit, in USDG base units (6 decimals), that\n     * `claimIfThreshold()` requires. Set once at deployment and immutable\n     * thereafter, so a given deployment's threshold can never be changed by\n     * any caller, key, or upgrade.\n     *\n     * Production uses 7_500_000 (7.50 USDG). A controlled test deployment may\n     * use a smaller floor so that a short draw interval can complete real\n     * claim -> commit -> settle cycles without waiting for production-sized\n     * fee accrual. The value is a deployment review gate: it appears in the\n     * constructor arguments and is readable on-chain.\n     *\n     * Must be greater than zero. A zero floor would let `claimIfThreshold()`\n     * be called against an empty escrow, which then reverts `NoClaimReceived`\n     * after paying gas.\n     */\n    uint256 public immutable MINIMUM_CLAIMABLE_USDG;\n\n    IPonsV2FeeEscrowClaim public immutable PONS_ESCROW;\n    address public immutable GM_TOKEN;\n    IERC20BalanceTransfer public immutable USDG;\n    address public immutable RESERVE_SAFE;\n    address public immutable RECOVERY_SAFE;\n    address public immutable COMMITTER;\n    IGMDrawVerifier public immutable DRAW_VERIFIER;\n\n    enum DrawStatus { NONE, COMMITTED, SETTLED }\n\n    struct Draw {\n        bytes32 snapshotHash;\n        bytes32 rangeRoot;\n        uint256 totalTickets;\n        uint64 commitmentRound;\n        uint64 futureRandomnessRound;\n        uint256 amount;\n        DrawStatus status;\n    }\n\n    struct RangeProof {\n        address holder;\n        uint256 startInclusive;\n        uint256 endExclusive;\n        uint256 leafIndex;\n        bytes32[] siblings;\n    }\n\n    mapping(bytes32 drawId => Draw draw) public draws;\n    uint256 public availableBalance;\n    /**\n     * Sum of every COMMITTED, unsettled draw's locked amount. Tracked so that\n     * `sweepDonations()` can distinguish USDG that belongs to a live draw from\n     * USDG that arrived by direct transfer. Increased in `commitDraw`, reduced\n     * in `settleDraw` by the same amount that is paid out.\n     */\n    uint256 public committedBalance;\n    bool public paused;\n    uint256 private _entered;\n\n    error ZeroAddress();\n    error ZeroThreshold();\n    error Paused();\n    error NotRecoverySafe();\n    error NotCommitter();\n    error ReentrantCall();\n    error BelowClaimThreshold(uint256 claimable);\n    error NoClaimReceived();\n    error DuplicateDraw();\n    error InvalidCommitment();\n    error NoAvailableBalance();\n    error NothingToSweep();\n    error RandomnessNotFuture();\n    error DrawNotCommitted();\n    error InvalidDrawProof();\n    error TransferFailed();\n    error InexactTransfer();\n\n    event FeesClaimed(address indexed executor, uint256 measuredAmount);\n    event DonationsSwept(address indexed executor, uint256 sweptAmount);\n    event DrawCommitted(\n        bytes32 indexed drawId,\n        bytes32 indexed snapshotHash,\n        bytes32 indexed rangeRoot,\n        uint256 totalTickets,\n        uint64 commitmentRound,\n        uint64 futureRandomnessRound,\n        uint256 amount,\n        uint256 commitmentBlock\n    );\n    event DrawSettled(\n        bytes32 indexed drawId,\n        uint256 winningTicket,\n        address indexed winner,\n        uint256 winnerAmount,\n        address indexed reserveSafe,\n        uint256 reserveAmount\n    );\n    event PauseChanged(bool paused);\n\n    modifier nonReentrant() {\n        if (_entered != 0) revert ReentrantCall();\n        _entered = 1;\n        _;\n        _entered = 0;\n    }\n\n    modifier whenRunning() {\n        if (paused) revert Paused();\n        _;\n    }\n\n    modifier onlyRecoverySafe() {\n        if (msg.sender != RECOVERY_SAFE) revert NotRecoverySafe();\n        _;\n    }\n\n    modifier onlyCommitter() {\n        if (msg.sender != COMMITTER) revert NotCommitter();\n        _;\n    }\n\n    constructor(\n        IPonsV2FeeEscrowClaim ponsEscrow,\n        address gmToken,\n        IERC20BalanceTransfer usdg,\n        address reserveSafe,\n        address recoverySafe,\n        address committer,\n        IGMDrawVerifier drawVerifier,\n        uint256 minimumClaimableUsdg\n    ) {\n        if (\n            address(ponsEscrow) == address(0) || gmToken == address(0) || address(usdg) == address(0)\n                || reserveSafe == address(0) || recoverySafe == address(0) || committer == address(0)\n                || address(drawVerifier) == address(0)\n        ) revert ZeroAddress();\n        if (minimumClaimableUsdg == 0) revert ZeroThreshold();\n        PONS_ESCROW = ponsEscrow;\n        GM_TOKEN = gmToken;\n        USDG = usdg;\n        RESERVE_SAFE = reserveSafe;\n        RECOVERY_SAFE = recoverySafe;\n        COMMITTER = committer;\n        DRAW_VERIFIER = drawVerifier;\n        MINIMUM_CLAIMABLE_USDG = minimumClaimableUsdg;\n    }\n\n    /** Permissionless and inclusive at exactly MINIMUM_CLAIMABLE_USDG. */\n    function claimIfThreshold() external nonReentrant whenRunning returns (uint256 claimedAmount) {\n        uint256 claimable = PONS_ESCROW.balanceOfToken(address(this), address(USDG));\n        if (claimable < MINIMUM_CLAIMABLE_USDG) revert BelowClaimThreshold(claimable);\n\n        uint256 balanceBefore = USDG.balanceOf(address(this));\n        PONS_ESCROW.claimToken(address(USDG));\n        uint256 balanceAfter = USDG.balanceOf(address(this));\n        if (balanceAfter <= balanceBefore) revert NoClaimReceived();\n        claimedAmount = balanceAfter - balanceBefore;\n        availableBalance += claimedAmount;\n        emit FeesClaimed(msg.sender, claimedAmount);\n    }\n\n    /**\n     * Rolls directly-transferred USDG into the next draw's pot.\n     *\n     * The contract cannot observe an incoming ERC-20 transfer, so USDG sent\n     * straight to this address is invisible to `availableBalance` and would\n     * otherwise be stranded permanently. This function measures the gap\n     * between the real token balance and the two tracked buckets, and credits\n     * the difference to `availableBalance`.\n     *\n     * Permissionless, like `claimIfThreshold`. Swept funds always land in the\n     * NEXT draw, never a pending one, so every published receipt still matches\n     * the amount fixed at commit time.\n     *\n     * SAFETY \u2014 the `nonReentrant` guard on this function and on `settleDraw`\n     * is LOAD-BEARING. Do not remove it, and do not add an unguarded variant\n     * of this function.\n     *\n     * Subtracting `committedBalance` is NOT by itself sufficient. Inside\n     * `settleDraw` there is a transient window between the winner transfer and\n     * the reserve transfer where `committedBalance` has already been reduced by\n     * the full draw amount while the reserve's share is still held by this\n     * contract. In that window `held - accounted == reserveAmount > 0`, so a\n     * reentrant call here would credit `availableBalance` with tokens that are\n     * about to leave. `availableBalance` would then permanently exceed the real\n     * balance, a later `commitDraw` would lock more than exists, `settleDraw`\n     * would revert on transfer, and with no owner key every remaining fund\n     * would be stranded forever.\n     *\n     * That window is unreachable only because `nonReentrant` serialises these\n     * functions and USDG performs no recipient callback. USDG is an upgradeable\n     * proxy, so its no-callback behaviour is not guaranteed for all time; the\n     * guard is the durable protection.\n     */\n    function sweepDonations() external nonReentrant whenRunning returns (uint256 sweptAmount) {\n        uint256 held = USDG.balanceOf(address(this));\n        uint256 accounted = availableBalance + committedBalance;\n        if (held <= accounted) revert NothingToSweep();\n        sweptAmount = held - accounted;\n        availableBalance += sweptAmount;\n        emit DonationsSwept(msg.sender, sweptAmount);\n    }\n\n    /** Locks all currently available claimed USDG to one immutable draw. */\n    function commitDraw(\n        bytes32 drawId,\n        bytes32 snapshotHash,\n        bytes32 rangeRoot,\n        uint256 totalTickets,\n        uint64 futureRandomnessRound\n    ) external onlyCommitter nonReentrant whenRunning returns (uint256 amount) {\n        if (drawId == bytes32(0) || snapshotHash == bytes32(0) || rangeRoot == bytes32(0) || totalTickets == 0) {\n            revert InvalidCommitment();\n        }\n        if (draws[drawId].status != DrawStatus.NONE) revert DuplicateDraw();\n\n        uint64 commitmentRound = DRAW_VERIFIER.currentRound();\n        if (futureRandomnessRound <= commitmentRound) revert RandomnessNotFuture();\n\n        amount = availableBalance;\n        if (amount == 0) revert NoAvailableBalance();\n        availableBalance = 0;\n        committedBalance += amount;\n        draws[drawId] = Draw({\n            snapshotHash: snapshotHash,\n            rangeRoot: rangeRoot,\n            totalTickets: totalTickets,\n            commitmentRound: commitmentRound,\n            futureRandomnessRound: futureRandomnessRound,\n            amount: amount,\n            status: DrawStatus.COMMITTED\n        });\n        emit DrawCommitted(\n            drawId,\n            snapshotHash,\n            rangeRoot,\n            totalTickets,\n            commitmentRound,\n            futureRandomnessRound,\n            amount,\n            block.number\n        );\n    }\n\n    /**\n     * Verifies the committed beacon, derives the winning ticket onchain, and\n     * derives its owner from a Merkle range proof. There is no randomness or\n     * winner argument: canonical randomness comes only from DRAW_VERIFIER.\n     */\n    function settleDraw(\n        bytes32 drawId,\n        bytes calldata drandSignature,\n        RangeProof calldata rangeProof\n    ) external nonReentrant whenRunning returns (uint256 winnerAmount, uint256 reserveAmount) {\n        Draw storage draw = draws[drawId];\n        if (draw.status != DrawStatus.COMMITTED) revert DrawNotCommitted();\n\n        bytes32 randomness = DRAW_VERIFIER.verifyBeacon(draw.futureRandomnessRound, drandSignature);\n        uint256 winningTicket = uint256(randomness) % draw.totalTickets;\n        address winner = _verifyRangeProof(draw.rangeRoot, draw.totalTickets, winningTicket, rangeProof);\n\n        uint256 amount = draw.amount;\n        reserveAmount = (amount * 10) / 100;\n        winnerAmount = amount - reserveAmount;\n        draw.status = DrawStatus.SETTLED;\n        // winnerAmount + reserveAmount == amount exactly (winnerAmount is derived\n        // by subtraction, not a second division), so this releases the full\n        // locked sum. Done before any transfer (checks-effects-interactions).\n        //\n        // NOTE: this decrement opens a transient window across the two transfers\n        // below in which `availableBalance + committedBalance` under-counts the\n        // tokens still held. `sweepDonations()` would misread that gap as a\n        // donation. The `nonReentrant` guard on both functions is what makes the\n        // window unreachable \u2014 see the SAFETY note on `sweepDonations`.\n        committedBalance -= amount;\n\n        _safeTransferExact(winner, winnerAmount);\n        _safeTransferExact(RESERVE_SAFE, reserveAmount);\n        emit DrawSettled(drawId, winningTicket, winner, winnerAmount, RESERVE_SAFE, reserveAmount);\n    }\n\n    function pause() external onlyRecoverySafe {\n        paused = true;\n        emit PauseChanged(true);\n    }\n\n    function unpause() external onlyRecoverySafe {\n        paused = false;\n        emit PauseChanged(false);\n    }\n\n    function _verifyRangeProof(\n        bytes32 rangeRoot,\n        uint256 totalTickets,\n        uint256 winningTicket,\n        RangeProof calldata proof\n    ) private pure returns (address holder) {\n        holder = proof.holder;\n        if (\n            holder == address(0) || proof.startInclusive >= proof.endExclusive\n                || proof.endExclusive > totalTickets || winningTicket < proof.startInclusive\n                || winningTicket >= proof.endExclusive || proof.siblings.length > 64\n        ) revert InvalidDrawProof();\n\n        bytes32 node = keccak256(abi.encode(\n            \"GM_HOLDER_RANGE_V1\", holder, proof.startInclusive, proof.endExclusive, totalTickets\n        ));\n        uint256 index = proof.leafIndex;\n        for (uint256 offset = 0; offset < proof.siblings.length; ++offset) {\n            bytes32 sibling = proof.siblings[offset];\n            node = (index & 1) == 0\n                ? keccak256(abi.encodePacked(node, sibling))\n                : keccak256(abi.encodePacked(sibling, node));\n            index >>= 1;\n        }\n        if (index != 0 || node != rangeRoot) revert InvalidDrawProof();\n    }\n\n    function _safeTransferExact(address recipient, uint256 amount) private {\n        uint256 senderBefore = USDG.balanceOf(address(this));\n        uint256 recipientBefore = USDG.balanceOf(recipient);\n        bool ok = USDG.transfer(recipient, amount);\n        if (!ok) revert TransferFailed();\n        uint256 senderAfter = USDG.balanceOf(address(this));\n        uint256 recipientAfter = USDG.balanceOf(recipient);\n        if (senderBefore - senderAfter != amount || recipientAfter - recipientBefore != amount) revert InexactTransfer();\n    }\n}\n"}, "contracts/GMContractCustodyV5.sol": {"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {GMContractCustody, IPonsV2FeeEscrowClaim, IERC20BalanceTransfer, IGMDrawVerifier}\n    from \"./GMContractCustody.sol\";\n\ninterface IPonsV2BondingCurveV5 {\n    function token() external view returns (address);\n    function pairToken() external view returns (address);\n    function buybackEnabled() external view returns (bool);\n    function sweepFees(uint256 minBuybackTokensOut) external;\n}\n\ninterface IPonsV2LaunchFactoryV5 {\n    enum GraduationPhase { NotGraduated, Swept, PoolCreated, Rescued }\n\n    struct LaunchedToken {\n        address token;\n        address curve;\n        address deployer;\n        address creatorFeeRecipient;\n        address pairToken;\n        uint256 graduationThreshold;\n        uint24 poolFee;\n        int24 tickSpacing;\n        uint16 creatorTaxBps;\n        bool buybackEnabled;\n        GraduationPhase phase;\n        uint256 sweptQuote;\n        uint256 sweptTokens;\n        uint256 sweptAt;\n        bool exists;\n    }\n\n    function feeEscrow() external view returns (address);\n    function getLaunchedToken(address token) external view returns (LaunchedToken memory);\n    function transferCreatorFeeRecipient(address token, address newRecipient) external;\n}\n\n/**\n * Custody v5 adds two narrow Pons integrations to the unchanged v4 lifecycle:\n * a permissionless, destination-free curve-fee sweep and a recovery-Safe-only\n * creator-recipient handoff. Neither path is coupled to claim, commit, or settle.\n */\ncontract GMContractCustodyV5 is GMContractCustody {\n    IPonsV2BondingCurveV5 public immutable PONS_CURVE;\n    IPonsV2LaunchFactoryV5 public immutable PONS_FACTORY;\n\n    error ContractCodeRequired(address target);\n    error CurveTokenMismatch(address actual);\n    error CurvePairTokenMismatch(address actual);\n    error FactoryEscrowMismatch(address actual);\n    error LaunchBindingMismatch();\n    error CustodyNotCreatorFeeRecipient(address actual);\n    error BuybackEnabled();\n    error BuybackStateMismatch();\n    error InvalidRecoveryRecipient();\n    error RecoveryRecipientMismatch(address actual);\n\n    event CurveFeesSwept(address indexed executor, address indexed curve);\n    event CreatorFeeRecipientTransferred(address indexed recoverySafe, address indexed newRecipient);\n\n    constructor(\n        IPonsV2FeeEscrowClaim ponsEscrow,\n        address gmToken,\n        IERC20BalanceTransfer usdg,\n        address reserveSafe,\n        address recoverySafe,\n        address committer,\n        IGMDrawVerifier drawVerifier,\n        uint256 minimumClaimableUsdg,\n        IPonsV2BondingCurveV5 ponsCurve,\n        IPonsV2LaunchFactoryV5 ponsFactory\n    ) GMContractCustody(\n        ponsEscrow,\n        gmToken,\n        usdg,\n        reserveSafe,\n        recoverySafe,\n        committer,\n        drawVerifier,\n        minimumClaimableUsdg\n    ) {\n        if (address(ponsCurve) == address(0) || address(ponsFactory) == address(0)) revert ZeroAddress();\n        if (address(ponsCurve).code.length == 0) revert ContractCodeRequired(address(ponsCurve));\n        if (address(ponsFactory).code.length == 0) revert ContractCodeRequired(address(ponsFactory));\n\n        address curveToken = ponsCurve.token();\n        if (curveToken != gmToken) revert CurveTokenMismatch(curveToken);\n        address curvePairToken = ponsCurve.pairToken();\n        if (curvePairToken != address(usdg)) revert CurvePairTokenMismatch(curvePairToken);\n        address factoryEscrow = ponsFactory.feeEscrow();\n        if (factoryEscrow != address(ponsEscrow)) revert FactoryEscrowMismatch(factoryEscrow);\n\n        IPonsV2LaunchFactoryV5.LaunchedToken memory launch = ponsFactory.getLaunchedToken(gmToken);\n        if (!launch.exists || launch.token != gmToken || launch.curve != address(ponsCurve)\n            || launch.pairToken != address(usdg)) revert LaunchBindingMismatch();\n\n        PONS_CURVE = ponsCurve;\n        PONS_FACTORY = ponsFactory;\n    }\n\n    /**\n     * Permissionless liveness trigger with no caller-selected target, amount, or\n     * destination. A zero buyback bound is safe only while the factory's\n     * authoritative launch record says buyback is disabled, so this fails closed\n     * if that policy changes. Reverts leave custody draw accounting untouched.\n     */\n    function sweepCurveFees() external nonReentrant whenRunning {\n        IPonsV2LaunchFactoryV5.LaunchedToken memory launch = PONS_FACTORY.getLaunchedToken(GM_TOKEN);\n        if (!launch.exists || launch.curve != address(PONS_CURVE)) revert LaunchBindingMismatch();\n        if (launch.creatorFeeRecipient != address(this)) {\n            revert CustodyNotCreatorFeeRecipient(launch.creatorFeeRecipient);\n        }\n        bool curveBuybackEnabled = PONS_CURVE.buybackEnabled();\n        if (launch.buybackEnabled != curveBuybackEnabled) revert BuybackStateMismatch();\n        if (launch.buybackEnabled) revert BuybackEnabled();\n        PONS_CURVE.sweepFees(0);\n        emit CurveFeesSwept(msg.sender, address(PONS_CURVE));\n    }\n\n    /** Irreversible, separately invoked recovery action; not a generic proxy. */\n    function transferCreatorFeeRecipient(address newRecipient) external onlyRecoverySafe nonReentrant {\n        if (newRecipient == address(0) || newRecipient == address(this)) revert InvalidRecoveryRecipient();\n        PONS_FACTORY.transferCreatorFeeRecipient(GM_TOKEN, newRecipient);\n        address actualRecipient = PONS_FACTORY.getLaunchedToken(GM_TOKEN).creatorFeeRecipient;\n        if (actualRecipient != newRecipient) revert RecoveryRecipientMismatch(actualRecipient);\n        emit CreatorFeeRecipientTransferred(msg.sender, newRecipient);\n    }\n}\n"}, "contracts/GMDrandQuicknetVerifier.sol": {"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {BLS2} from \"./vendor/bls-solidity/BLS2.sol\";\n\n/**\n * Stateless verifier for drand quicknet (`bls-unchained-g1-rfc9380`).\n *\n * It accepts only the canonical 48-byte compressed signature returned by the\n * drand HTTP API. The returned randomness is drand's canonical\n * `sha256(signature)` value, so the contract and public verifier derive exactly\n * the same draw input.\n *\n * The vendored BLS primitives are experimental and unaudited. This contract is\n * suitable for the controlled live rehearsal only until independently audited.\n */\ncontract GMDrandQuicknetVerifier {\n    string public constant DST = \"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_\";\n    bytes32 public constant CHAIN_HASH =\n        0x52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971;\n    uint64 public constant PERIOD_SECONDS = 3;\n    uint64 public constant GENESIS_TIMESTAMP = 1_692_803_367;\n    uint256 public constant COMPRESSED_SIGNATURE_LENGTH = 48;\n\n    error BeforeGenesis();\n    error InvalidSignatureLength();\n    error InvalidBeacon();\n\n    function currentRound() public view returns (uint64) {\n        if (block.timestamp < GENESIS_TIMESTAMP) revert BeforeGenesis();\n        return uint64((block.timestamp - GENESIS_TIMESTAMP) / PERIOD_SECONDS) + 1;\n    }\n\n    function verifyBeacon(uint64 round, bytes calldata signature) external view returns (bytes32 randomness) {\n        if (signature.length != COMPRESSED_SIGNATURE_LENGTH) revert InvalidSignatureLength();\n\n        BLS2.PointG1 memory signaturePoint = BLS2.g1UnmarshalCompressed(signature);\n        BLS2.PointG1 memory messagePoint =\n            BLS2.hashToPoint(bytes(DST), abi.encodePacked(sha256(abi.encodePacked(round))));\n        (bool pairingSuccess, bool callSuccess) = BLS2.verifySingle(signaturePoint, _publicKey(), messagePoint);\n        if (!pairingSuccess || !callSuccess) revert InvalidBeacon();\n\n        return sha256(signature);\n    }\n\n    function _publicKey() private pure returns (BLS2.PointG2 memory) {\n        // Uncompressed quicknet public key from Randamu's MIT QuicknetRegistry,\n        // corresponding to the official drand quicknet chain hash above.\n        return BLS2.PointG2(\n            0x03cf0f2896adee7eb8b5f01fcad39122,\n            0x12c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d106451,\n            0x0d1fec758c921cc22b0e17e63aaf4bcb,\n            0x5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a,\n            0x01a714f2edb74119a2f2b0d5a7c75ba9,\n            0x02d163700a61bc224ededd8e63aef7be1aaf8e93d7a9718b047ccddb3eb5d68b,\n            0x0e5db2b6bfbb01c867749cadffca88b3,\n            0x6c24f3012ba09fc4d3022c5c37dce0f977d3adb5d183c7477c442b1f04515273\n        );\n    }\n}\n"}, "contracts/vendor/bls-solidity/BLS2.sol": {"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8;\n\nimport \"./Precompiles.sol\";\n\n/// @title  Boneh\u2013Lynn\u2013Shacham (BLS) signature scheme on Barreto-Lynn-Scott 381-bit curve (BLS12-381) used to verify BLS signatures\n/// @notice We use BLS signature aggregation to reduce the size of signature data to store on chain.\n/// @dev We use G1 points for signatures and messages, and G2 points for public keys or vice versa\n/// @dev base field elements are 48-bytes, and are represented as an uint128 followed by and uint256.\n/// @dev G1 is 96 bytes and G2 is 192 bytes. Compression is not currently available.\nlibrary BLS2 {\n    struct PointG1 {\n        uint128 x_hi;\n        uint256 x_lo;\n        uint128 y_hi;\n        uint256 y_lo;\n    }\n\n    struct PointG2 {\n        uint128 x1_hi;\n        uint256 x1_lo;\n        uint128 x0_hi;\n        uint256 x0_lo;\n        uint128 y1_hi;\n        uint256 y1_lo;\n        uint128 y0_hi;\n        uint256 y0_lo;\n    }\n\n    uint128 private constant N_G2_X0_HI = 0x024aa2b2f08f0a91260805272dc51051;\n    uint256 private constant N_G2_X0_LO = 0xc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8;\n    uint128 private constant N_G2_X1_HI = 0x13e02b6052719f607dacd3a088274f65;\n    uint256 private constant N_G2_X1_LO = 0x596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e;\n    uint128 private constant N_G2_Y0_HI = 0x0d1b3cc2c7027888be51d9ef691d77bc;\n    uint256 private constant N_G2_Y0_LO = 0xb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa;\n    uint128 private constant N_G2_Y1_HI = 0x13fa4d4a0ad8b1ce186ed5061789213d;\n    uint256 private constant N_G2_Y1_LO = 0x993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed;\n\n    // Field order\n    uint128 private constant P_HI = 0x1a0111ea397fe69a4b1ba7b6434bacd7;\n    uint256 private constant P_LO = 0x64774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab;\n    uint128 private constant P_PLUS_ONE_SLASH_2_HI = 0x0680447a8e5ff9a692c6e9ed90d2eb35;\n    uint256 private constant P_PLUS_ONE_SLASH_2_LO = 0xd91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaab;\n\n    error InvalidDSTLength(bytes dst);\n\n    /// @notice Unmarshals a point on G1 from bytes in an uncompressed form.\n    function g1Unmarshal(bytes memory m) internal pure returns (PointG1 memory) {\n        require(m.length == 96, \"Invalid G1 bytes length\");\n\n        uint128 x_hi;\n        uint256 x_lo;\n        uint128 y_hi;\n        uint256 y_lo;\n\n        assembly {\n            x_hi := shr(128, mload(add(m, 0x20)))\n            x_lo := mload(add(m, 0x30))\n            y_hi := shr(128, mload(add(m, 0x50)))\n            y_lo := mload(add(m, 0x60))\n        }\n\n        return PointG1(x_hi, x_lo, y_hi, y_lo);\n    }\n\n    // @notice Unmarshal a G1 point in compressed form.\n    function g1UnmarshalCompressed(bytes memory m) internal view returns (PointG1 memory) {\n        require(m.length == 48, \"Invalid G1 bytes length\");\n\n        uint128 x_hi;\n        uint256 x_lo;\n        uint128 y_hi;\n        uint256 y_lo;\n\n        bytes memory buf = new bytes(288);\n\n        uint8 flags;\n        bool larger = false;\n\n        assembly {\n            x_hi := shr(128, mload(add(m, 0x20)))\n            x_lo := mload(add(m, 0x30))\n            flags := byte(16, x_hi)\n            x_hi := and(x_hi, 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n        }\n\n        if (flags & 0x80 == 0) {\n            revert(\"Invalid G1 point: not compressed\");\n        }\n        if (flags & 0x40 != 0) {\n            revert(\"unsupported: point at infinity\");\n        }\n        if (flags & 0x20 == 0) {\n            larger = true;\n        }\n\n        // compute x**3 mod p\n        bool ok;\n        assembly {\n            let p := add(buf, 32)\n            mstore(p, 64) // length of base\n            p := add(p, 32)\n            mstore(p, 1) // length of exponent 3\n            p := add(p, 32)\n            mstore(p, 64) // length of modulus\n            p := add(p, 32)\n            mstore(p, x_hi)\n            p := add(p, 32)\n            mstore(p, x_lo)\n            p := add(p, 32)\n            mstore8(p, 3) // exponent\n            p := add(p, 1)\n            mstore(p, P_HI)\n            p := add(p, 32)\n            mstore(p, P_LO)\n            ok := staticcall(gas(), MODEXP_ADDRESS, add(32, buf), 225, add(32, buf), 64)\n            y_hi := mload(add(buf, 32))\n            y_lo := mload(add(buf, 64))\n        }\n        assert(ok);\n        unchecked {\n            y_lo += 4;\n        }\n        if (y_lo < 4) {\n            // overflow -> carry\n            y_hi += 1;\n        }\n\n        // compute y = sqrt(x**3 + 4) mod p = (x**3 + 4)^(p+1)/2 mod p\n        assembly {\n            let p := add(buf, 32)\n            mstore(p, 64) // length of base\n            p := add(p, 32)\n            mstore(p, 64) // length of exponent\n            p := add(p, 32)\n            mstore(p, 64) // length of modulus\n            p := add(p, 32)\n            mstore(p, y_hi)\n            p := add(p, 32)\n            mstore(p, y_lo)\n            p := add(p, 32)\n            mstore(p, P_PLUS_ONE_SLASH_2_HI)\n            p := add(p, 32)\n            mstore(p, P_PLUS_ONE_SLASH_2_LO)\n            p := add(p, 32)\n            mstore(p, P_HI)\n            p := add(p, 32)\n            mstore(p, P_LO)\n            ok := staticcall(gas(), MODEXP_ADDRESS, add(32, buf), 288, add(32, buf), 64)\n            y_hi := mload(add(buf, 32))\n            y_lo := mload(add(buf, 64))\n        }\n        assert(ok);\n\n        uint128 alt_y_hi = P_HI - y_hi;\n        uint256 alt_y_lo;\n        unchecked {\n            alt_y_lo = P_LO - y_lo;\n        }\n        if (alt_y_lo > P_LO) {\n            // underflow -> carry\n            alt_y_hi -= 1;\n        }\n\n        bool do_swap = y_hi > alt_y_hi || (y_hi == alt_y_hi && y_lo > alt_y_lo);\n        do_swap = larger == do_swap;\n        if (do_swap) {\n            y_hi = alt_y_hi;\n            y_lo = alt_y_lo;\n        }\n\n        return PointG1(x_hi, x_lo, y_hi, y_lo);\n    }\n\n    /// @notice Marshals a point on G1 to bytes form.\n    function g1Marshal(PointG1 memory point) internal pure returns (bytes memory) {\n        bytes memory m = new bytes(96);\n        uint256 x_hi = point.x_hi;\n        uint256 x_lo = point.x_lo;\n        uint256 y_hi = point.y_hi;\n        uint256 y_lo = point.y_lo;\n\n        assembly {\n            mstore(add(m, 0x20), shl(128, x_hi))\n            mstore(add(m, 0x30), x_lo)\n            mstore(add(m, 0x50), shl(128, y_hi))\n            mstore(add(m, 0x60), y_lo)\n        }\n\n        return m;\n    }\n\n    function g2Unmarshal(bytes memory m) internal pure returns (PointG2 memory) {\n        require(m.length == 192, \"Invalid G2 bytes length\");\n\n        uint128 x1_hi;\n        uint256 x1_lo;\n        uint128 x0_hi;\n        uint256 x0_lo;\n        uint128 y1_hi;\n        uint256 y1_lo;\n        uint128 y0_hi;\n        uint256 y0_lo;\n\n        assembly {\n            x1_hi := shr(128, mload(add(m, 0x20)))\n            x1_lo := mload(add(m, 0x30))\n            x0_hi := shr(128, mload(add(m, 0x50)))\n            x0_lo := mload(add(m, 0x60))\n            y1_hi := shr(128, mload(add(m, 0x80)))\n            y1_lo := mload(add(m, 0x90))\n            y0_hi := shr(128, mload(add(m, 0xb0)))\n            y0_lo := mload(add(m, 0xc0))\n        }\n\n        return PointG2(x1_hi, x1_lo, x0_hi, x0_lo, y1_hi, y1_lo, y0_hi, y0_lo);\n    }\n\n    function g2Marshal(PointG2 memory point) internal pure returns (bytes memory) {\n        bytes memory m = new bytes(192);\n        uint256 x1_hi = point.x1_hi;\n        uint256 x1_lo = point.x1_lo;\n        uint256 x0_hi = point.x0_hi;\n        uint256 x0_lo = point.x0_lo;\n        uint256 y1_hi = point.y1_hi;\n        uint256 y1_lo = point.y1_lo;\n        uint256 y0_hi = point.y0_hi;\n        uint256 y0_lo = point.y0_lo;\n\n        assembly {\n            mstore(add(m, 0x20), shl(128, x1_hi))\n            mstore(add(m, 0x30), x1_lo)\n            mstore(add(m, 0x50), shl(128, x0_hi))\n            mstore(add(m, 0x60), x0_lo)\n            mstore(add(m, 0x80), shl(128, y1_hi))\n            mstore(add(m, 0x90), y1_lo)\n            mstore(add(m, 0xb0), shl(128, y0_hi))\n            mstore(add(m, 0xc0), y0_lo)\n        }\n\n        return m;\n    }\n\n    // follows RFC9380 \u00a75\n    function hashToPoint(bytes memory dst, bytes memory message) internal view returns (PointG1 memory out) {\n        bytes memory uniform_bytes = expandMsg(dst, message, 128);\n        bytes memory buf = new bytes(225);\n        bytes memory buf2 = new bytes(256);\n        bool ok;\n        for (uint256 i = 0; i < 2; i++) {\n            assembly {\n                // inplace mod in uniform_bytes[64*i]\n                let p := add(32, uniform_bytes)\n                let q := add(32, buf)\n\n                p := add(p, mul(64, i))\n                mstore(q, 64) // length of base\n                q := add(q, 32)\n                mstore(q, 1) // length of exponent 1\n                q := add(q, 32)\n                mstore(q, 64) // length of modulus\n                q := add(q, 32)\n                mcopy(q, p, 64) // copy base\n                q := add(q, 64)\n                mstore8(q, 1) // exponent\n                q := add(q, 1)\n                mstore(q, P_HI)\n                q := add(q, 32)\n                mstore(q, P_LO)\n                ok := staticcall(gas(), MODEXP_ADDRESS, add(32, buf), 225, p, 64)\n\n                // EIP-2537 map_fp_to_g1\n                let r := add(32, buf2)\n                r := add(r, mul(128, i))\n                ok := and(ok, staticcall(gas(), BLS12_MAP_FP_TO_G1, p, 64, r, 128))\n            }\n            require(ok);\n        }\n        assembly {\n            ok := staticcall(gas(), BLS12_G1ADD, add(buf2, 32), 256, out, 128)\n        }\n        require(ok, \"g1add failed\");\n    }\n\n    /// @notice Expand arbitrary message to n bytes, as described\n    ///     in rfc9380 section 5.3.1, using H = sha256.\n    /// @param DST Domain separation tag\n    /// @param message The message to expand\n    /// @param n_bytes The number of bytes to extend to\n    function expandMsg(bytes memory DST, bytes memory message, uint8 n_bytes) internal pure returns (bytes memory) {\n        uint256 domainLen = DST.length;\n        if (domainLen > 255) {\n            revert InvalidDSTLength(DST);\n        }\n        bytes memory zpad = new bytes(64);\n        bytes memory b_0 = abi.encodePacked(zpad, message, uint8(0), n_bytes, uint8(0), DST, uint8(domainLen));\n        bytes32 b0 = sha256(b_0);\n\n        bytes memory b_i = abi.encodePacked(b0, uint8(1), DST, uint8(domainLen));\n        bytes32 bi = sha256(b_i);\n        bytes memory out = new bytes(n_bytes);\n        uint256 ell = (n_bytes + uint256(31)) >> 5;\n        for (uint256 i = 1; i < ell; i++) {\n            b_i = abi.encodePacked(b0 ^ bi, uint8(1 + i), DST, uint8(domainLen));\n            assembly {\n                let p := add(32, out)\n                p := add(p, mul(32, sub(i, 1)))\n                mstore(p, bi)\n            }\n            bi = sha256(b_i);\n        }\n        assembly {\n            let p := add(32, out)\n            p := add(p, mul(32, sub(ell, 1)))\n            mstore(p, bi)\n        }\n        return out;\n    }\n\n    /// @notice Verify signed message on g1 against signature on g1 and public key on g2\n    /// @param signature Signature to check\n    /// @param pubkey Public key of signer\n    /// @param message Message to check\n    /// @return pairingSuccess bool indicating if the pairing check was successful\n    /// @return callSuccess bool indicating if the static call to the evm precompile was successful\n    function verifySingle(PointG1 memory signature, PointG2 memory pubkey, PointG1 memory message)\n        internal\n        view\n        returns (bool pairingSuccess, bool callSuccess)\n    {\n        uint256[24] memory input = [\n            signature.x_hi,\n            signature.x_lo,\n            signature.y_hi,\n            signature.y_lo,\n            N_G2_X0_HI,\n            N_G2_X0_LO,\n            N_G2_X1_HI,\n            N_G2_X1_LO,\n            N_G2_Y0_HI,\n            N_G2_Y0_LO,\n            N_G2_Y1_HI,\n            N_G2_Y1_LO,\n            message.x_hi,\n            message.x_lo,\n            message.y_hi,\n            message.y_lo,\n            pubkey.x0_hi,\n            pubkey.x0_lo,\n            pubkey.x1_hi,\n            pubkey.x1_lo,\n            pubkey.y0_hi,\n            pubkey.y0_lo,\n            pubkey.y1_hi,\n            pubkey.y1_lo\n        ];\n        uint256[1] memory out;\n        assembly {\n            callSuccess := staticcall(gas(), BLS12_PAIRING_CHECK, input, 768, out, 0x20)\n        }\n        return (out[0] != 0, callSuccess);\n    }\n}\n"}, "contracts/vendor/bls-solidity/Precompiles.sol": {"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8;\n\n// @notice address of the EIP-198 modular exponentiation precompile\nuint256 constant MODEXP_ADDRESS = 5;\n\n// @notice address of the EIP-196 BN254 G1 point addition\nuint256 constant ECADD_ADDRESS = 6;\n\n// @notice address of the EIP-196 BN254 G1 scalar multiplication\nuint256 constant ECMUL_ADDRESS = 7;\n\n// @notice address of the EIP-197 BN254 pairing check\nuint256 constant BN254_ECPAIRING_ADDRESS = 8;\n\n// @notice address of the EIP-2537 BLS12-381 point addition precompile\nuint256 constant BLS12_G1ADD = 0x0b;\n\n// @notice address of the EIP-2537 BLS12-381 pairing check precompile\nuint256 constant BLS12_PAIRING_CHECK = 0x0f;\n\n// @notice address of the EIP-2537 BLS12-381 base field element to point precompile\n// @dev it uses the Simplified Shallue-van de Woest\u0133ne-Ulas mapping (SSWU)\nuint256 constant BLS12_MAP_FP_TO_G1 = 0x10;\n"}}, "settings": {"optimizer": {"enabled": true, "runs": 200}, "evmVersion": "cancun", "outputSelection": {"*": {"*": ["abi", "evm.bytecode.object", "evm.deployedBytecode.object", "evm.deployedBytecode.immutableReferences"], "": ["ast"]}}}}