Skip to main content

SSF-SPEC-001 โ€” The Stablecoin Stack

FieldValue
Document IDSSF-SPEC-001
TitleThe Stablecoin Stack
Version1.0.0
StatusDraft
Date2026-03-04
SupersedesSSF-SPEC-000, SSF-SPEC-001 (pre-unification), SSF-SPEC-002 (pre-unification)
Author(s)Adalton Reis [email protected]
Reviewersโ€”
OrganizationStablecoin Stack Foundation
Contact[email protected]
Public Address0x0000000000000000000000000000000000000000
LicenseApache License 2.0

Table of Contentsโ€‹

  1. Abstract
  2. Introduction
  3. Vision and Design Philosophy
  4. System Architecture
  5. Component Specifications
  6. Cryptographic Conventions
  7. Data Structures
  8. Submission Payloads
  9. The Acquiring Model
  10. Settlement Contract โ€” State Variables
  11. Settlement Contract โ€” Events
  12. Settlement Contract โ€” Fee Model
  13. Settlement Contract โ€” Functions
  14. Validation Rules
  15. Submission Flow
  16. End-to-End Payment Flow
  17. Error Handling
  18. Security Model
  19. Conformance
  20. Future Work
  21. Versioning
  22. Change Log
  23. License

1. Abstractโ€‹

This document is the foundational specification of the Stablecoin Stack โ€” an open architecture for processing stablecoin payments on Ethereum-compatible networks. It establishes the design philosophy, system architecture, component responsibilities, cryptographic conventions, data structures, submission protocols, on-chain contract interface, end-to-end payment flow, security model, and conformance requirements for the full stack.

The Stablecoin Stack is built on a central proposition: that cryptographic signatures are a superior foundation for payment authorisation compared to identity-based delegation models, and that the tooling to make this practical for everyday users is both achievable and urgently needed. All architectural decisions described herein follow directly from this proposition.

This is the single authoritative specification for the Stablecoin Stack. It supersedes the pre-unification documents SSF-SPEC-000, the pre-unification SSF-SPEC-001, and SSF-SPEC-002. Future companion specifications covering individual component interfaces will reference this document.


2. Introductionโ€‹

2.1 Purposeโ€‹

This document provides the normative definitions required to implement, deploy, audit, or assess conformance of any component of the Stablecoin Stack. It is intended for:

  • developers integrating a wallet or checkout front-end with the payment processor API;
  • smart-contract engineers implementing or auditing a conformant Settlement Contract;
  • payment processor operators who need to understand the on-chain guarantees upon which their off-chain service depends;
  • implementers building any conformant component of the Stablecoin Stack; and
  • auditors, regulators, and reviewers assessing the correctness, security, and compliance of an existing implementation.

2.2 Scopeโ€‹

This specification covers:

  • the design principles governing all architectural decisions;
  • the system architecture, principal actors, component responsibilities, and trust boundaries;
  • the cryptographic conventions for all signatures;
  • all data structures accepted by the payment processor;
  • the two primary submission flows: payment transfer and acquirer registration;
  • the full on-chain Settlement Contract interface: state variables, events, fee model, and functions;
  • the validation rules a compliant processor MUST enforce before broadcasting;
  • the end-to-end payment flow from session creation through settlement confirmation;
  • the security model and threat mitigations; and
  • conformance requirements for full and partial implementations.

This specification does not cover:

  • the Checkout Engine API exposed to merchant servers (planned: future specification);
  • the Broadcast Layer WebSocket protocol (planned: future specification);
  • individual microservice interface specifications (planned: future specifications);
  • key management and custody procedures;
  • token issuance and redemption mechanics;
  • regulatory compliance guidance; and
  • offline transaction signing (identified as future work).

2.3 Normative Referencesโ€‹

ReferenceDescription
ERC-20Token Standard โ€” Ethereum Improvement Proposal 20
ERC-2612Permit Extension for EIP-20 Signed Approvals
EIP-712Typed Structured Data Hashing and Signing
ECDSAElliptic Curve Digital Signature Algorithm (FIPS 186-4)
SEC 1 v2.0Elliptic Curve Cryptography โ€” SECG Standard
RFC 2119Key words for use in RFCs to Indicate Requirement Levels
RFC 4648The Base16, Base32, and Base64 Data Encodings
RFC 5246The Transport Layer Security (TLS) Protocol Version 1.2
RFC 8446The Transport Layer Security (TLS) Protocol Version 1.3
RFC 8705OAuth 2.0 Mutual-TLS Client Authentication
Solidity 0.8.xSmart Contract Programming Language โ€” solidity-lang.org
OpenZeppelin ContractsAudited Solidity contract library โ€” openzeppelin.com

2.4 Conventions and Terminologyโ€‹

The key words MUST, MUST NOT, REQUIRED, SHALL, SHOULD, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC 2119.

TermDefinition
Stablecoin StackThe full set of components, protocols, and interfaces specified by this document.
Payment ProcessorAn operator that deploys and runs a conformant instance of the Stablecoin Stack. Responsible for the Broadcast Layer, Checkout Engine, and Relayer.
RelayerThe account that submits signed transactions on-chain on behalf of payers, absorbing gas costs. Operated by the Payment Processor.
MerchantA business or individual that accepts stablecoin payments by integrating with the Checkout Engine.
PayerThe individual who holds the stablecoin and signs the payment commitment.
AcquirerA registered third-party participant entitled to a share of the processing fee on payments they referred.
Service ProviderAn Acquirer who has opted in to public discovery via the Basic Data Service. Visible to wallets as a selectable payment provider.
Settlement ContractThe on-chain Solidity smart contract that verifies signatures, executes token transfers, and distributes fees.
Permit SignatureAn ERC-2612 off-chain signature authorising the Settlement Contract to call permit() on a token contract, granting a token allowance. Corresponds to permitSig in payload structures.
Binding SignatureAn EIP-712 signature over the full operation parameters, authorising the processor to submit a specific operation. Corresponds to payWithPermitSig in payload structures.
ChargeA processor-issued record representing an expected payment of a specific amount, in a specific token, to a specific merchant, within a specific time window.
SessionThe lifecycle context of a single charge, from creation through to settlement or expiry.
Order ReferenceA 16-byte reference created by the merchant for tracking purposes. Embedded in the on-chain PermittedTransfer event and used for session reconciliation.
Payload IDA client-generated identifier correlating a submission with a specific broadcasting intent. Both the client and the processor MUST use this ID to ensure request idempotency; the processor MUST validate that this ID is known, currently unprocessed, and unique to the broadcast session.
Acquirer IDA 16-byte (bytes16) UUID uniquely identifying a registered Acquirer within the Settlement Contract.
Zero-UUIDThe Acquirer ID consisting entirely of zero bytes (0x00000000000000000000000000000000). Represents the absence of an Acquirer on a given payment.
Ephemeral TokenA short-lived, single-use token issued by the checkout-public-widget that authorises a wallet to retrieve session payment details.
Principal AmountThe token amount intended to reach the beneficiary before fee deduction.
Total With FeesThe total token amount that must be held by the payer, equal to the principal amount plus all applicable fees.
Base FeeThe minimum absolute fee charged by the processor on every transfer, in token units.
Acquiring FeeThe additional percentage-based fee charged on behalf of a registered Acquirer.
AdministratorThe privileged account that controls operational parameters of the Settlement Contract. MUST NOT have the ability to move user funds.
Hex stringA UTF-8 string with a 0x prefix followed by an even number of lowercase hexadecimal digits.
EVM AddressA 20-byte account identifier, represented as a 42-character hex string (0x + 40 lowercase hex digits).
acquiringPriceThe amount that must be transferred to the Settlement Contract to register a new Acquirer, in the smallest unit of the respective token.

