trident-sdk 0.2.0

End-user SDK for Trident deposits and cross-chain spends
Documentation
#![allow(clippy::too_many_arguments)]

use alloy_sol_types::sol;

sol! {
    /// Cross-chain spend specification used for identity hashing.
    #[derive(Default, Debug, PartialEq, Eq, Hash)]
    struct SpendSpec {
        bytes32 srcSpender;
        uint32 srcDomain;
        bytes32 srcToken;
        bytes32 srcDepositContract;
        uint32 dstDomain;
        bytes32 dstToken;
        bytes32 dstDeliveryContract;
        bytes32 dstRecipient;
        bytes32 dstCaller;
        uint256 amount;
        bytes32 salt;
    }

    /// EIP-712 typed struct matching the Solidity `SpendIntent`.
    #[derive(Default, Debug, PartialEq, Eq, Hash)]
    struct SpendIntent {
        uint256 maxFee;
        uint256 expiryHeight;
        SpendSpec spec;
    }

    /// Signed payload authorizing one `TridentDelivery` execution.
    ///
    /// `expiryHeight` is an exclusive upper bound:
    /// the attestation is valid only while the destination contract's
    /// chain-specific block clock is less than `expiryHeight`.
    #[derive(Default, Debug, PartialEq, Eq, Hash)]
    struct SpendAttestation {
        SpendSpec spec;
        uint256 expiryHeight;
        uint8 liquidityPath;
        bytes liquidityPathData;
    }

    /// Spender/depositor-facing subset of the `TridentDeposits` contract ABI.
    #[sol(rpc, all_derives)]
    contract TridentDeposits {
        error ZeroAmount();
        error InvalidClaimDomain();
        error InvalidClaimDepositContract();
        error InvalidClaimAmount();
        error InvalidSpendIntentSigner();
        error ClaimSpendSpecHashAlreadyUsed(bytes32 hash);
        error SpendIntentExpired();
        error UnsupportedToken(address token);
        error EnforcedPause();

        event Deposit(address indexed depositor, address indexed token, uint256 amount);
        event DepositClaimed(
            bytes32 indexed spendSpecHash,
            address indexed token,
            uint256 amount,
            address indexed recipient,
            address signer,
            uint256 fee,
            address feeCollector
        );
        event DepositBalanceDeficit(
            address indexed depositor,
            address indexed token,
            bytes32 indexed spendSpecHash,
            uint256 claimAmount,
            uint256 fee,
            uint256 availableBalance
        );

        /// Deposits a supported token into `TridentDeposits`.
        function deposit(address token, uint256 amount) external;

        /// Returns whether `token` is currently depositable on this deployment.
        function isTokenSupported(address token) external view returns (bool);

        /// Returns the current supported-token allowlist for this deployment.
        function getSupportedTokens() external view returns (address[] memory);

        /// Returns the source-side balance tracked in `TridentDeposits` for `depositor` and `token`.
        ///
        /// This is the contract's own reimbursement ledger after processed claims.
        /// It is not the delivery-service balance returned by `TridentClient::get_balance`,
        /// and it is not a projected or attested amount.
        function depositedAmount(address depositor, address token) external view returns (uint256);

        /// Returns whether `spendSpecHash` has already been consumed on the source-side contract.
        function usedSpendSpecHashes(bytes32 spendSpecHash) external view returns (bool);

        /// Returns the source domain this deployment is configured for.
        function domain() external view returns (uint32);

        /// Returns the paired `TridentDelivery` contract address for this domain.
        function tridentDelivery() external view returns (address);

        /// Returns the configured withdrawal delay in blocks.
        function withdrawalDelay() external view returns (uint256);

        /// Returns the current source-side fee collector.
        function feeCollector() external view returns (address);

        /// Returns the EIP-712 struct hash for `intent`.
        function spendIntentStructHash(SpendIntent calldata intent) external pure returns (bytes32);

        /// Returns the EIP-712 digest a source spender signs for `intent`.
        function spendIntentDigest(SpendIntent calldata intent) external pure returns (bytes32);

        /// Recovers the signer of `intent` from its EIP-712 signature.
        function recoverSpendIntentSigner(SpendIntent calldata intent, bytes calldata signature)
            external
            pure
            returns (address);
    }

    /// Spender/depositor-facing subset of the `TridentDelivery` contract ABI.
    #[sol(rpc, all_derives)]
    contract TridentDelivery {
        error InvalidAttestationDomain();
        error InvalidAttestationCaller();
        error InvalidAttestationRecipient();
        error InvalidAttestationDeliveryContract();
        error InvalidAttestationAmount();
        error InvalidAttestationExpired();
        error InvalidAttestationToken();
        error AttestationSpendSpecHashAlreadyUsed(bytes32 hash);
        error InvalidLiquidityPath();
        error NotSameChainSpend();
        error TridentDepositsNotSet();
        error InvalidAttestationSigner();
        error UnsupportedToken(address token);
        error EnforcedPause();

        event SpendAttestationProcessed(
            bytes32 indexed spendSpecHash,
            address indexed token,
            uint256 amount,
            uint256 usdcMinted,
            address indexed signer
        );

        /// Executes a signed spend attestation.
        function tridentSpend(bytes calldata attestation, bytes calldata signature) external;

        /// Validates `attestation` against the destination contract's current state.
        ///
        /// This is useful for preflight simulation before sending `tridentSpend`.
        function validateSpendAttestation(bytes calldata attestation)
            external
            view
            returns (SpendAttestation memory spendAttestation);

        /// Returns whether `token` is currently spendable on this deployment.
        function isTokenSupported(address token) external view returns (bool);

        /// Returns the current supported-token allowlist for this deployment.
        function getSupportedTokens() external view returns (address[] memory);

        /// Returns whether `spendSpecHash` has already been consumed on the destination-side contract.
        function usedSpendSpecHashes(bytes32 spendSpecHash) external view returns (bool);

        /// Returns the destination domain this deployment is configured for.
        function domain() external view returns (uint32);

        /// Returns the paired `TridentDeposits` contract used for same-chain settlement.
        function tridentDeposits() external view returns (address);

        /// Returns whether `signer` is currently authorized to sign spend attestations.
        function isAttestationSigner(address signer) external view returns (bool);

        /// Returns the keccak256 hash of the encoded attestation payload bytes.
        function hashSpendAttestation(bytes calldata attestation) external pure returns (bytes32);

        /// Returns the EIP-191 digest of the encoded attestation payload bytes.
        function digestSpendAttestation(bytes calldata attestation) external pure returns (bytes32);
    }

    /// Minimal ERC-20 surface used by the SDK's deposit allowance flow.
    #[sol(rpc)]
    interface IERC20 {
        /// Returns the remaining allowance `spender` can pull from `owner`.
        function allowance(address owner, address spender) external view returns (uint256);
        /// Sets `spender`'s allowance on the caller's balance to `value`.
        function approve(address spender, uint256 value) external returns (bool);
    }
}