Skip to main content
A 4Mica transaction is a cryptographic guarantee: a signed payment commitment backed by payer collateral. The payer does not send an on-chain transfer for every request. They sign a guarantee, the recipient submits it to 4Mica Core, and Core returns a BLS certificate after it verifies the request and locks collateral. The is the payment authorization. After the recipient verifies it, they can provide the service knowing Core accepted the guarantee. There are two types of guarantees:
  • V1 is payable as soon as Core issues it. Use it for agreed payments.
  • V2 is validation-gated. A verifier, such as an , must confirm the job before the recipient can use the validation path for payment.
With V1, the payer and recipient already accept the payment terms. Core checks the payer signature, user status, accepted version, and collateral. If the request passes, Core stores the guarantee as FINALIZED_PAYABLE so it can enter cycle netting. With V2, the payer locks collateral without making the guarantee payable right away. The signed request includes a validation policy. Core checks that policy, stores the guarantee as PENDING_VALIDATION, and keeps it out of netting until the lifecycle changes. The recipient can use the validation path only if the trusted registry publishes a result that matches the policy.

Where req_id comes from

req_id must exist before the payer signs because it is part of the signed request. The payer or SDK generates a unique request identifier before signing. The cycle-native Core issuance path, /core/guarantees, does not generate req_id. It verifies the signed value, derives the deterministic guarantee_id from it, and rejects another guarantee with the same identity.

How V1 works

V1 fits known-party payments and x402 flows where you do not need external outcome validation.

V1 signed request fields

The payer signs these fields before the recipient submits the request to Core. Core verifies them, but it does not rewrite them.
FieldTypeSet byDescription
user_addressaddressPayer / SDKPayer wallet.
recipient_addressaddressRecipient, then payer / SDKRecipient wallet.
req_iduint256Payer / SDKUnique request identifier.
amountuint256Recipient, then payer / SDKToken base units.
asset_addressaddressRecipient, then payer / SDKSettlement asset. 0x0 means ETH.
timestampuint64Payer / SDKRequest time.
The submitted request also includes signature and scheme. The SDK uses EIP-712 signing.

V1 certificate fields

After Core accepts the request, it signs a BLS certificate over the issued guarantee. The certificate adds fields that come from Core rather than from the payer.
FieldTypeSet byDescription
domainbytes32CoreVersion domain.
cycle_iduint256CoreOwning cycle.
versionuint64Request, accepted by Core1.
user_addressaddressRequestPayer wallet.
recipient_addressaddressRequestRecipient wallet.
req_iduint256RequestRequest counter.
amountuint256RequestPayment amount.
asset_addressaddressRequestAsset.
timestampuint64RequestRequest time.

V1 lifetime

StateHow it startsWhat happens next
FINALIZED_PAYABLECore issues V1.Waits for netting.
NETTEDCore commits the batch.Debtor pays or defaults.
SETTLEDClearing completes.Collateral unlocks.
DEFAULT_REMUNERATEDDebtor misses finality.Collateral covers default.
V1 does not normally remain in ISSUED. Core stores accepted V1 guarantees as FINALIZED_PAYABLE because no validation step is left.

How V2 works

V2 is for payments that need validation before the recipient can collect. The trust model has three parties:
  1. Recipient proposes the validation requirements, including which registry to use, in the payment request.
  2. Payer signs those requirements, agreeing to pay only if that specific registry confirms the outcome.
  3. Core enforces the allowlist: before locking any collateral, Core checks that the proposed validation_registry_address is on the operator-configured allowlist. If it is not, the request is rejected immediately.
To find out which registries are approved on a given Core deployment, call GET /core/public-params. The response includes a trusted_validation_registries field listing all accepted registry addresses. This endpoint does not require authentication.

V2 signed request fields

V2 signs all V1 request fields plus validation_policy.
FieldTypeSet byDescription
user_addressaddressPayer / SDKPayer wallet.
recipient_addressaddressRecipient, then payer / SDKRecipient wallet.
req_iduint256Payer / SDKUnique request identifier.
amountuint256Recipient, then payer / SDKToken base units.
asset_addressaddressRecipient, then payer / SDKSettlement asset.
timestampuint64Payer / SDKRequest time.
validation_policyobjectRecipient + SDKValidation gate.

V2 validation policy fields