3. Vision and Design Philosophyโ€‹

Every architectural decision in the Stablecoin Stack derives from the following explicit principles.

3.1 User-Centric by Designโ€‹

Technical complexity must not be a barrier to participation. The end user โ€” the person making a payment โ€” SHOULD encounter a flow as simple as any mobile payment: open a wallet, confirm a transaction, done. All complexity โ€” signature construction, nonce management, fee calculation, gas payment โ€” MUST be absorbed by the infrastructure and hidden behind well-designed interfaces.

This principle applies equally to merchants. A merchant integrating the Stablecoin Stack SHOULD NOT need to understand ERC-2612 or EIP-712. They interact with an API that accepts standard e-commerce concepts: charges, sessions, webhooks, and reconciliation reports.

3.2 Payer Sovereigntyโ€‹

The authority to authorise a payment belongs exclusively to the payer, expressed through cryptographic signature. No component of the stack โ€” not the processor, not the relayer, not the checkout engine โ€” can move funds on a payer's behalf without a valid signed authorisation. The signature is the payment commitment; everything else is infrastructure for delivering and executing it.

The system is payer-agnostic: the identity of the account that submits a transaction to the network is irrelevant to its validity. Provided the signatures are correct, the payment executes.

3.3 Gas Abstraction as a Baselineโ€‹

Requiring users to hold native gas tokens creates friction that is, in the context of a payment system, entirely artificial. The Stablecoin Stack resolves this at the architectural level: gas is always paid by the Relayer, which recovers costs through the processing fee. The user holds only the stablecoin they wish to spend.

3.4 Complementary Rails, Not Replacementโ€‹

The Stablecoin Stack does not position itself as a replacement for existing payment infrastructure. It is a set of complementary rails, particularly well-suited to cross-border transfers, privacy-preserving payments, contexts where the parties lack a shared banking relationship, and scenarios where programmable settlement logic adds value.

3.5 Open by Defaultโ€‹

All specifications, reference implementations, and supporting materials produced by the Foundation are published under open licences. There are no proprietary extensions, no closed conformance test suites, and no tollgates on the information required to build a compliant implementation.


4. System Architectureโ€‹

4.1 Principal Actorsโ€‹

ActorRole
MerchantCreates charges and receives settlement confirmation. Integrates with the Checkout Engine over mTLS. Does not interact directly with the blockchain.
PayerHolds the stablecoin, signs the payment commitment, and submits the payload via a compliant wallet. Never submits transactions directly to the network.
Payment ProcessorOperates the off-chain infrastructure (Checkout Engine, Broadcast Layer, Relayer). Acts as the trusted intermediary between Merchants and the on-chain Settlement Contract.
AcquirerA registered third party who distributes the payment service to payers and earns a share of the processing fee. May operate as a public Service Provider.

4.2 Component Overviewโ€‹

A fully conformant Stablecoin Stack deployment MUST include the following components:

ComponentSubsystemKey Requirements
Settlement ContractOn-chainMUST satisfy all requirements of Sections 10โ€“13 of this specification.
core-checkout-engineCheckout EngineMUST expose a charge creation API to merchants over mTLS. MUST reconcile sessions on confirmed PermittedTransfer events.
checkout-public-widgetCheckout EngineMUST issue single-use Ephemeral Tokens. MUST deliver session parameters to wallets.
ca-serverCheckout EngineMUST issue and manage certificates for mTLS sessions between merchant servers and core-checkout-engine.
login-serverCheckout EngineMUST issue JWT bearer tokens within authenticated mTLS sessions.
credentials-managerCheckout EngineMUST manage certificate lifecycle and user administration.
merchant-dashboardCheckout EngineSHOULD provide real-time order monitoring, fee reporting, and account management.
wallet-gatewayBroadcast LayerMUST accept TransferRequest and BuyAcquiringPackRequest payloads. MUST maintain WebSocket connections for real-time status updates. SHOULD provide nonce retrieval and fee calculation to wallets.
broadcast-serviceBroadcast LayerMUST enqueue validated payloads, manage submission state transitions, and publish state updates to wallets via wallet-gateway.
broadcast-submitterBroadcast LayerMUST hold the Relayer's funded account and be the sole component that issues on-chain transactions.
balance-and-historyBroadcast LayerSHOULD maintain real-time wallet balance views and deliver transfer notifications over WebSocket.
transfer-historyEvent IndexingMUST monitor the Settlement Contract for PermittedTransfer events and publish confirmed events to the Checkout Engine after a configurable number of block confirmations.
basic-data-serverShared InfrastructureMUST expose a publicly accessible read-only API providing supported token lists, Service Provider registry, and processor configuration.
Client WalletClientMUST satisfy all wallet requirements stated in Section 5.6.

4.3 Trust Boundariesโ€‹

Fully trusted by the payer: the payer's own private key and the wallet software that manages it. No other component is trusted to act on the payer's behalf without a valid signature.

Trusted by the merchant within a verified mTLS session: the core-checkout-engine, which receives charge creation requests and delivers settlement confirmation.

Trusted to relay faithfully, but not trusted with funds: the Payment Processor and Relayer. They can submit transactions but cannot construct valid signatures without the payer's key. A malicious Processor cannot forge a payment.

Trusted as a shared public resource: the basic-data-server. It holds no private state and serves only public reference data.

