Skip to main content

Transfer Restrictions

The Security Token implements a sophisticated two-layer transfer restriction system that combines multi-type token support with identity-based compliance rules. This system replaces traditional transfer groups with a more flexible approach based on token types and investor identities.

Architecture Overview

Transfer restrictions are enforced through the integrated TransferRules.sol contract, which works closely with IdentityRegistry.sol to provide comprehensive compliance controls:

Two-Layer Rule System

Layer 1: Token Type Assignment Rules

Automatically assigns token types based on investor identity:

// Configure US Accredited investors to receive RegD tokens
transferRules.setTokenTypeRule(
840, // region: United States
2, // accreditation: Accredited
2, // tokenType: RegD
true, // requiresAmlKyc
true // isActive
);

Layer 2: Transfer Restriction Rules

Define holding periods and compliance requirements per token type:

// Configure 6-month holding period for RegD tokens
transferRules.setTransferRule(
2, // tokenType: RegD
840, // recipientRegion: US
0, // recipientAccreditation: Any
TransferRule({
lockDurationSeconds: 180 days,
requiresAmlKyc: true,
isActive: true
})
);

Transfer Validation Process

Here's how transfer restrictions are validated in the current system:

Comprehensive Transfer Rule Configuration

The system supports complex regulatory scenarios through flexible rule configuration:

1. Token Type Assignment Examples

// US Retail Investors → RegCF tokens
transferRules.setTokenTypeRule(840, 1, 3, true, true); // US, Retail, RegCF, AML/KYC required, Active

// US Accredited Investors → RegD tokens
transferRules.setTokenTypeRule(840, 2, 2, true, true); // US, Accredited, RegD, AML/KYC required, Active

// Non-US Qualified Investors → RegS tokens
transferRules.setTokenTypeRule(826, 3, 1, true, true); // UK, Qualified, RegS, AML/KYC required, Active

// Institutional Investors → Custom tokens
transferRules.setTokenTypeRule(0, 4, 4, true, true); // Any region, Institutional, Custom, AML/KYC required, Active

2. Transfer Restriction Examples

// RegS 1-year holding period (offshore to any)
transferRules.setTransferRule(1, 0, 0, TransferRule({
lockDurationSeconds: 365 days,
requiresAmlKyc: true,
isActive: true
}));

// RegD 6-month holding period (US accredited to any)
transferRules.setTransferRule(2, 0, 0, TransferRule({
lockDurationSeconds: 180 days,
requiresAmlKyc: true,
isActive: true
}));

// RegCF restrictions (retail to accredited only)
transferRules.setTransferRule(3, 840, 2, TransferRule({
lockDurationSeconds: 0, // No holding period
requiresAmlKyc: true,
isActive: true
}));

Practical Configuration Process

Step 1: Identity Management

// Register investor identity
uint256[] memory regions = new uint256[](1);
regions[0] = 840; // United States

IdentityInfo memory identity = IdentityInfo({
regions: regions,
accreditationType: 2, // Accredited
lastAmlKycChangeTimestamp: 0, // Use current timestamp
lastAccreditationChangeTimestamp: 0,
amlKycPassed: true
});

identityRegistry.setIdentity(investorAddress, identity);

Step 2: Rule Configuration

// Set token type rules for automatic assignment
transferRules.setTokenTypeRule(840, 2, 2, true, true); // US Accredited → RegD, Active

// Set transfer restrictions for RegD tokens
transferRules.setTransferRule(2, 0, 0, TransferRule({
lockDurationSeconds: 180 days,
requiresAmlKyc: true,
isActive: true
}));

Step 3: Token Operations

// Mint tokens (type automatically determined via rules)
token.mint(investorAddress, 1000 * 10**decimals);

// Or mint specific type
token.mintTokenType(investorAddress, 1000 * 10**decimals, 2); // RegD

Advanced Transfer Scenarios

Multi-Jurisdiction Compliance

