TL;DR
- Six regulatory actions (FREEZE, SEIZE, CONFISCATE, LIQUIDATE, RESTRICT, RECOVER) each possess unique state transition rules and reversibility conditions, standardized through OIP message formats
- OSS four-stage validation pipeline filters all regulatory actions through Authority Verification → State Transition Check → Legal Basis Verification → Cross-chain Consistency
- D-quencer priority system assigns CRITICAL (P0) priority to emergency regulatory actions, ensuring processing before standard transactions
- Three-phase cross-chain broadcast protocol (PREPARE → COMMIT → FINALIZE) supports three execution strategies based on atomicity level: ALL_OR_NOTHING, GUARANTEED, and BEST_EFFORT
- This specification transforms the philosophical foundation of enforceability into implementable technical standards, defining integration APIs for DeFi protocol developers
Introduction: From Philosophy to Protocol
In our previous exploration of enforceability as the third pillar of RCP, we philosophically examined why regulatory enforcement power is essential. We demonstrated that the fundamental contradiction of “how to implement centralized enforcement power in a decentralized system” could be resolved through the Selective Decentralization paradigm.
However, philosophical justification alone does not make systems operational. Protocol specification is required.
In our recent analysis of asset state management complexity, we introduced the Hierarchical Lock Status framework. We defined what states an asset can occupy and which transitions are valid. Now we must specify who can trigger these state transitions, how, and why.
This research fully specifies at the protocol level how six regulatory actions are encoded as OIP messages, validated by OSS, prioritized by D-quencer, and broadcast across chains.
“Protocol specification is the bridge between philosophy and implementation. Specification without principles yields directionless implementation; principles without specification remain unrealizable ideals.”
Taxonomy of Six Regulatory Actions
Action Characteristics Matrix
Building upon the Lock Status framework established in our asset state management research, each of the six regulatory actions possesses unique state transition rules. The following table summarizes the core characteristics of each action:
| Action | Permitted Start States | Target State | Reversibility | Cross-chain Requirement |
|---|---|---|---|---|
| FREEZE | AVAILABLE, RESERVED | RESTRICTED | true | Synchronous broadcast |
| SEIZE | RESTRICTED | SEIZED | Conditional | Atomic commit required |
| CONFISCATE | SEIZED | TERMINATED | false | Finality proof required |
| LIQUIDATE | AVAILABLE, RESTRICTED, SEIZED | TERMINATED | false | Market integration |
| RESTRICT | AVAILABLE | RESTRICTED | true | Condition propagation |
| RECOVER | RESTRICTED, SEIZED | AVAILABLE | N/A | Ownership restoration |
Enforcing the Escalation Chain
As argued in our enforceability analysis, the core of regulatory enforcement power lies in procedural legitimacy. Code must enforce legal procedure:
- SEIZE presupposes FREEZE — assets cannot be seized without first being frozen
- CONFISCATE presupposes SEIZE — assets cannot be confiscated without first being seized
- RECOVER presupposes proof of fraudulent acquisition — legal basis for ownership restoration is required
This escalation chain is enforced during the State Transition Check stage of the OSS validation pipeline.
OIP Regulatory Action Message Format
Base Message Structure
In OIP v0.3, regulatory actions are defined as the REGULATORY_ACTION message type. Extending the base OIP message structure from our earlier protocol specification, regulatory-specific fields are added:
{
"version": "0.3.0",
"messageId": "uuid-v4",
"messageType": "REGULATORY_ACTION",
"timestamp": "ISO-8601",
"sourceChainId": "oraclizer-l3",
"signature": "ed25519-signature",
"regulatoryPayload": {
"actionType": "FREEZE|SEIZE|CONFISCATE|LIQUIDATE|RESTRICT|RECOVER",
"targetAsset": {
"assetId": "bytes32",
"assetType": "ERC20|ERC721|ERC1155|BOND|STOCK",
"currentStateHash": "bytes32"
},
"authority": {
"authorityId": "bytes32",
"authorityType": "NATIONAL|INTERNATIONAL|INDUSTRY|SELF_REGULATORY",
"jurisdiction": ["ISO-3166-alpha-2"],
"legalBasis": {
"documentType": "COURT_ORDER|REGULATORY_DIRECTIVE|EMERGENCY_ORDER",
"documentHash": "bytes32",
"issuedAt": "ISO-8601",
"validUntil": "ISO-8601|null"
},
"priorityLevel": "CRITICAL|HIGH|NORMAL"
},
"actionParameters": { },
"evidence": {
"documentHashes": ["bytes32"],
"witnessSignatures": ["signature"],
"externalReferences": ["uri"]
}
},
"crossChainScope": {
"targetChains": ["chainId"],
"atomicityRequirement": "ALL_OR_NOTHING|GUARANTEED|BEST_EFFORT",
"timeoutSeconds": 300,
"fallbackPolicy": "RETRY|PARTIAL|ABORT"
}
}
Action-Specific Parameter Details
Each regulatory action requires a unique parameter set in the actionParameters field:
FREEZE Parameters
{
"freezeScope": "FULL|PARTIAL",
"exemptOperations": ["VIEW", "DIVIDEND_CLAIM"],
"expirationTime": "ISO-8601|null",
"autoUnfreezeCondition": {
"type": "TIME_BASED|CONDITION_BASED|MANUAL",
"parameters": {}
}
}
Key Design Decision: exemptOperations specifies operations permitted even during freeze. For example, dividend claim rights may be exercisable during a freeze. This is the protocol-level implementation of the “proportionality principle” discussed in our enforceability research.
SEIZE Parameters
{
"custodyAddress": "ERC-3770-address",
"ownershipRetained": true,
"accessRestrictions": {
"allowedOperations": [],
"custodianPermissions": ["VIEW", "TRANSFER_TO_COURT"]
},
"releasePreconditions": {
"type": "COURT_ORDER|APPEAL_PERIOD|SETTLEMENT",
"parameters": {}
}
}
Key Design Decision: ownershipRetained: true specifies that seizure is not ownership deprivation. Legally, ownership of seized assets remains with the original owner; only control is delegated to regulatory authority.
CONFISCATE Parameters
{
"destinationAddress": "ERC-3770-address",
"finalityProof": {
"courtDecision": {
"caseNumber": "string",
"documentHash": "bytes32",
"jurisdiction": "ISO-3166"
},
"appealDeadlinePassed": true,
"appealWaiver": "bytes32|null"
},
"compensationMechanism": {
"type": "NONE|PARTIAL|FULL",
"parameters": {}
}
}
Key Design Decision: finalityProof proves the legal finality of confiscation. If appealDeadlinePassed is false, OSS rejects this message. This mechanism resolves the tension between blockchain’s irreversibility and legal procedure’s reversibility.
LIQUIDATE Parameters
{
"liquidationType": "MARKET_SALE|AUCTION|FIXED_PRICE",
"minimumPrice": {
"amount": "uint256",
"currency": "ERC-3770-address",
"priceOracle": "oracleId"
},
"proceedsDistribution": {
"primaryCreditor": {
"address": "ERC-3770-address",
"percentage": 80
},
"remainderRecipient": {
"address": "ERC-3770-address",
"percentage": 20
}
},
"deadline": "ISO-8601"
}
Key Design Decision: priceOracle references external price oracles for fair market price determination. This directly integrates with Oraclizer’s state synchronization capabilities, ensuring liquidation price fairness.
RESTRICT Parameters
{
"restrictionType": "WHITELIST|BLACKLIST|THRESHOLD|GEOGRAPHIC",
"allowedCounterparties": ["OCID"],
"blockedCounterparties": ["OCID"],
"transactionLimits": {
"perTransaction": "uint256",
"daily": "uint256",
"monthly": "uint256"
},
"conditionExpression": "DSL-expression",
"exceptions": [{
"conditionType": "EMERGENCY|LEGAL_OBLIGATION",
"authorizedBy": "authorityId"
}]
}
Key Design Decision: conditionExpression expresses complex conditions in a domain-specific language (DSL). For example, expressions like "sender.kycLevel >= 2 AND receiver.jurisdiction NOT IN ['XX', 'YY']" are possible.
RECOVER Parameters
{
"originalOwner": {
"ocid": "OCID",
"ownershipProof": {
"type": "TRANSACTION_HISTORY|LEGAL_DOCUMENT|COURT_ORDER",
"documentHash": "bytes32"
}
},
"fraudulentHolder": {
"ocid": "OCID",
"fraudProof": {
"type": "THEFT|SCAM|UNAUTHORIZED_TRANSFER",
"documentHash": "bytes32"
}
},
"recoveryBasis": {
"legalFramework": "string",
"courtOrder": "bytes32"
},
"compensationMechanism": {
"toFraudulentHolder": false,
"toIntermediaries": {
"enabled": true,
"parameters": {}
}
}
}
Key Design Decision: RECOVER, unlike other actions, has the character of “reverting” state. While this appears to conflict with blockchain’s immutability principle, it is justified under the Selective Immutability paradigm explored in our rollback mechanisms research.
OSS Validation Pipeline
Four-Stage Validation Process
The Oracle State Synchronizer (OSS) validates all incoming regulatory action messages through a four-stage pipeline:
Stage 1: Authority Verification
package oss
import (
"context"
"errors"
)
var (
ErrAuthorityNotRegistered = errors.New("AUTHORITY_NOT_REGISTERED")
ErrJurisdictionMismatch = errors.New("JURISDICTION_MISMATCH")
ErrActionNotPermitted = errors.New("ACTION_NOT_PERMITTED")
ErrCriticalPriorityNotAllowed = errors.New("CRITICAL_PRIORITY_NOT_AUTHORIZED")
)
type AuthorityVerificationResult struct {
Verified bool
Authority *RegisteredAuthority
}
func (v *Validator) VerifyAuthority(ctx context.Context, msg *RegulatoryActionMessage) (*AuthorityVerificationResult, error) {
authority := msg.RegulatoryPayload.Authority
// 1. Verify authorityId exists in Registry
registeredAuthority, err := v.authorityRegistry.Get(ctx, authority.AuthorityID)
if err != nil || registeredAuthority == nil {
return nil, ErrAuthorityNotRegistered
}
// 2. Check jurisdiction scope
targetJurisdiction, err := v.getAssetJurisdiction(ctx, msg.RegulatoryPayload.TargetAsset)
if err != nil {
return nil, err
}
if !containsJurisdiction(authority.Jurisdiction, targetJurisdiction) {
return nil, ErrJurisdictionMismatch
}
// 3. Verify permissions for action type
actionPermissions := registeredAuthority.Permissions[authority.AuthorityType]
if !containsAction(actionPermissions, msg.RegulatoryPayload.ActionType) {
return nil, ErrActionNotPermitted
}
// 4. Validate priority level
if authority.PriorityLevel == PriorityCritical && !registeredAuthority.CanIssueCritical {
return nil, ErrCriticalPriorityNotAllowed
}
return &AuthorityVerificationResult{
Verified: true,
Authority: registeredAuthority,
}, nil
}
Stage 2: State Transition Check
package oss
var (
ErrStateHashMismatch = errors.New("STATE_HASH_MISMATCH")
ErrFreezeRequiredBeforeSeize = errors.New("FREEZE_REQUIRED_BEFORE_SEIZE")
ErrSeizeRequiredBeforeConfiscate = errors.New("SEIZE_REQUIRED_BEFORE_CONFISCATE")
ErrInvalidStateTransition = errors.New("INVALID_STATE_TRANSITION")
)
// ValidTransitions defines permitted starting states for each action
var ValidTransitions = map[ActionType][]LockStatus{
ActionFreeze: {StatusAvailable, StatusReserved},
ActionSeize: {StatusRestricted}, // Must be frozen first
ActionConfiscate: {StatusSeized}, // Must be seized first
ActionLiquidate: {StatusAvailable, StatusRestricted, StatusSeized},
ActionRestrict: {StatusAvailable},
ActionRecover: {StatusRestricted, StatusSeized},
}
type StateTransitionResult struct {
Valid bool
CurrentState *AssetState
}
func (v *Validator) CheckStateTransition(ctx context.Context, msg *RegulatoryActionMessage) (*StateTransitionResult, error) {
actionType := msg.RegulatoryPayload.ActionType
targetAsset := msg.RegulatoryPayload.TargetAsset
// Query current state from RWA Registry
currentState, err := v.rwaRegistry.GetState(ctx, targetAsset.AssetID)
if err != nil {
return nil, err
}
// Verify state hash match (concurrency control)
if currentState.StateHash != targetAsset.CurrentStateHash {
return nil, ErrStateHashMismatch
}
// Check valid transition
validFromStates, exists := ValidTransitions[actionType]
if !exists {
return nil, ErrInvalidStateTransition
}
if !containsStatus(validFromStates, currentState.LockStatus) {
// Check escalation requirements
if actionType == ActionSeize && currentState.LockStatus == StatusAvailable {
return nil, ErrFreezeRequiredBeforeSeize
}
if actionType == ActionConfiscate && currentState.LockStatus != StatusSeized {
return nil, ErrSeizeRequiredBeforeConfiscate
}
return nil, ErrInvalidStateTransition
}
return &StateTransitionResult{
Valid: true,
CurrentState: currentState,
}, nil
}
Stage 3: Legal Basis Verification
package oss
import "time"
var (
ErrInvalidLegalDocumentStructure = errors.New("INVALID_LEGAL_DOCUMENT_STRUCTURE")
ErrEvidenceHashInvalid = errors.New("EVIDENCE_HASH_INVALID")
ErrLegalBasisExpired = errors.New("LEGAL_BASIS_EXPIRED_OR_NOT_YET_VALID")
ErrAppealPeriodNotExpired = errors.New("APPEAL_PERIOD_NOT_EXPIRED")
)
type LegalBasisResult struct {
Verified bool
}
func (v *Validator) VerifyLegalBasis(ctx context.Context, msg *RegulatoryActionMessage) (*LegalBasisResult, error) {
legalBasis := msg.RegulatoryPayload.Authority.LegalBasis
evidence := msg.RegulatoryPayload.Evidence
// 1. Validate legal document structure
if !v.isValidLegalDocument(legalBasis) {
return nil, ErrInvalidLegalDocumentStructure
}
// 2. Verify evidence hash integrity
for _, hash := range evidence.DocumentHashes {
verified, err := v.verifyDocumentHash(ctx, hash)
if err != nil || !verified {
return nil, ErrEvidenceHashInvalid
}
}
// 3. Check temporal validity
now := time.Now()
issuedAt := legalBasis.IssuedAt
if now.Before(issuedAt) {
return nil, ErrLegalBasisExpired
}
if legalBasis.ValidUntil != nil && now.After(*legalBasis.ValidUntil) {
return nil, ErrLegalBasisExpired
}
// 4. Additional finality proof verification for confiscation
if msg.RegulatoryPayload.ActionType == ActionConfiscate {
finalityProof := msg.RegulatoryPayload.ActionParameters.(*ConfiscateParams).FinalityProof
if !finalityProof.AppealDeadlinePassed {
return nil, ErrAppealPeriodNotExpired
}
}
return &LegalBasisResult{Verified: true}, nil
}
Stage 4: Cross-chain Consistency Check
package oss
import "sync"
var (
ErrCrossChainStateConflict = errors.New("CROSS_CHAIN_STATE_CONFLICT")
ErrAtomicCommitNotSupported = errors.New("ATOMIC_COMMIT_NOT_SUPPORTED")
)
type CrossChainConsistencyResult struct {
Consistent bool
ChainStates map[string]*AssetState
}
func (v *Validator) CheckCrossChainConsistency(ctx context.Context, msg *RegulatoryActionMessage) (*CrossChainConsistencyResult, error) {
crossChainScope := msg.CrossChainScope
targetAsset := msg.RegulatoryPayload.TargetAsset
// 1. Query current states from target chains (parallel)
chainStates := make(map[string]*AssetState)
var mu sync.Mutex
var wg sync.WaitGroup
errChan := make(chan error, len(crossChainScope.TargetChains))
for _, chainID := range crossChainScope.TargetChains {
wg.Add(1)
go func(cid string) {
defer wg.Done()
state, err := v.crossChainBridge.QueryState(ctx, cid, targetAsset.AssetID)
if err != nil {
errChan <- err
return
}
mu.Lock()
chainStates[cid] = state
mu.Unlock()
}(chainID)
}
wg.Wait()
close(errChan)
if err := <-errChan; err != nil {
return nil, err
}
// 2. Detect state conflicts
stateConflicts := v.detectStateConflicts(chainStates)
if len(stateConflicts) > 0 {
resolved, err := v.attemptConflictResolution(ctx, stateConflicts)
if err != nil || !resolved {
return nil, ErrCrossChainStateConflict
}
}
// 3. Verify atomicity feasibility
if crossChainScope.AtomicityRequirement == AtomicityAllOrNothing {
for _, chainID := range crossChainScope.TargetChains {
bridgeStatus, err := v.crossChainBridge.GetStatus(ctx, chainID)
if err != nil {
return nil, err
}
if !bridgeStatus.SupportsAtomicCommit {
return nil, fmt.Errorf("%w: chainId=%s", ErrAtomicCommitNotSupported, chainID)
}
}
}
// 4. Verify execution feasibility within timeout
estimatedTime := v.estimateExecutionTime(crossChainScope.TargetChains)
if estimatedTime > time.Duration(crossChainScope.TimeoutSeconds)*time.Second*8/10 {
v.logger.Warn("Execution time may exceed timeout",
"estimatedTime", estimatedTime,
"timeout", crossChainScope.TimeoutSeconds)
}
return &CrossChainConsistencyResult{
Consistent: true,
ChainStates: chainStates,
}, nil
}
D-quencer Priority Handling
Multi-Priority Queue Architecture
D-quencer processes regular transactions and regulatory actions distinctly. On top of the D-quencer consensus algorithm detailed in our core component documentation, a regulatory-specific priority system is added:
package dquencer
import (
"container/heap"
"sync"
)
type PriorityLevel int
const (
PriorityCritical PriorityLevel = iota // P0: Emergency regulatory actions
PriorityRegulatory // P1: Standard regulatory actions
PriorityHigh // P2: High priority regular transactions
PriorityNormal // P3: Normal transactions
PriorityLow // P4: Low priority
)
type RegulatoryPriorityQueue struct {
queues map[PriorityLevel]*MaxHeap
regulatoryTxPerBlock int
mu sync.RWMutex
}
func NewRegulatoryPriorityQueue() *RegulatoryPriorityQueue {
rpq := &RegulatoryPriorityQueue{
queues: make(map[PriorityLevel]*MaxHeap),
regulatoryTxPerBlock: 20,
}
for _, level := range []PriorityLevel{
PriorityCritical, PriorityRegulatory, PriorityHigh, PriorityNormal, PriorityLow,
} {
rpq.queues[level] = NewMaxHeap()
}
return rpq
}
func (rpq *RegulatoryPriorityQueue) Enqueue(tx *Transaction) {
rpq.mu.Lock()
defer rpq.mu.Unlock()
priority := rpq.determinePriority(tx)
heap.Push(rpq.queues[priority], &HeapItem{
Value: tx,
Priority: tx.Timestamp.UnixNano(),
})
}
func (rpq *RegulatoryPriorityQueue) determinePriority(tx *Transaction) PriorityLevel {
if tx.MessageType != MessageTypeRegulatoryAction {
if tx.PriorityHint != nil {
return *tx.PriorityHint
}
return PriorityNormal
}
authority := tx.RegulatoryPayload.Authority
// CRITICAL: Emergency freeze, seize, confiscate
if authority.PriorityLevel == "CRITICAL" ||
authority.LegalBasis.DocumentType == DocumentTypeEmergencyOrder {
return PriorityCritical
}
// REGULATORY: Standard regulatory actions
return PriorityRegulatory
}
func (rpq *RegulatoryPriorityQueue) DequeueForBlock(blockCapacity int) []*Transaction {
rpq.mu.Lock()
defer rpq.mu.Unlock()
selected := make([]*Transaction, 0, blockCapacity)
regulatoryCount := 0
// CRITICAL always processed first
for rpq.queues[PriorityCritical].Len() > 0 && len(selected) < blockCapacity {
item := heap.Pop(rpq.queues[PriorityCritical]).(*HeapItem)
selected = append(selected, item.Value.(*Transaction))
regulatoryCount++
}
// REGULATORY subject to per-block limit
for rpq.queues[PriorityRegulatory].Len() > 0 &&
regulatoryCount < rpq.regulatoryTxPerBlock &&
len(selected) < blockCapacity {
item := heap.Pop(rpq.queues[PriorityRegulatory]).(*HeapItem)
selected = append(selected, item.Value.(*Transaction))
regulatoryCount++
}
// Fill remaining capacity with regular transactions
for _, priority := range []PriorityLevel{PriorityHigh, PriorityNormal, PriorityLow} {
for rpq.queues[priority].Len() > 0 && len(selected) < blockCapacity {
item := heap.Pop(rpq.queues[priority]).(*HeapItem)
selected = append(selected, item.Value.(*Transaction))
}
}
return selected
}
Scheduled Regulatory Action Processing
Some regulatory actions require scheduled execution rather than immediate execution. For example, when a court order takes effect on a specific date:
package dquencer
import (
"context"
"time"
)
type ScheduledActionStatus string
const (
StatusPending ScheduledActionStatus = "PENDING"
StatusExecuted ScheduledActionStatus = "EXECUTED"
StatusFailed ScheduledActionStatus = "FAILED"
)
type ScheduledAction struct {
ID string
Message *RegulatoryActionMessage
ExecutionTime time.Time
Status ScheduledActionStatus
RetryPolicy RetryPolicy
RetryCount int
}
type RetryPolicy struct {
MaxRetries int
RetryInterval time.Duration
}
type ScheduledRegulatoryActionManager struct {
dquencer *DQuencer
scheduledActions *TimerQueue
notifier Notifier
}
func NewScheduledManager(dq *DQuencer, notifier Notifier) *ScheduledRegulatoryActionManager {
return &ScheduledRegulatoryActionManager{
dquencer: dq,
scheduledActions: NewTimerQueue(),
notifier: notifier,
}
}
func (m *ScheduledRegulatoryActionManager) ScheduleAction(
msg *RegulatoryActionMessage,
executionTime time.Time,
) (string, error) {
scheduledAction := &ScheduledAction{
ID: generateID(),
Message: msg,
ExecutionTime: executionTime,
Status: StatusPending,
RetryPolicy: RetryPolicy{
MaxRetries: 3,
RetryInterval: time.Minute,
},
}
m.scheduledActions.Insert(scheduledAction, executionTime)
m.setExecutionTimer(scheduledAction)
return scheduledAction.ID, nil
}
func (m *ScheduledRegulatoryActionManager) executeScheduledAction(
ctx context.Context,
action *ScheduledAction,
) {
// Re-validate preconditions at execution time
if err := m.validatePreconditions(ctx, action.Message); err != nil {
if action.RetryCount < action.RetryPolicy.MaxRetries {
action.RetryCount++
time.AfterFunc(action.RetryPolicy.RetryInterval, func() {
m.executeScheduledAction(ctx, action)
})
return
}
action.Status = StatusFailed
m.notifier.NotifyExecutionFailure(action, err)
return
}
// Inject into D-quencer with CRITICAL priority
m.dquencer.InjectRegulatoryAction(action.Message, PriorityCritical)
action.Status = StatusExecuted
}
Cross-chain Broadcast Protocol
Three-Phase Atomic Execution
Cross-chain regulatory actions render partial execution legally meaningless. For example, when seizing assets distributed across four chains, success on only three chains fails to achieve the regulatory objective.
Phase 1: PREPARE
package crosschain
import (
"context"
"sync"
"time"
)
type PrepareStatus string
const (
PrepareReady PrepareStatus = "READY"
PrepareFailed PrepareStatus = "PREPARE_FAILED"
)
type PrepareResult struct {
ChainID string
Status PrepareStatus
ReservationID string
Error string
}
func (b *Broadcaster) PreparePhase(
ctx context.Context,
msg *RegulatoryActionMessage,
) ([]PrepareResult, error) {
crossChainScope := msg.CrossChainScope
regulatoryPayload := msg.RegulatoryPayload
results := make([]PrepareResult, 0, len(crossChainScope.TargetChains))
var mu sync.Mutex
var wg sync.WaitGroup
for _, chainID := range crossChainScope.TargetChains {
wg.Add(1)
go func(cid string) {
defer wg.Done()
result, err := b.bridge.SendPrepare(ctx, cid, &PrepareRequest{
ActionType: regulatoryPayload.ActionType,
TargetAsset: regulatoryPayload.TargetAsset,
StateReservation: StateReservation{
LockUntil: time.Now().Add(time.Duration(crossChainScope.TimeoutSeconds) * time.Second),
ReservationID: generateReservationID(),
},
})
mu.Lock()
defer mu.Unlock()
if err != nil {
results = append(results, PrepareResult{
ChainID: cid,
Status: PrepareFailed,
Error: err.Error(),
})
return
}
results = append(results, PrepareResult{
ChainID: cid,
Status: PrepareReady,
ReservationID: result.ReservationID,
})
}(chainID)
}
wg.Wait()
// Check quorum
readyCount := 0
for _, r := range results {
if r.Status == PrepareReady {
readyCount++
}
}
if crossChainScope.AtomicityRequirement == AtomicityAllOrNothing &&
readyCount != len(crossChainScope.TargetChains) {
// Cancel all reservations
if err := b.rollbackPrepare(ctx, results); err != nil {
b.logger.Error("Failed to rollback prepare", "error", err)
}
return nil, ErrPreparePhasesFailed
}
return results, nil
}
Phase 2: COMMIT
package crosschain
type CommitStatus string
const (
CommitCommitted CommitStatus = "COMMITTED"
CommitFailed CommitStatus = "COMMIT_FAILED"
)
type CommitResult struct {
ChainID string
Status CommitStatus
TxHash string
BlockNumber uint64
Error string
}
func (b *Broadcaster) CommitPhase(
ctx context.Context,
prepareResults []PrepareResult,
msg *RegulatoryActionMessage,
) ([]CommitResult, error) {
crossChainScope := msg.CrossChainScope
regulatoryPayload := msg.RegulatoryPayload
// Filter only READY chains
readyChains := make([]PrepareResult, 0)
for _, r := range prepareResults {
if r.Status == PrepareReady {
readyChains = append(readyChains, r)
}
}
commitResults := make([]CommitResult, 0, len(readyChains))
var mu sync.Mutex
var wg sync.WaitGroup
for _, prepared := range readyChains {
wg.Add(1)
go func(p PrepareResult) {
defer wg.Done()
signature, _ := b.signCommitMessage(p.ChainID, regulatoryPayload)
result, err := b.bridge.SendCommit(ctx, p.ChainID, &CommitRequest{
ReservationID: p.ReservationID,
RegulatoryPayload: regulatoryPayload,
Signature: signature,
})
mu.Lock()
defer mu.Unlock()
if err != nil {
commitResults = append(commitResults, CommitResult{
ChainID: p.ChainID,
Status: CommitFailed,
Error: err.Error(),
})
return
}
commitResults = append(commitResults, CommitResult{
ChainID: p.ChainID,
Status: CommitCommitted,
TxHash: result.TxHash,
BlockNumber: result.BlockNumber,
})
}(prepared)
}
wg.Wait()
// Handle failures based on atomicity level
failedCommits := make([]CommitResult, 0)
for _, r := range commitResults {
if r.Status == CommitFailed {
failedCommits = append(failedCommits, r)
}
}
if len(failedCommits) > 0 {
return b.handleCommitFailures(ctx, commitResults, crossChainScope.AtomicityRequirement, msg)
}
return commitResults, nil
}
func (b *Broadcaster) handleCommitFailures(
ctx context.Context,
commitResults []CommitResult,
atomicityLevel AtomicityRequirement,
msg *RegulatoryActionMessage,
) ([]CommitResult, error) {
switch atomicityLevel {
case AtomicityBestEffort:
// Keep successful chains, log failures
succeeded := make([]CommitResult, 0)
failed := make([]CommitResult, 0)
for _, r := range commitResults {
if r.Status == CommitCommitted {
succeeded = append(succeeded, r)
} else {
failed = append(failed, r)
}
}
b.logger.Warn("Partial commit success",
"succeeded", len(succeeded),
"failed", len(failed))
return commitResults, nil
case AtomicityGuaranteed:
// Retry failed chains with exponential backoff
for _, failed := range commitResults {
if failed.Status == CommitFailed {
go b.retryWithBackoff(ctx, failed.ChainID, msg, RetryConfig{
MaxRetries: 5,
InitialDelay: time.Second,
MaxDelay: 30 * time.Second,
})
}
}
return commitResults, nil
case AtomicityAllOrNothing:
// Rollback all chains
successfulCommits := make([]CommitResult, 0)
for _, r := range commitResults {
if r.Status == CommitCommitted {
successfulCommits = append(successfulCommits, r)
}
}
if err := b.rollbackCommits(ctx, successfulCommits); err != nil {
b.logger.Error("Rollback failed", "error", err)
}
return nil, ErrAtomicCommitFailed
}
return commitResults, nil
}
Phase 3: FINALIZE
package crosschain
type FinalizeResult struct {
Status string
AggregateProof *CrossChainProof
RegistryUpdate *RegistryUpdateResult
}
func (b *Broadcaster) FinalizePhase(
ctx context.Context,
commitResults []CommitResult,
msg *RegulatoryActionMessage,
) (*FinalizeResult, error) {
// 1. Generate aggregate cross-chain proof
aggregateProof, err := b.generateCrossChainProof(commitResults)
if err != nil {
return nil, fmt.Errorf("failed to generate proof: %w", err)
}
// 2. Update RWA Registry on origin chain (Oraclizer L3)
chainIDs := make([]string, 0, len(commitResults))
txHashes := make([]string, 0, len(commitResults))
for _, r := range commitResults {
chainIDs = append(chainIDs, r.ChainID)
txHashes = append(txHashes, r.TxHash)
}
registryUpdate, err := b.rwaRegistry.UpdateState(ctx, &RegistryUpdateRequest{
AssetID: msg.RegulatoryPayload.TargetAsset.AssetID,
NewState: deriveNewState(msg.RegulatoryPayload.ActionType),
CrossChainProof: aggregateProof,
ExecutionDetails: ExecutionDetails{
Timestamp: time.Now(),
AffectedChains: chainIDs,
TransactionHashes: txHashes,
},
})
if err != nil {
return nil, fmt.Errorf("failed to update registry: %w", err)
}
// 3. Emit event
b.eventEmitter.Emit("REGULATORY_ACTION_FINALIZED", map[string]interface{}{
"actionId": msg.MessageID,
"actionType": msg.RegulatoryPayload.ActionType,
"targetAsset": msg.RegulatoryPayload.TargetAsset.AssetID,
"authority": msg.RegulatoryPayload.Authority.AuthorityID,
"affectedChains": len(commitResults),
"aggregateProofHash": aggregateProof.Hash,
"registryUpdateTx": registryUpdate.TxHash,
})
return &FinalizeResult{
Status: "FINALIZED",
AggregateProof: aggregateProof,
RegistryUpdate: registryUpdate,
}, nil
}
DeFi Protocol Integration Guide
Regulatory Event Subscription API
DeFi protocol developers can subscribe to Oraclizer’s regulatory events for automatic response:
package integration
import (
"context"
"log"
oraclizer "github.com/oraclizer/sdk-go"
)
func SetupRegulatoryEventSubscription(ctx context.Context) error {
// Initialize Oraclizer client
client, err := oraclizer.NewClient(oraclizer.Config{
Endpoint: "wss://api.oraclizer.io/v1",
APIKey: os.Getenv("ORACLIZER_API_KEY"),
})
if err != nil {
return err
}
// Get list of managed assets
managedAssets, err := getProtocolManagedAssets(ctx)
if err != nil {
return err
}
// Subscribe to regulatory events
subscription, err := client.Subscribe(ctx, oraclizer.SubscriptionConfig{
EventType: "REGULATORY_ACTION",
AssetFilter: managedAssets,
ActionTypes: []string{"FREEZE", "SEIZE", "CONFISCATE", "LIQUIDATE"},
})
if err != nil {
return err
}
// Handle events
go func() {
for event := range subscription.Events() {
handleRegulatoryAction(ctx, event)
}
}()
return nil
}
func handleRegulatoryAction(ctx context.Context, event *oraclizer.RegulatoryEvent) {
actionType := event.ActionType
targetAsset := event.TargetAsset
switch actionType {
case "FREEZE":
// Exclude from collateral valuation
if err := collateralManager.MarkAsFrozen(ctx, targetAsset.AssetID); err != nil {
log.Printf("Failed to mark asset as frozen: %v", err)
}
// Suspend liquidation for positions based on this collateral
if err := liquidationEngine.SuspendForAsset(ctx, targetAsset.AssetID); err != nil {
log.Printf("Failed to suspend liquidation: %v", err)
}
case "SEIZE":
// Fully exclude from collateral
if err := collateralManager.RemoveFromCollateral(ctx, targetAsset.AssetID); err != nil {
log.Printf("Failed to remove from collateral: %v", err)
}
// Initiate forced liquidation for related positions
if err := liquidationEngine.InitiateForAsset(ctx, targetAsset.AssetID); err != nil {
log.Printf("Failed to initiate liquidation: %v", err)
}
case "LIQUIDATE":
// Coordinate protocol liquidation with regulatory liquidation
if err := coordinateWithRegulatoryLiquidation(ctx, event); err != nil {
log.Printf("Failed to coordinate liquidation: %v", err)
}
}
}
Regulatory Status Query API
package integration
// Query current regulatory status of an asset
func QueryAssetRegulatoryStatus(ctx context.Context, client *oraclizer.Client, assetID string) (*RegulatoryStatus, error) {
status, err := client.GetAssetRegulatoryStatus(ctx, oraclizer.StatusQuery{
AssetID: assetID,
IncludeHistory: true,
CrossChainScope: []string{"ethereum", "arbitrum", "optimism"},
})
if err != nil {
return nil, err
}
return status, nil
}
// Response structure example:
// {
// AssetID: "0x742d35...",
// CurrentStatus: {
// LockStatus: "RESTRICTED",
// ActiveActions: [{
// ActionType: "FREEZE",
// Authority: "SEC",
// Since: "2024-03-15T10:30:00Z",
// ExpiresAt: nil,
// ExemptOperations: ["VIEW"],
// }],
// LastUpdated: "2024-03-15T10:30:05Z",
// },
// CrossChainStatus: {
// "ethereum": {Synced: true, Status: "RESTRICTED"},
// "arbitrum": {Synced: true, Status: "RESTRICTED"},
// "optimism": {Synced: true, Status: "RESTRICTED"},
// },
// History: [/* Past regulatory action history */],
// }
Important Note: Even if a DeFi protocol does not respond to regulatory events, transfers of the asset are already blocked at the Oraclizer L3 level. However, protocol-level measures (such as excluding from collateral valuation) must be explicitly implemented by each protocol.
Conclusion: Complete Protocolization of Enforceability
In this research, we transformed the philosophical foundation of enforceability into actually implementable protocol specification.
For each of the six regulatory actions:
- OIP message formats were defined to clearly encode regulatory intent
- The OSS validation pipeline systematically validates authority, state, legal basis, and cross-chain consistency
- The D-quencer priority system guarantees emergency regulatory actions are processed without delay
- Three-phase cross-chain broadcast technically prevents the legal meaninglessness of partial execution
Combined with our asset state management framework, Oraclizer now possesses both state definition (what) and state modification (how).
“When code enforces law, that code must reflect the procedural legitimacy of law. No CONFISCATE without SEIZE, no SEIZE without FREEZE. This is due process implemented as protocol.”
In upcoming research, we will explore cross-chain address systems and ERC-3770 integration, examining how standardized chain-specific address formats enable seamless regulatory action execution across heterogeneous blockchain environments.
References
- Ethereum Improvement Proposals. (2021). EIP-3770: Chain-specific addresses. https://eips.ethereum.org/EIPS/eip-3770
- Financial Stability Board. (2023). Global Regulatory Framework for Crypto-asset Activities. https://www.fsb.org/2023/07/high-level-recommendations-for-the-regulation-supervision-and-oversight-of-crypto-asset-activities-and-markets-final-report/
- FATF. (2021). Updated Guidance for a Risk-Based Approach for Virtual Assets and Virtual Asset Service Providers. https://www.fatf-gafi.org/en/publications/Fatfrecommendations/Guidance-rba-virtual-assets-2021.html