Trust-minimised โ€” verified on-chain: the Settlement Contract. Its behaviour is determined by its deployed bytecode, verified independently by the blockchain network. No off-chain component can alter its execution.


5. Component Specificationsโ€‹

5.1 Settlement Contractโ€‹

The Settlement Contract is the trust anchor of the entire system. Its responsibilities are:

  • verifying the Permit Signature against the ERC-2612 token contract;
  • verifying the Binding Signature against the processor's authorisation;
  • preventing replay attacks by recording consumed Binding Signature hashes in usedHashes;
  • transferring the full payment amount from the payer via permit() and transferFrom();
  • computing and distributing fees to the processor and, if applicable, the acquirer;
  • crediting the principal amount to the merchant beneficiary; and
  • registering new acquirers upon receipt of a valid buyAcquiringPack call.

The Settlement Contract MUST be deployed by the Payment Processor and its address MUST be published in the Basic Data Service. The full on-chain interface is specified in Sections 10โ€“13.

5.2 Checkout Engineโ€‹

The Checkout Engine is the merchant-facing subsystem. It manages the lifecycle of payment sessions from charge creation through final reconciliation.

core-checkout-engine โ€” The central service. Exposes an API to merchant servers for session creation, charge management, and reconciliation queries. Receives confirmed settlement events from transfer-history and marks corresponding charges as settled. Communication with merchants MUST be secured by mutual TLS (mTLS).

checkout-public-widget โ€” A payment page hosted by the Payment Processor. Displays merchant-supplied order information and issues an Ephemeral Token that the wallet uses to fetch payment parameters. The widget does not accept payment directly; it serves only as a secure information delivery mechanism between the Checkout Engine and the wallet.

ca-server โ€” An internal Certificate Authority that issues and manages the client and server certificates used in mTLS sessions between merchant servers and the core-checkout-engine.

login-server โ€” Provides merchants with a mechanism to obtain JWT bearer tokens within the mTLS context, simplifying programmatic API access.

credentials-manager โ€” Administrative service for certificate lifecycle management and user administration. Interfaces with the ca-server and Keycloak identity service.

merchant-dashboard โ€” The merchant-facing web interface. Provides account management, real-time order monitoring, fee reporting, and statistical views.

5.3 Broadcast Layerโ€‹

The Broadcast Layer is responsible for receipt, validation, queuing, submission, and real-time status reporting of signed payment payloads.

wallet-gateway โ€” The external entry point for wallet connections. Accepts payload submissions and maintains persistent WebSocket connections for real-time status updates. Also provides nonce retrieval and fee calculation as convenience endpoints, reducing the need for wallets to perform direct on-chain calls.

broadcast-service โ€” Manages the internal lifecycle of a submission. Enqueues validated payloads and tracks each through a defined set of states. State transitions are published in real time to connected wallets via wallet-gateway. Submission completion โ€” meaning the Relayer received no revert when broadcasting โ€” does NOT constitute final settlement. Finality is confirmed by transfer-history after sufficient block confirmations.

broadcast-submitter โ€” The component that holds the Relayer's funded account and submits signed payloads on-chain. This is the only component in the off-chain stack that issues Ethereum transactions.

balance-and-history โ€” Maintains a real-time view of known wallet balances and delivers on-chain transfer notifications to wallets over WebSocket.

5.4 Event Indexing and Historyโ€‹

transfer-history โ€” Monitors the Settlement Contract and all supported ERC-2612 token contracts for on-chain events. When a PermittedTransfer event is observed with sufficient block confirmation depth, transfer-history publishes the confirmed event to the Checkout Engine, which uses the ref field to reconcile the corresponding charge. This service has no write authority over any other component; it is a read-and-publish relay.

5.5 Basic Data Serviceโ€‹

basic-data-server โ€” A publicly accessible, read-only service providing:

  • the list of ERC-2612-compliant stablecoins supported by the processor;
  • the registry of registered Acquirers who have opted in to public discovery (Service Providers); and
  • the public wallet addresses and configuration of the Payment Processor.

This service is intentionally designed to be operable as a shared public resource. The Foundation intends to operate a canonical instance as a free public good for the ecosystem.

5.6 Client Walletโ€‹

A conformant Client Wallet MUST be able to:

  • retrieve payment session details from the checkout-public-widget using an Ephemeral Token;
  • read the payer's ERC-2612 nonce from the token contract or wallet-gateway;
  • construct and sign a valid PermitParams structure using EIP-712;
  • construct and sign a valid PayWithPermitParams structure using EIP-712;
  • assemble a complete TransferRequest payload as specified in Section 8.2;
  • submit the payload to the wallet-gateway and maintain a WebSocket connection for status updates; and
  • present the payment status to the user in a clear and timely manner.

The wallet MUST NOT transmit the payer's private key or seed phrase to any remote service at any time. All signing MUST be performed locally on the user's device.

5.7 Merchant Dashboardโ€‹

The merchant-dashboard provides merchants with a self-service interface to manage their integration with the Checkout Engine. It does not interact with the blockchain directly. Its backend delegates all payment session and reconciliation logic to the core-checkout-engine. Merchants access it using credentials managed by the credentials-manager.


6. Cryptographic Conventionsโ€‹

6.1 Signature Algorithmโ€‹

All signatures in this specification are produced using the Elliptic Curve Digital Signature Algorithm (ECDSA) over the secp256k1 curve, as specified in FIPS 186-4 and SEC 1 v2.0. This is the same scheme used natively by the Ethereum protocol.

6.2 Typed Data Signing (EIP-712)โ€‹

Every signature MUST be computed over a structured hash produced in accordance with EIP-712. This scheme binds each signature to a specific domain (chain identifier, contract address, and version) and to a well-typed data structure, preventing cross-domain and cross-type replay attacks.

A compliant signer MUST construct the digest as:

digest = keccak256(
0x1901 ||
domainSeparator ||
hashStruct(message)
)

where domainSeparator encodes the name, version, chainId, and verifyingContract of the relevant contract.

The Permit Signature MUST use the token contract's domain separator. The Binding Signature MUST use the Settlement Contract's domain separator.

6.3 Signature Representationโ€‹

FieldType / FormatRequiredDescription
hashbytes32 โ€” 66-char hex stringREQUIREDThe EIP-712 digest that was signed. 0x + 64 lowercase hex characters.
vuint8 โ€” integerREQUIREDRecovery identifier. MUST be 27 or 28. Some signers produce 0 or 1; processors MUST normalise by adding 27 if the value is less than 27.
rbytes32 โ€” 66-char hex stringREQUIREDThe r component of the ECDSA signature. 0x + 64 lowercase hex characters.
sbytes32 โ€” 66-char hex stringREQUIREDThe s component of the ECDSA signature. 0x + 64 lowercase hex characters.