FieldTypeSet byDescription
validation_registry_addressaddressRecipient / policyRegistry that must publish the validation result. Core rejects the guarantee if this address is not on its operator allowlist.
validation_request_hashbytes32SDKPolicy hash.
validation_chain_iduint64Recipient / policyChain where the registry result must exist. Core rejects if this does not match its own chain ID.
validator_addressaddressRecipient / policyExpected validator.
validator_agent_iduint256Recipient / policyExpected agent ID.
min_validation_scoreuint8Recipient / policyRequired score, 1-100.
validation_subject_hashbytes32SDKPayment subject hash.
job_hashbytes32Recipient / policyJob identifier.
required_validation_tagstringRecipient / policyRequired result tag.

V2 certificate and on-chain fields

Core issues the same certificate fields as V1 and sets version to 2. The encoded V2 certificate also includes the validation policy fields.
FieldTypeSet byDescription
domainbytes32CoreV2 domain.
cycle_iduint256CoreOwning cycle.
versionuint64Request, accepted by Core2.
user_addressaddressRequestPayer wallet.
recipient_addressaddressRequestRecipient wallet.
req_iduint256RequestRequest counter.
amountuint256RequestPayment amount.
asset_addressaddressRequestAsset.
timestampuint64RequestRequest time.
validation_policy fieldsmixedRequest, validated by CoreValidation gate.

V2 lifetime

StateHow it startsWhat happens next
PENDING_VALIDATIONCore issues V2.Waits for resolution.
FINALIZED_PAYABLECore marks payable.Follows V1 netting.
DISPUTEDCore marks disputed.Stays out of netting.
CANCELLEDCore cancels it.Collateral unlocks.
NETTEDPayable V2 enters netting.Debtor pays or defaults.
SETTLEDClearing completes.Collateral unlocks.
DEFAULT_REMUNERATEDDefault path pays recipient.Collateral covers default.
The on-chain validation remuneration path does not use cycle netting. If the registry result does not match the policy, remunerate reverts and no funds move.

How settlement cycles affect both versions

Both V1 and V2 guarantees flow into a settlement cycle once they reach FINALIZED_PAYABLE. The cycle batches those guarantees, computes net positions across all participants, and commits a Merkle clearing batch on chain. Only the net amounts move. Individual guarantees are not settled one by one. Each cycle runs through six phases:
PhaseDefault timingWhat happens
Cycle open0 – 24 hCore accepts FINALIZED_PAYABLE guarantees into the batch.
Cycle closes24 hNo new guarantees enter. The batch is fixed.
Resolution cutoff+6 h after closeCore builds net debtor and creditor positions from the batch.
Clearing commit+15 min after cutoffMerkle root of net positions is committed on chain.
Payment window+2 h after commitNet debtors submit payment against their position.
Finality deadline+2 h after payment openUncovered positions become defaulted and are covered from locked collateral.
Timings are configurable per deployment. V2 guarantees that remain PENDING_VALIDATION, DISPUTED, or CANCELLED when a cycle closes are excluded from netting. They do not affect any net debit or credit position in that cycle.

V1 and V2 comparison

BehaviorV1V2
Signed by payerBase payment fieldsBase payment fields plus validation policy
Core status after issuanceFINALIZED_PAYABLEPENDING_VALIDATION
Validation registryNoYes
Enters cycle netting immediatelyYesNo
Can enter cycle netting laterAlready payableYes, after FINALIZED_PAYABLE
On-chain remuneration pathUses the base guarantee decoderUses the V2 validation decoder before payout
Best fitKnown-party or pre-approved paymentsAutonomous payments that need outcome validation

Builder guidance

Choose V1 when a signed request should become payable as soon as Core verifies it. Choose V2 when the payer should lock collateral first and release value only after a trusted validator confirms the result. When you build with V2:
  • Call GET /core/public-params and check trusted_validation_registries before building your payment requirements. Core rejects any registry not on that list.
  • Put all validation requirements in paymentRequirements.extra before the payer signs.
  • Use the SDK to compute validation_subject_hash and validation_request_hash.
  • Keep validation_chain_id aligned with the chain_id returned by GET /core/public-params.
  • Set min_validation_score from 1 to 100.
  • Make sure the validator publishes a result with the expected validator address, agent ID, score, and tag.
  • Treat pending guarantees as locked collateral until the lifecycle finalizes, disputes, cancels, or remunerates.
See Settlements, Bilateral netting cycles, and How x402 works for related flows.