// Investor with dual citizenship (US + UK)
uint256[] memory dualRegions = new uint256[](2);
dualRegions[0] = 840; // US
dualRegions[1] = 826; // UK

// Configure rules for both jurisdictions
transferRules.setTokenTypeRule(840, 2, 2, true, true); // US Accredited → RegD, Active
transferRules.setTokenTypeRule(826, 3, 1, true, true); // UK Qualified → RegS, Active

Time-Based Restrictions

// Different holding periods for different recipient types
transferRules.setTransferRule(2, 840, 2, TransferRule({
lockDurationSeconds: 90 days, // 3 months to US accredited
requiresAmlKyc: true,
isActive: true
}));

transferRules.setTransferRule(2, 0, 1, TransferRule({
lockDurationSeconds: 180 days, // 6 months to retail investors
requiresAmlKyc: true,
isActive: true
}));

Error Codes and Restriction Messages

The system provides detailed error codes for different restriction scenarios:

CodeRestriction TypeDescription
0SUCCESSTransfer allowed
1SENDER_NOT_AMLKYCPASSEDSender failed AML/KYC verification
2RECIPIENT_NOT_AMLKYCPASSEDRecipient failed AML/KYC verification
3HOLDING_PERIOD_NOT_METToken holding period requirement not satisfied
4RECIPIENT_NOT_ELIGIBLERecipient not eligible for this token type
5TRANSFER_RULE_NOT_FOUNDNo applicable transfer rule configured

Administrative Functions

FunctionDescriptionAccess Control
setTokenTypeRule(region, accreditation, tokenType, requiresAmlKyc, isActive)Configure automatic token type assignmentTransfer Admin
batchSetTokenTypeRules(regions[], accreditations[], tokenTypes[], requiresAmlKycFlags[], isActiveFlags[])Configure multiple token type rules in batchTransfer Admin
setDefaultTokenTypeRule(tokenType, requiresAmlKyc, isActive)Set a global fallback token type when no specific rule matchesTransfer Admin
resetDefaultTokenTypeRule()Reset the default rule to inactive GENERICTransfer Admin
defaultTokenTypeRule()Get the current default rule configurationAnyone (view)
setTransferRule(tokenType, recipientRegion, recipientAccreditation, rule)Set transfer restrictions for token typesTransfer Admin
updateTransferRule(ruleId, rule)Update existing transfer ruleTransfer Admin
deactivateTransferRule(ruleId)Temporarily disable a transfer ruleTransfer Admin
checkTransferAllowed(tokenType, mintTimestamp, recipient, identityRegistry)Query if transfer would be allowedAnyone (view)

Batch Configuration

For efficiency when setting up multiple rules, use the batch function:

// Configure multiple token type rules in one transaction
uint256[] memory regions = new uint256[](3);
regions[0] = 840; // US
regions[1] = 826; // UK
regions[2] = 392; // Japan

uint256[] memory accreditations = new uint256[](3);
accreditations[0] = 2; // Accredited
accreditations[1] = 3; // Qualified
accreditations[2] = 3; // Qualified

uint256[] memory tokenTypes = new uint256[](3);
tokenTypes[0] = 2; // RegD
tokenTypes[1] = 1; // RegS
tokenTypes[2] = 1; // RegS

bool[] memory requiresAmlKycFlags = new bool[](3);
requiresAmlKycFlags[0] = true;
requiresAmlKycFlags[1] = true;
requiresAmlKycFlags[2] = true;

bool[] memory isActiveFlags = new bool[](3);
isActiveFlags[0] = true;
isActiveFlags[1] = true;
isActiveFlags[2] = true;

transferRules.batchSetTokenTypeRules(
regions,
accreditations,
tokenTypes,
requiresAmlKycFlags,
isActiveFlags
);

This modern transfer restriction system provides regulatory compliance while maintaining the flexibility needed for complex international securities offerings.