All hex strings throughout this specification MUST use the 0x prefix and lowercase hexadecimal digits. Leading zero bytes MUST be preserved; the encoded string MUST always be the full expected length.


7. Data Structuresโ€‹

7.1 Signature Object โ€” ERC20RelayerSigโ€‹

A generic container for an ECDSA signature. Reused as permitSig and payWithPermitSig across all payload types.

FieldType / FormatRequiredDescription
hashbytes32 โ€” 66-char hex stringREQUIREDThe EIP-712 message digest. Must be exactly 32 bytes (0x + 64 hex chars).
vuint8 โ€” integer (27 or 28)REQUIREDECDSA recovery parameter. Processors MUST reject values outside {0, 1, 27, 28} and normalise 0 and 1 to 27 and 28 respectively.
rbytes32 โ€” 66-char hex stringREQUIREDFirst 32-byte component. Must be exactly 32 bytes.
sbytes32 โ€” 66-char hex stringREQUIREDSecond 32-byte component. Must be exactly 32 bytes.

7.2 ERC-2612 Permit Parameters โ€” PermitParamsโ€‹

Encapsulates the parameters of an ERC-2612 permit authorisation. Incorporated verbatim into the on-chain permit() call.

FieldType / FormatRequiredDescription
owneraddress โ€” 42-char hex stringREQUIREDThe Ethereum address of the token holder granting the approval.
spenderaddress โ€” 42-char hex stringREQUIREDThe address authorised to transfer tokens. Typically the Settlement Contract address.
valueuint256 โ€” decimal or hex stringREQUIREDThe total token amount approved, in the token's smallest unit. MUST equal the principal plus all applicable fees.
nonceuint256 โ€” decimal or hex stringREQUIREDThe current ERC-2612 permit nonce of the owner on the token contract. The processor MUST verify this matches the on-chain nonce at submission time.
deadlineuint256 โ€” Unix timestamp (seconds)REQUIREDThe permit expiry. The Settlement Contract will revert if block.timestamp exceeds this value.

7.3 Payment Transfer Parameters โ€” PayWithPermitParamsโ€‹

Defines the business-level parameters of a stablecoin payment.

FieldType / FormatRequiredDescription
tokenaddress โ€” 42-char hex stringREQUIREDThe contract address of the ERC-2612-compliant stablecoin to be transferred.
beneficiaryaddress โ€” 42-char hex stringREQUIREDThe merchant's receiving address. Funds are credited here after fee deduction.
refbytes32 โ€” 66-char hex stringREQUIREDA 32-byte field formed by the concatenation of the 16-byte Order Reference and the 16-byte Acquirer ID. Missing parts MUST be filled with zero bytes. This field MUST always be present.
permitParamsPermitParams โ€” nested objectREQUIREDThe ERC-2612 permit parameters. The owner field MUST match the address recovered from the Permit Signature.

7.4 Acquirer Registration Parameters โ€” BuyAcquiringPackPermitParamsโ€‹

Defines the parameters for purchasing an acquirer registration entitlement.

FieldType / FormatRequiredDescription
tokenaddress โ€” 42-char hex stringREQUIREDThe ERC-2612-compliant token used to pay the registration fee. Must be in acquiringAllowedTokens.
feeValueuint256 โ€” decimal or hex stringREQUIREDThe registration fee amount. MUST equal permitParams.value and the current acquiringPrice.
acquiringaddress โ€” 42-char hex stringREQUIREDThe Ethereum address to be registered as an Acquirer. Must not already be registered.
permitParamsPermitParams โ€” nested objectREQUIREDThe ERC-2612 permit parameters. The value field MUST equal feeValue.

8. Submission Payloadsโ€‹

8.1 Two-Signature Patternโ€‹

Every submission payload carries exactly two signature objects:

Signature fieldWhat it signsVerified by
permitSigERC-2612 Permit typed-data: authorises the Settlement Contract to call permit() on the token contract. Produced by the token holder.The ERC-2612 token contract on-chain.
payWithPermitSigThe full operation parameters. Authorises the processor to submit this specific operation. Produced by the payer.The Payment Processor off-chain, and the Settlement Contract on-chain.

Separating these two signatures ensures that neither the Payment Processor nor the token contract can unilaterally reuse an authorisation in an unintended context.

8.2 Payment Transfer Payload โ€” TransferRequestโ€‹

Submitted to initiate a stablecoin payment from a payer to a merchant beneficiary.

FieldType / FormatRequiredDescription
payWithPermitParamsPayWithPermitParams โ€” nested objectREQUIREDPayment parameters as defined in Section 7.3.
payWithPermitSigERC20RelayerSig โ€” nested objectREQUIREDBinding Signature over payWithPermitParams. The processor MUST recover the signer and verify it matches permitParams.owner.
permitSigERC20RelayerSig โ€” nested objectREQUIREDPermit Signature over the token's Permit typed-data. Forwarded verbatim to the Settlement Contract.
payloadIdstring โ€” UUID or processor-issued opaque IDREQUIREDClient-generated identifier for idempotency. The processor MUST validate that this ID is known, currently unprocessed, and unique to the broadcast session.

8.3 Acquirer Registration Payload โ€” BuyAcquiringPackRequestโ€‹

Submitted to register a new Acquirer. Upon settlement, the acquiring address is registered on-chain with a unique Acquirer ID.

FieldType / FormatRequiredDescription
buyAcquiringPackParamsBuyAcquiringPackPermitParams โ€” nested objectREQUIREDRegistration parameters as defined in Section 7.4.
payWithPermitSigERC20RelayerSig โ€” nested objectREQUIREDBinding Signature over buyAcquiringPackParams. The processor MUST recover the signer and verify it matches permitParams.owner.
permitSigERC20RelayerSig โ€” nested objectREQUIREDPermit Signature. The signed value MUST equal buyAcquiringPackParams.feeValue. Forwarded verbatim to the Settlement Contract.

9. The Acquiring Modelโ€‹

9.1 Overviewโ€‹

The Stablecoin Stack incorporates a first-class acquiring model allowing third-party participants โ€” Acquirers โ€” to distribute the payment service and earn a share of the processing fee. Acquirers are identified by a bytes16 UUID Acquirer ID. When a payer includes an Acquirer ID in a payment, the Settlement Contract automatically distributes the acquiring fee to the registered acquirer's balance. This distribution is atomic with the payment and is reflected in the CommissionGenerated event.

