This document outlines the security considerations, threat model, authorization mechanisms, and best practices for the Bridgelet Core system.
The Bridgelet Core system is designed to operate in a trust-minimized environment. The following threat vectors have been considered and mitigated:
- Threat: An attacker attempts to sweep funds from an active Ephemeral Account to their own wallet.
- Mitigation:
- Authorization Signatures: Sweeping requires a valid Ed25519 signature from an authorized signer. The
SweepControllercontract verifies this signature before allowing a sweep. - Destination Locking: The
SweepControllercan be initialized with a lockedauthorized_destination. If set, funds can only be swept to that specific address, regardless of the signer. - Nonce Protection: Each sweep operation requires a unique nonce to prevent replay attacks.
- Authorization Signatures: Sweeping requires a valid Ed25519 signature from an authorized signer. The
- Threat: An attacker attempts to sweep the same account multiple times or replay a valid sweep signature.
- Mitigation:
- State Machine: The
EphemeralAccountcontract enforces a strict state machine (Active->PaymentReceived->Swept|Expired). Once the state transitions toSwept, subsequent calls fail withError::AlreadySwept. - Nonces: The
SweepControllermaintains a monotonically increasing nonce. Every signed sweep request must include the current nonce, and the nonce is incremented upon success.
- State Machine: The
- Threat: An attacker attempts to keep funds in an ephemeral account indefinitely or sweep them after they should have expired.
- Mitigation:
- Ledger-based Expiration: Expiration is tied to the Stellar ledger sequence number, providing an objective time source.
- Guard Clauses: The
sweepfunction explicitly checksis_expired()and fails if the account has passed its expiry ledger. - Recovery Mechanism: After expiration, the
expire()function allows funds to be recovered to a pre-definedrecovery_address, preventing funds from being permanently locked.
- Threat: An attacker initializes an account with a past expiry or invalid parameters.
- Mitigation:
- Initialization Checks: The
initializefunction validates thatexpiry_ledgeris in the future. - One-time Initialization: The
Initializedflag prevents re-initialization of an existing contract.
- Initialization Checks: The
Bridgelet Core uses a layered authorization model:
- Mechanism:
require_auth() - Scope: The creator address must authorize the initialization of an
EphemeralAccount.
- Mechanism: Ed25519 Signatures + Soroban Auth
- Flow:
- Off-chain SDK generates a signature covering
hash(destination + nonce + contract_id). - Caller invokes
SweepController.execute_sweep. SweepControllerverifies the Ed25519 signature against the storedauthorized_signer.SweepControllercallsEphemeralAccount.sweep.EphemeralAccountvalidates its internal state and transitions toSwept.
- Off-chain SDK generates a signature covering
- Mechanism: Public (Permissionless)
- Scope: Once the expiry ledger is reached, anyone can call
expire()to return funds to the recovery address. This ensures funds are never stuck due to a missing signer.
The system employs the Checks-Effects-Interactions pattern and leverages Soroban's execution model:
- State Updates First: In
EphemeralAccount::sweep, the status is updated toSweptbefore any external calls or event emissions would typically occur (though currently, no external calls are made). - Atomic Execution: Soroban contract invocations are atomic. If any part of the sweep operation fails (e.g., signature verification), the entire transaction reverts, ensuring no partial state changes.
- Single-Threaded: Soroban executes transactions sequentially for a given contract instance, preventing race conditions.
- Single-Use: An account can effectively be swept only once.
- Time-Bounded: Funds are guaranteed to be either sweepable or recoverable after the expiry ledger.
- Auditability: All critical state transitions (
Created,PaymentReceived,Swept,Expired) emit on-chain events.
- EphemeralAccount Signature Verification: The
verify_sweep_authorizationfunction inEphemeralAccountis currently a placeholder ("TODO"). Do not rely onEphemeralAccount::sweepdirectly for security. Always route sweeps throughSweepController, which implements proper Ed25519 verification. - Token Transfers: The actual logic to move tokens (calling
token.transfer) is currently commented out or not fully integrated inSweepController. The contracts currently manage state and authorization but do not yet move funds.
- Asset Limit: The
EphemeralAccountsupports recording up to 10 distinct assets. - Gas Management: Users/Integrators are responsible for providing sufficient gas for sweep operations.
- Trust Assumption: The system assumes the
authorized_signerprivate key is kept secure off-chain.
- Use SweepController: Always use
SweepController::execute_sweepto perform sweeps. Never callEphemeralAccount::sweepdirectly, as it currently lacks active signature verification. - Verify Expiry: When creating accounts, ensure
expiry_ledgerprovides enough buffer for network latency and confirmation times. - Monitor Events: Listen for
AccountCreatedandPaymentReceivedevents to trigger off-chain workflows. - Key Management: Securely manage the Ed25519 private key used for generating sweep signatures. Use a hardware security module (HSM) or secure enclave if possible.
- Recovery: Monitor for expired accounts and trigger
expire()to reclaim funds to the recovery address.