9.2 Acquirer Registrationโ€‹

Registration is performed by submitting a BuyAcquiringPackRequest payload to the Payment Processor, which broadcasts the corresponding buyAcquiringPack call on the Settlement Contract. Registration requires:

  • payment of the registration fee (acquiringPrice) in an accepted stablecoin;
  • selection of a fee percentage, subject to the maxAcquiringFee ceiling; and
  • the wallet address to be registered as the acquirer.

The payer and the account being registered do not need to be the same address, enabling delegated or sponsored registration. Upon successful registration, a new Acquirer ID is assigned on-chain and the AcquirerCreated event is emitted.

9.3 Fee Distributionโ€‹

Every payment processed by the Settlement Contract is subject to two fee components:

FeeTypeRecipient
Base Fee (baseFeeAmount)Absolute, in token unitsPayment Processor fee recipient
Acquiring FeePercentage of principalRegistered Acquirer (if Acquirer ID is non-zero)

The acquiring fee is applied only when the payment includes a non-zero Acquirer ID. Payments without an Acquirer MUST use the Zero-UUID to suppress the acquiring fee component without reverting.

9.4 Service Provider Discoveryโ€‹

An Acquirer who wishes to be discoverable by wallet users MAY publish their information to the basic-data-server, where they appear as a Service Provider. This opt-in mechanism allows wallets to present users with a curated list of available providers, enabling selection based on fee rates, reputation, or other criteria.


10. Settlement Contract โ€” State Variablesโ€‹

The following state variables constitute the minimal persistent state that a conformant Settlement Contract MUST maintain.

/// @notice Minimum absolute fee (in token units) charged on every transfer.
uint256 public baseFeeAmount;

/// @notice Maximum acquiring fee percentage an acquirer may configure.
uint256 public maxAcquiringFee;

/// @notice Internal token balances per participant.
/// Mapping: token address => participant address => amount.
mapping(address => mapping(address => uint256)) public balances;

/// @notice Registry of consumed Binding Signature hashes.
/// A hash present here MUST cause the transaction to revert.
mapping(bytes32 => bool) public usedHashes;

/// @notice Registry mapping Acquirer IDs to wallet addresses.
mapping(bytes16 => address) public acquirerWallets;

/// @notice Fee percentage charged by each registered acquirer.
mapping(address => uint256) public acquiringFeePercent;

/// @notice Set of ERC-2612-compliant tokens accepted for acquirer registration.
mapping(IERC20Permit => bool) public acquiringAllowedTokens;

/// @notice Price (in token units) required to register as a new acquirer.
uint256 public acquiringPrice;

Notes:

  • baseFeeAmount provides a floor ensuring every transaction covers at minimum the cost of on-chain execution. Administrators SHOULD set this to reflect prevailing gas costs.
  • maxAcquiringFee is a ceiling applied at acquirer registration. Acquirers MAY set their fee anywhere between zero and this ceiling.
  • balances uses a two-level mapping (token โ†’ participant โ†’ amount) to support multiple token types.
  • usedHashes stores the EIP-712 digest of each processed Binding Signature. Once recorded, any subsequent submission presenting the same hash MUST revert.
  • acquirerWallets uses bytes16 (UUID) keys. The canonical term for this key is Acquirer ID.

11. Settlement Contract โ€” Eventsโ€‹

A conformant Settlement Contract MUST emit the following events.

/// @notice Emitted when a participant withdraws their accumulated balance.
event Withdrawal(
address indexed owner,
address indexed beneficiary,
uint256 amount
);

/// @notice Emitted upon successful execution of a permitted token transfer.
/// @param orderReference The 32-byte field: 16-byte Order Reference || 16-byte Acquirer ID.
event PermittedTransfer(
bytes32 indexed domainSeparator,
address indexed token,
address indexed payer,
address recipient,
uint256 value,
uint256 fee,
bytes32 orderReference
);

/// @notice Emitted when a new acquirer is successfully registered.
event AcquirerCreated(
bytes16 indexed acquirerId,
address indexed wallet,
uint256 feePercent
);

/// @notice Emitted when an acquirer updates their fee percentage.
event AcquiringFeeUpdated(
address indexed acquiring,
uint256 feePercent
);

/// @notice Emitted when an acquiring fee is generated on a payment.
event CommissionGenerated(
bytes16 indexed acquirerId,
uint256 amount
);

Notes:

  • PermittedTransfer is the primary event consumed by transfer-history for session reconciliation. The orderReference field MUST match the ref value submitted in the TransferRequest payload.
  • AcquirerCreated uses feePercent โ€” not feeValue โ€” to clarify that this parameter represents a rate.
  • The Zero-UUID MUST never be registerable as an acquirer wallet. The contract MUST enforce this.

12. Settlement Contract โ€” Fee Modelโ€‹

12.1 Overviewโ€‹

Every payment is subject to two potentially applicable fee components:

Fee ComponentTypeApplicability
Base Fee (baseFeeAmount)Absolute, in token unitsApplied to every transfer unconditionally.
Acquiring FeePercentage of the principal, as set by the acquirerApplied only when the payment includes a non-zero Acquirer ID.

When no acquirer is involved, the caller MUST pass the Zero-UUID (0x00000000000000000000000000000000) as the acquirerId. The Zero-UUID suppresses the Acquiring Fee component entirely without reverting.

12.2 calculateFeesโ€‹

Computes the total fee to be added on top of a given principal amount.

function calculateFees(
uint256 amount,
bytes16 acquirerId
) public view returns (uint256 totalFee)
ParameterTypeDescription
amountuint256The principal amount intended to reach the beneficiary, in token units.
acquirerIdbytes16The Acquirer ID. Pass Zero-UUID if no acquirer is involved.

Returns: totalFee โ€” the absolute fee amount that must be added to amount to yield the correct PermitParams.value.

12.3 breakdownTransferAmountโ€‹

Decomposes a total amount (principal plus fees) into its constituent parts.

function breakdownTransferAmount(
uint256 totalWithFees,
bytes16 acquirerId
) public view returns (uint256 principalAmount, uint256 totalFees)
ParameterTypeDescription
totalWithFeesuint256The total token amount inclusive of fees. The value in the permit's value field.
acquirerIdbytes16The Acquirer ID. Pass Zero-UUID if no acquirer is involved.

Returns: principalAmount โ€” amount credited to beneficiary; totalFees โ€” fees distributed to processor and acquirer.


13. Settlement Contract โ€” Functionsโ€‹

13.1 transferWithPermitโ€‹

Executes a complete stablecoin payment: verifies both signatures, collects the full amount from the payer, distributes fees, and credits the principal to the beneficiary.

function transferWithPermit(
IERC20Permit token,
address tokenOwner,
uint256 amount,
uint256 deadline,
uint8 v1, bytes32 r1, bytes32 s1,
uint8 v2, bytes32 r2, bytes32 s2,
address recipient,
bytes32 ref
) external
ParameterTypeDescription
tokenIERC20PermitThe ERC-2612-compliant stablecoin to transfer from.
tokenOwneraddressThe token holder whose permit authorises the transfer.
amountuint256Total amount inclusive of all fees. MUST equal value in the signed permit.
deadlineuint256Permit expiry. Forwarded to token.permit().
v1, r1, s1signaturePermit Signature โ€” validated by the ERC-2612 token contract.
v2, r2, s2signatureBinding Signature โ€” validated by the Settlement Contract.
recipientaddressBeneficiary address. Receives principal after fee deduction.
refbytes3232-byte field: 16-byte Order Reference || 16-byte Acquirer ID.

The function MUST revert if: Binding Signature digest is in usedHashes ยท Binding Signature signer not authorised ยท deadline โ‰ค block.timestamp ยท token.permit() reverts ยท tokenOwner balance less than amount.

Upon successful execution: Binding Signature digest recorded in usedHashes ยท amount transferred from tokenOwner ยท fees distributed ยท principal credited to recipient ยท PermittedTransfer emitted ยท CommissionGenerated emitted if acquirer fee applies.

13.2 buyAcquiringPackโ€‹

Registers a new Acquirer by accepting a fee payment. The payer and the account being registered do not need to be the same address.

function buyAcquiringPack(
IERC20Permit token,
address payer,
address acquiring,
uint256 feePercent,
uint256 price,
uint256 deadline,
uint8 v1, bytes32 r1, bytes32 s1,
uint8 v2, bytes32 r2, bytes32 s2
) public
ParameterTypeDescription
tokenIERC20PermitToken used to pay the registration fee. Must be in acquiringAllowedTokens.
payeraddressToken holder paying the fee. May differ from acquiring.
acquiringaddressWallet to be registered as Acquirer. Must not already be registered.
feePercentuint256Acquiring fee percentage. MUST NOT exceed maxAcquiringFee.
priceuint256Registration fee in token units. MUST equal current acquiringPrice.
deadlineuint256Permit expiry.
v1, r1, s1signaturePermit Signature โ€” validated by the ERC-2612 token contract.
v2, r2, s2signatureBinding Signature โ€” validated by the Settlement Contract.

The function MUST revert if: token not in acquiringAllowedTokens ยท feePercent exceeds maxAcquiringFee ยท price does not equal acquiringPrice ยท acquiring already registered ยท Binding Signature digest in usedHashes ยท Binding Signature signer not authorised ยท token.permit() reverts ยท payer balance less than price.

Upon successful execution: Binding Signature digest recorded in usedHashes ยท price transferred from payer to fee recipient ยท new bytes16 Acquirer ID assigned and recorded in acquirerWallets ยท acquiring recorded in acquiringFeePercent ยท AcquirerCreated emitted.

13.3 getBalances (single token)โ€‹

function getBalances(
address token,
address[] calldata users
) external view returns (uint256[] memory balances)

Returns internal balances for a list of participants in a single token. Response array is parallel to users.

13.4 getBalances (multi-token overload)โ€‹

function getBalances(
address[] calldata tokens,
address[] calldata users
) external view returns (uint256[][] memory balances)

Returns internal balances for multiple participants across multiple tokens. balances[i][j] is the internal balance of users[j] for tokens[i].

13.5 getAcquiringWalletโ€‹

function getAcquiringWallet(
bytes16 acquirerId
) public view returns (address)

Resolves the wallet address registered under a given Acquirer ID. Returns the zero address if not registered.


14. Validation Rulesโ€‹

A compliant Payment Processor MUST enforce all of the following checks before broadcasting a transaction. Any failure MUST result in immediate rejection with an appropriate error code. Partial processing is not permitted.

14.1 Structural Validationโ€‹

  • All REQUIRED fields MUST be present and non-empty.
  • All hex strings MUST have a 0x prefix and consist exclusively of hexadecimal digits (0โ€“9, aโ€“f). Uppercase hex MUST be normalised to lowercase before processing.
  • Address fields MUST be exactly 42 characters (0x + 40 hex digits).
  • bytes32 fields MUST be exactly 66 characters (0x + 64 hex digits).
  • The v field MUST be an integer. Values of 0 or 1 MUST be normalised to 27 or 28 respectively. All other values outside {0, 1, 27, 28} MUST be rejected.
  • Numeric fields (value, nonce, deadline, feeValue) MUST represent non-negative integers within the uint256 range (0 to 2ยฒโตโถ โˆ’ 1).

14.2 Semantic Validationโ€‹

  • The deadline field in permitParams MUST be strictly greater than the processor clock at time of receipt. Processors SHOULD apply a configurable tolerance (e.g., 30 seconds) to account for clock skew.
  • The nonce field in permitParams MUST match the current on-chain permit nonce of the owner address on the specified token contract.
  • For TransferRequest, the payloadId MUST correspond to a known, unprocessed checkout session held by the processor.
  • For TransferRequest, the ref field MUST be present. It is formed by the 16-byte Order Reference concatenated with the 16-byte Acquirer ID. Missing parts MUST be filled with zeros.
  • For BuyAcquiringPackRequest, feeValue MUST equal permitParams.value.

14.3 Cryptographic Validationโ€‹

  • The signer recovered from payWithPermitSig MUST equal permitParams.owner for both payload types.
  • The processor SHOULD verify permitSig locally using the token contract's EIP-712 domain separator before broadcasting, to avoid on-chain reversal.
  • The hash field in each ERC20RelayerSig MUST equal the digest that the processor recomputes from the accompanying parameters. Mismatches MUST be rejected.

15. Submission Flowโ€‹

15.1 Payment Transfer โ€” Step-by-Stepโ€‹

  1. Checkout Engine issues a payment session: ref (16-byte Order Reference), beneficiary, token, principal amount, acquirerId, and deadline.
  2. Client Wallet fetches the current ERC-2612 nonce for the owner from the token contract or wallet-gateway.
  3. Client Wallet calls calculateFees(principal, acquirerId) to determine the fee. Computes permitValue = principal + fee.
  4. Client Wallet constructs PermitParams: owner, spender (Settlement Contract), value = permitValue, nonce, deadline.
  5. Client Wallet signs the ERC-2612 Permit typed-data using EIP-712 against the token contract's domain separator to produce permitSig.
  6. Client Wallet constructs the 32-byte ref: orderReference (16 bytes) || acquirerId (16 bytes). Missing parts filled with zeros.
  7. Client Wallet constructs PayWithPermitParams: token, beneficiary, ref, permitParams.
  8. Client Wallet signs PayWithPermitParams using EIP-712 against the Settlement Contract's domain separator to produce payWithPermitSig.
  9. Client Wallet generates a payloadId (UUID) and stores it for idempotency tracking.
  10. Client Wallet assembles the TransferRequest and submits it to the wallet-gateway over HTTPS.
  11. Payment Processor validates the payload per Section 14 and, on success, broadcasts the settlement transaction.
  12. Settlement Contract executes permit(), transferFrom(), and fee distribution atomically. The processor monitors the transaction and updates the session status accordingly.

15.2 Acquirer Registration โ€” Step-by-Stepโ€‹

  1. Client Wallet fetches acquiringPrice from the Settlement Contract or wallet-gateway.
  2. Client Wallet fetches the ERC-2612 nonce for the owner from the token contract or wallet-gateway.
  3. Client Wallet constructs PermitParams: owner, spender (Settlement Contract), value = acquiringPrice, nonce, deadline.
  4. Client Wallet signs the ERC-2612 Permit typed-data against the token contract's domain separator to produce permitSig.
  5. Client Wallet constructs BuyAcquiringPackPermitParams: token, feeValue = acquiringPrice, acquiring, permitParams.
  6. Client Wallet signs BuyAcquiringPackPermitParams using EIP-712 against the Settlement Contract's domain separator to produce payWithPermitSig.
  7. Client Wallet assembles the BuyAcquiringPackRequest and submits it to the wallet-gateway over HTTPS.
  8. Payment Processor validates the payload per Section 14 and broadcasts the settlement transaction.
  9. Settlement Contract executes permit(), collects the fee, registers the acquiring address with a randomly generated Acquirer ID, and emits AcquirerCreated.

16. End-to-End Payment Flowโ€‹

16.1 Phase A โ€” Session Creationโ€‹

  1. The Merchant Server sends a charge creation request to the core-checkout-engine over a mutually authenticated TLS session, including payment amount, accepted token, beneficiary address, and order metadata.
  2. The core-checkout-engine generates a unique 16-byte Order Reference, a Payload ID, and a deadline. A new charge session is created in the awaiting-payment state.
  3. The core-checkout-engine returns a Checkout Widget URL and an Ephemeral Token to the Merchant Server, which presents it to the payer via QR code, deep-link, or redirect.

16.2 Phase B โ€” Payload Construction and Signingโ€‹

  1. The Client Wallet redeems the Ephemeral Token against the checkout-public-widget to retrieve session parameters. The Ephemeral Token is invalidated upon first use.
  2. The wallet fetches the payer's ERC-2612 permit nonce and fee amount.
  3. The wallet constructs and signs PermitParams using EIP-712 (Permit Signature).
  4. The wallet constructs and signs PayWithPermitParams using EIP-712 (Binding Signature).

16.3 Phase C โ€” Submission and Off-Chain Validationโ€‹

  1. The wallet assembles the TransferRequest and submits it to the wallet-gateway. A WebSocket connection is maintained for status updates.
  2. The broadcast-service enqueues the submission; the wallet-gateway acknowledges receipt.
  3. The Payment Processor performs structural, semantic, and cryptographic validation per Section 14. Any failure causes immediate rejection with a categorised error.

16.4 Phase D โ€” On-Chain Settlementโ€‹

  1. The broadcast-submitter broadcasts the transaction by calling transferWithPermit on the Settlement Contract, paying gas from the Relayer's account.
  2. The Settlement Contract verifies the Binding Signature, checks usedHashes, calls permit(), and grants itself an allowance.
  3. The Settlement Contract calls transferFrom, distributes fees, credits the principal to the beneficiary, records the Binding Signature hash in usedHashes, and emits PermittedTransfer (and CommissionGenerated if applicable). All operations are atomic.
  4. The broadcast-service delivers a status update to the wallet confirming the transaction was broadcast without revert. This does not represent final settlement.

16.5 Phase E โ€” Confirmation and Reconciliationโ€‹

  1. The transfer-history service observes the PermittedTransfer event. After a configurable number of block confirmations, it publishes the confirmed event to the core-checkout-engine.
  2. The core-checkout-engine matches the event's orderReference against its session registry and marks the charge as settled.
  3. The core-checkout-engine dispatches a settlement webhook to the Merchant Server.
  4. The balance-and-history service delivers a final settlement notification to the wallet over WebSocket.

17. Error Handlingโ€‹

A compliant Payment Processor MUST communicate validation failures clearly and without ambiguity.

Error CategoryDescription
STRUCTURAL_ERRORA required field is absent, of the wrong type, or violates encoding constraints. The submission MUST be rejected immediately without any on-chain activity.
SEMANTIC_ERRORAll fields are structurally valid but a business rule is violated (e.g., expired deadline, nonce mismatch, unknown payloadId). The submission MUST be rejected with a descriptive error indicating the violated rule.
CRYPTOGRAPHIC_ERRORA signature cannot be verified or the recovered signer does not match the expected owner. The submission MUST be rejected. The processor MUST NOT disclose details that could aid signature forgery.
BROADCAST_ERRORThe payload passed all validation checks but the on-chain transaction reverted or could not be submitted. The processor MUST record the failure, return an appropriate error to the client, and MUST NOT mark the session as settled.

18. Security Modelโ€‹

18.1 Threat Modelโ€‹

ThreatMitigation
Forged payment commitmentECDSA signature; only the payer's private key can produce a valid Permit or Binding Signature.
Replay of a valid signatureusedHashes registry in the Settlement Contract; ERC-2612 nonce on the token contract.
Parameter substitution (change recipient, amount, or token after signing)Binding Signature covers all operation parameters; any modification invalidates the signature.
Processor submitting payment to wrong beneficiaryBeneficiary is embedded in the Binding Signature; alteration invalidates the signature.
Expired permit executed after deadlineSettlement Contract enforces block.timestamp โ‰ค deadline; token contract enforces the same.
Session replay (same payloadId submitted twice)Processor enforces single-use payloadId at the off-chain validation layer.
Malicious Relayer double-spendingImpossible without a valid Binding Signature; the Relayer holds no signing authority.
Merchant server impersonationmTLS mutual authentication between merchant servers and core-checkout-engine.
Ephemeral Token interceptionShort lifetime and single-use invalidation; contains no signing authority.

18.2 Dual-Signature Bindingโ€‹

The Permit Signature authorises a specific token contract to grant an allowance to the Settlement Contract. Its scope is limited to the allowance grant; it does not determine where funds go or how much is taken in fees.

The Binding Signature authorises the processor to execute a specific operation โ€” including the token, the beneficiary, the amount, the fee structure, and the Order Reference โ€” against the Settlement Contract. Without a valid Binding Signature, the Settlement Contract MUST revert.

Neither signature alone is sufficient to execute a payment. A valid Permit Signature without a valid Binding Signature results in an allowance with no execution. A valid Binding Signature without a valid Permit Signature results in a settlement attempt with no allowance.

18.3 Replay Protectionโ€‹

Replay protection is enforced at two independent layers:

  • ERC-2612 nonce โ€” the token contract tracks a per-owner nonce. Each issued permit increments the nonce, invalidating all previously issued permits for that owner.
  • usedHashes registry โ€” the Settlement Contract records the EIP-712 digest of every consumed Binding Signature. Any subsequent transaction presenting the same digest MUST revert.

Both controls MUST be active in a conformant implementation. They are complementary, not redundant.

18.4 Payer-Agnostic Execution and its Implicationsโ€‹

The payer-agnostic model enables the gasless relayer model. Any party in possession of both valid signatures can submit the transaction. This is acceptable because:

  1. the signatures bind the payment to specific parameters, including the beneficiary and the amount;
  2. the usedHashes registry ensures the same signatures cannot be used more than once; and
  3. submitting a valid transaction on behalf of a payer is not harmful to the payer โ€” it is precisely what they authorised.

Clients MUST submit payloads over TLS and MUST NOT persist signed payloads in environments accessible to untrusted parties.

18.5 Ephemeral Token Securityโ€‹

The Ephemeral Token issued by the checkout-public-widget is a time-bounded, single-use credential:

  • Short lifetime: the token MUST expire within a processor-configured window, RECOMMENDED to be no longer than 5 minutes.
  • Single use: the token MUST be invalidated upon first successful redemption.
  • No signing authority: possession of an Ephemeral Token does not enable payment. The payer's private key is still required for both signatures.

18.6 mTLS for Merchant Communicationโ€‹

Communication between Merchant Servers and the core-checkout-engine MUST be protected by mutual TLS. Both parties present certificates issued by the ca-server. JWT bearer tokens obtained via the login-server provide application-layer authorisation within the authenticated TLS session.

18.7 Administrative Privilege Boundariesโ€‹

The Administrator MUST be able to set baseFeeAmount, maxAcquiringFee, acquiringPrice, and the fee recipient address.

The Administrator MUST NOT be able to:

  • transfer tokens held in the contract's balance on behalf of any participant;
  • modify the usedHashes registry; or
  • alter the registered wallet address or fee percentage of an existing Acquirer without their consent.

This constraint MUST be enforced at the contract code level and verified by independent audit.


19. Conformanceโ€‹

19.1 Fully Compliant Stackโ€‹

A fully conformant Stablecoin Stack deployment MUST include:

  • a deployed Settlement Contract satisfying all requirements of Sections 10โ€“13;
  • a Checkout Engine satisfying all requirements of Section 5.2;
  • a Broadcast Layer satisfying all requirements of Sections 5.3 and 14;
  • a transfer-history service that monitors and reports confirmed on-chain events; and
  • a Basic Data Service accessible to wallets and other components.

A fully conformant Client Wallet MUST satisfy all requirements stated in Section 5.6.

19.2 Partial Conformanceโ€‹

Components MAY be implemented and deployed independently. A conformant Settlement Contract MAY be used with a non-reference Checkout Engine. A conformant wallet MAY interact with any Settlement Contract and Broadcast Layer that satisfies the specified interfaces. Partial conformance MUST be declared explicitly by the implementer, with clear indication of which sections are and are not satisfied.

19.3 Future Specificationsโ€‹

The following companion specifications are planned and will reference this document:

Planned IDSubject
SSF-SPEC-002wallet-gateway Interface
SSF-SPEC-003Broadcast Layer Protocol โ€” WebSocket protocol between wallet and wallet-gateway
SSF-SPEC-004Checkout Engine API โ€” merchant-facing session and charge management
SSF-SPEC-005broadcast-service Interface
SSF-SPEC-006broadcast-submitter Interface
SSF-SPEC-007transfer-history Interface
SSF-SPEC-008basic-data-server Interface
SSF-SPEC-009Client Wallet Certification

20. Future Workโ€‹

Offline Transaction Signing โ€” Enabling payers to construct and sign a payment commitment without a live network connection. This is a priority for populations with limited or intermittent mobile network access.

Multi-Network Support โ€” Extending conformance to non-EVM networks with equivalent programmable token standards.

Wallet Certification Programme โ€” A conformance test suite and certification programme for third-party wallet implementations.

Acquirer Incentive Structures โ€” Further specification of fee tier and pricing models available to Acquirers.

ref Field Evolution โ€” The ref field currently concatenates two values (Order Reference and Acquirer ID) that serve distinct and non-dependent purposes. A future version will separate these into independent fields.


21. Versioningโ€‹

This specification follows Semantic Versioning 2.0.0.

SegmentMeaning
MAJORA backwards-incompatible change to any interface, encoding, security model, or conformance requirement.
MINORAddition of new components, flows, or requirements that do not break existing conformant implementations.
PATCHEditorial corrections, clarifications, and non-normative changes that do not affect conformance.

All future companion specifications MUST declare the version of SSF-SPEC-001 to which they conform.


22. Change Logโ€‹

VersionDateAuthorSummary
1.0.02026-03-04Adalton ReisInitial release. Unification of SSF-SPEC-000 (system overview), pre-unification SSF-SPEC-001 (submission protocol), and SSF-SPEC-002 (Settlement Contract) into a single specification under the Layered Docs structure.

23. Licenseโ€‹

Copyright ยฉ 2026 Stablecoin Stack Foundation. All rights reserved.

This specification is published under the Apache License, Version 2.0. Unless required by applicable law or agreed to in writing, material distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.