Skip to main content

Transfer Rules

Overview

The TransferRules contract manages token type determination and transfer restrictions for the RestrictedLockupToken. It implements a two-layer approach to regulatory compliance through configurable rules managed by the Transfer Admin.

Architecture

The TransferRules contract provides two main functionalities:

  1. Token Type Rules - Determine token type based on investor identity
  2. Transfer Rules - Control transfer restrictions based on token type and recipient identity

Usage

Token Type Rules

Token Type Rules map investor identity (region + accreditation) to appropriate token types during minting.

Data Structure

struct TokenTypeRule {
uint256 tokenType; // Token type to assign (1=RegS, 2=RegD, etc.)
bool requiresAmlKyc; // Whether AML/KYC is required for this type
bool isActive; // Whether this rule is currently active
}

Configuration

// Set a single rule
transferRules.setTokenTypeRule(
840, // region (US)
2, // accreditation (Accredited)
2, // tokenType (RegD)
true, // requiresAmlKyc
true // isActive
);

// Get a configured rule
TokenTypeRule memory rule = transferRules.getTokenTypeRule(840, 2);

// Batch set multiple rules
transferRules.batchSetTokenTypeRules(
[840, 0], // regions
[2, 0], // accreditations
[2, 1], // tokenTypes
[true, true], // requiresAmlKyc flags
[true, true] // isActive flags
);

// Remove a rule
transferRules.removeTokenTypeRule(840, 2);

Automatic Type Determination

// Called by RestrictedLockupToken during minting
uint256 tokenType = transferRules.determineTokenType(
walletAddress,
identityRegistry
);

Example Rules for US Exempt Offerings

RegionAccreditationToken TypeAML/KYC RequiredDescription
840 (US)2 (Accredited)2 (RegD)YesUS Accredited → RegD
0 (Any)0 (Any)1 (RegS)YesDefault → RegS
840 (US)1 (Retail)3 (RegCF)YesUS Retail → RegCF

Transfer Rules Configuration

Transfer Rules define restrictions for transferring tokens based on token type, mint timestamp, and recipient identity.

Transfer Rule Data Structure

struct TransferRule {
uint256 lockDurationSeconds; // Holding period from mint timestamp
bool requiresAmlKyc; // Whether recipient must have AML/KYC
bool isActive; // Whether this rule is currently active
}

Transfer Rule Configuration

// Set a transfer rule
transferRules.setTransferRule(
2, // tokenType (RegD)
840, // recipientRegion (US)
0, // recipientAccreditation (Any)
TransferRule({
lockDurationSeconds: 180 days,
requiresAmlKyc: true,
isActive: true
})
);

// Get a transfer rule
TransferRule memory rule = transferRules.transferRuleFor(2, 840, 0);

// Batch set multiple rules
transferRules.batchSetTransferRules(
[2, 1], // tokenTypes
[840, 0], // recipientRegions
[0, 0], // recipientAccreditations
[rule1, rule2] // TransferRule structs
);

// Remove a rule
transferRules.removeTransferRule(2, 840, 0);

Transfer Validation Usage

// Called by RestrictedLockupToken during transfers
uint8 restrictionCode = transferRules.detectTransferRestriction(
tokenAddress,
senderAddress,
recipientAddress,
transferAmount
);

// Get unlock timestamp for a holding
uint256 unlockTime = transferRules.getUnlockTimestamp(
tokenType,
mintTimestamp,
recipientAddress,
identityRegistry
);

Example Transfer Rules for US Exempt Offerings

Token TypeRecipient RegionRecipient AccreditationLock DurationAML/KYCDescription
2 (RegD)840 (US)0 (Any)180 daysYesRegD → US: 6 months
1 (RegS)0 (Any)0 (Any)365 daysYesRegS → Any: 12 months
4 (Institutional)0 (Any)4 (Institutional)0 daysYesInstitutional → Institutional: No hold

Process Flows

Token Minting Flow

Transfer Validation Flow

Validation Logic

Token Type Determination

When determineTokenType() is called:

  1. Get Identity: Retrieve investor's region and accreditation from IdentityRegistry
  2. Find Rule: Look up TokenTypeRule for (region, accreditation) combination
  3. Return Type:
    • If rule found and active: return rule.tokenType
    • If no rule found: return TOKEN_TYPE_GENERIC (0)

Transfer Validation Logic

When checkTransferAllowed() is called:

  1. Get Recipient Identity: Retrieve recipient's region, accreditation, and AML/KYC status
  2. Find Transfer Rule: Look up TransferRule for (tokenType, recipientRegion, recipientAccreditation)
  3. Check Conditions:
    • Rule exists and is active
    • Holding period satisfied: mintTimestamp + lockDurationSeconds <= block.timestamp
    • AML/KYC requirement met (if required)
  4. Return Result:
    • SUCCESS (0): All conditions met
    • NO_RULE_FOR_RECIPIENT (13): No matching rule found
    • HOLDING_PERIOD_NOT_MET (12): Lock duration not elapsed
    • RECIPIENT_NOT_QUALIFIED (14): AML/KYC requirement not met

Administrative Functions

Access Control

  • Transfer Admin: Can configure all rules (token type and transfer rules) via external AccessControl
  • Contract Admin: Can upgrade the TransferRules contract via external AccessControl

Key Functions

// Token Type Rules
function setTokenTypeRule(uint256 region, uint256 accreditation, uint256 tokenType, bool requiresAmlKyc) external onlyTransferAdmin;
function removeTokenTypeRule(uint256 region, uint256 accreditation) external onlyTransferAdmin;
function batchSetTokenTypeRules(uint256[] regions, uint256[] accreditations, uint256[] tokenTypes, bool[] requiresAmlKycFlags) external onlyTransferAdmin;

// Transfer Rules
function setTransferRule(uint256 tokenType, uint256 recipientRegion, uint256 recipientAccreditation, TransferRule memory rule) external onlyTransferAdmin;
function removeTransferRule(uint256 tokenType, uint256 recipientRegion, uint256 recipientAccreditation) external onlyTransferAdmin;
function batchSetTransferRules(uint256[] tokenTypes, uint256[] recipientRegions, uint256[] recipientAccreditations, TransferRule[] rules) external onlyTransferAdmin;

// View Functions
function getTokenTypeRule(uint256 region, uint256 accreditation) external view returns (TokenTypeRule memory);
function transferRuleFor(uint256 tokenType, uint256 recipientRegion, uint256 recipientAccreditation) external view returns (TransferRule memory);

Error Handling

Common Restriction Codes

  1. SUCCESS (0): Transfer allowed
  2. HOLDING_PERIOD_NOT_MET (12): Required holding period not elapsed
  3. NO_RULE_FOR_RECIPIENT (13): No transfer rule defined for combination
  4. RECIPIENT_NOT_QUALIFIED (14): AML/KYC requirement not met

Troubleshooting

  • No rule found: Verify rules are configured for the specific combination
  • Holding period: Check mintTimestamp + lockDurationSeconds vs current time
  • AML/KYC issues: Confirm recipient's AML/KYC status in IdentityRegistry
  • Rule inactive: Ensure rules have isActive = true

Integration

With RestrictedLockupToken

  • Token calls determineTokenType() during minting
  • Token calls checkTransferAllowed() during transfers
  • Token respects restriction codes and blocks invalid transfers

With IdentityRegistry

  • TransferRules queries recipient identity for validation
  • Supports region, accreditation, and AML/KYC status checks
  • Works with configurable AML/KYC validity periods

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, // Contract will use block.timestamp
lastAccreditationChangeTimestamp: 0, // Contract will use block.timestamp
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**18); // 1000 tokens

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

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

// Configure different holding periods for different token types
transferRules.setTransferRule(1, 0, 0, TransferRule({
lockDurationSeconds: 365 days, // RegS: 1 year hold
requiresAmlKyc: true,
isActive: true
}));

transferRules.setTransferRule(2, 840, 0, TransferRule({
lockDurationSeconds: 180 days, // RegD to US: 6 months
requiresAmlKyc: true,
isActive: true
}));

transferRules.setTransferRule(4, 0, 4, TransferRule({
lockDurationSeconds: 0, // Institutional to Institutional: No hold
requiresAmlKyc: true,
isActive: true
}));

API Reference

Constructor

constructor(address trustedForwarder_, address accessControl_)

Initializes the TransferRules contract with ERC-2771 meta-transaction support and access control integration.

Parameters:

  • trustedForwarder_ (address): Address of the trusted forwarder for meta-transactions
  • accessControl_ (address): Address of the AccessControl contract for role management

Requirements:

  • accessControl_ cannot be the zero address

Emits:

  • None

Errors:

  • TransferRules_InvalidAccessControl(): When accessControl_ is the zero address

Constants

Restriction Codes

SUCCESS() → uint8

Returns the success code (0) indicating no transfer restrictions.

GREATER_THAN_RECIPIENT_MAX_BALANCE() → uint8

Returns restriction code 1 for exceeding recipient maximum balance.

SENDER_TOKENS_TIME_LOCKED() → uint8

Returns restriction code 2 for sender tokens being time-locked.

DO_NOT_SEND_TO_TOKEN_CONTRACT() → uint8

Returns restriction code 3 for attempting to send tokens to the token contract itself.

DO_NOT_SEND_TO_EMPTY_ADDRESS() → uint8

Returns restriction code 4 for attempting to send tokens to the zero address.

SENDER_ADDRESS_FROZEN() → uint8

Returns restriction code 5 for sender address being frozen.

ALL_TRANSFERS_PAUSED() → uint8

Returns restriction code 6 for all transfers being paused.

RECIPIENT_ADDRESS_FROZEN() → uint8

Returns restriction code 7 for recipient address being frozen.

LOWER_THAN_RECIPIENT_MIN_BALANCE() → uint8

Returns restriction code 8 for transfer resulting in balance below recipient minimum.

INSUFFICIENT_BALANCE_OF_SENDER() → uint8

Returns restriction code 9 for insufficient sender balance.

SENDER_NOT_AMLKYCPASSED() → uint8

Returns restriction code 10 for sender not having passed AML/KYC.

RECIPIENT_NOT_AMLKYCPASSED() → uint8

Returns restriction code 11 for recipient not having passed AML/KYC.

HOLDING_PERIOD_NOT_MET() → uint8

Returns restriction code 12 for holding period not being met.

NO_RULE_FOR_RECIPIENT() → uint8

Returns restriction code 13 for no transfer rule found for the recipient.

RECIPIENT_NOT_QUALIFIED() → uint8

Returns restriction code 14 for recipient not being qualified for the transfer.

MAX_RESTRICTION_CODE() → uint8

Returns the maximum valid restriction code (14).

Token Type Constants

TOKEN_TYPE_GENERIC() → uint256

Returns the generic token type constant (0).

Interface Constants

INTERFACE_ID() → bytes4

Returns the interface ID for the ITransferRules interface.


Token Type Rule Management (API)

setTokenTypeRule(uint256 region, uint256 accreditation, uint256 tokenType, bool requiresAmlKyc, bool isActive)

Sets a token type rule for a specific region and accreditation combination.

Parameters:

  • region (uint256): The region identifier
  • accreditation (uint256): The accreditation type identifier
  • tokenType (uint256): The token type to assign
  • requiresAmlKyc (bool): Whether AML/KYC is required for this token type
  • isActive (bool): Whether this rule is active

Requirements:

  • Caller must have TRANSFER_ADMIN_ROLE

Emits:

  • TokenTypeRuleSet(region, accreditation, tokenType, requiresAmlKyc, isActive)

Errors:

  • EasyAccessControl_DoesNotHaveTransferAdminRole(address): When caller lacks transfer admin role

removeTokenTypeRule(uint256 region, uint256 accreditation)

Removes a token type rule for a specific region and accreditation combination.

Parameters:

  • region (uint256): The region identifier
  • accreditation (uint256): The accreditation type identifier

Requirements:

  • Caller must have TRANSFER_ADMIN_ROLE

Emits:

  • TokenTypeRuleRemoved(region, accreditation)

Errors:

  • EasyAccessControl_DoesNotHaveTransferAdminRole(address): When caller lacks transfer admin role

getTokenTypeRule(uint256 region, uint256 accreditation) → TokenTypeRule

Retrieves a token type rule for a specific region and accreditation combination.

Parameters:

  • region (uint256): The region identifier
  • accreditation (uint256): The accreditation type identifier

Returns:

  • TokenTypeRule: The token type rule struct containing tokenType, requiresAmlKyc, and isActive

batchSetTokenTypeRules(uint256[] regions, uint256[] accreditations, uint256[] tokenTypes, bool[] requiresAmlKycFlags, bool[] isActiveFlags)

Sets multiple token type rules in a single transaction.

Parameters:

  • regions (uint256[]): Array of region identifiers
  • accreditations (uint256[]): Array of accreditation type identifiers
  • tokenTypes (uint256[]): Array of token types to assign
  • requiresAmlKycFlags (bool[]): Array of AML/KYC requirement flags
  • isActiveFlags (bool[]): Array of active status flags

Requirements:

  • Caller must have TRANSFER_ADMIN_ROLE
  • All arrays must have the same length

Emits:

  • TokenTypeRuleSet(region, accreditation, tokenType, requiresAmlKyc, isActive) for each rule

Errors:

  • EasyAccessControl_DoesNotHaveTransferAdminRole(address): When caller lacks transfer admin role
  • TransferRules_InvalidArrayLengths(): When arrays have different lengths

setDefaultTokenTypeRule(uint256 tokenType, bool requiresAmlKyc, bool isActive)

Sets the default token type rule used when no specific rule matches.

Parameters:

  • tokenType (uint256): The default token type to assign
  • requiresAmlKyc (bool): Whether AML/KYC is required for the default token type
  • isActive (bool): Whether the default rule is active

Requirements:

  • Caller must have TRANSFER_ADMIN_ROLE

Emits:

  • DefaultTokenTypeRuleSet(tokenType, requiresAmlKyc, isActive)

Errors:

  • EasyAccessControl_DoesNotHaveTransferAdminRole(address): When caller lacks transfer admin role

resetDefaultTokenTypeRule()

Resets the default token type rule to inactive generic type.

Requirements:

  • Caller must have TRANSFER_ADMIN_ROLE

Emits:

  • DefaultTokenTypeRuleSet(TOKEN_TYPE_GENERIC, false, false)

Errors:

  • EasyAccessControl_DoesNotHaveTransferAdminRole(address): When caller lacks transfer admin role

defaultTokenTypeRule() → TokenTypeRule

Returns the current default token type rule.

Returns:

  • TokenTypeRule: The default token type rule struct

Token Type Determination (API)

determineTokenType(address wallet, IIdentityRegistry identityRegistry) → uint256

Determines the appropriate token type for a wallet based on identity and configured rules.

Parameters:

  • wallet (address): The wallet address to determine token type for
  • identityRegistry (IIdentityRegistry): The identity registry contract

Returns:

  • tokenType (uint256): The determined token type

Logic:

  1. Retrieves wallet identity from the registry
  2. Iterates through wallet's regions to find matching active rules
  3. Checks AML/KYC requirements if specified in the rule
  4. Falls back to default rule if no specific rule matches
  5. Reverts if no applicable rule is found

Errors:

  • TransferRules_RecipientNotAmlKycPassed(): When default rule requires AML/KYC but wallet doesn't have it
  • TransferRules_TokenTypeRuleNotFound(): When no applicable rule is found

tokenTypeAllowed(uint256 tokenType, address wallet, IIdentityRegistry identityRegistry) → bool

Checks if a specific token type is allowed for a wallet.

Parameters:

  • tokenType (uint256): The token type to check
  • wallet (address): The wallet address
  • identityRegistry (IIdentityRegistry): The identity registry contract

Returns:

  • bool: True if the token type is allowed for the wallet

Transfer Rule Management (API)

setTransferRule(uint256 tokenType, uint256 recipientRegion, uint256 recipientAccreditation, TransferRule _rule)

Sets a transfer rule for a specific token type and recipient identity combination.

Parameters:

  • tokenType (uint256): The token type identifier
  • recipientRegion (uint256): The recipient's region identifier
  • recipientAccreditation (uint256): The recipient's accreditation type
  • _rule (TransferRule): The transfer rule struct containing lockDurationSeconds, requiresAmlKyc, and isActive

Requirements:

  • Caller must have TRANSFER_ADMIN_ROLE

Emits:

  • TransferRuleSet(tokenType, recipientRegion, recipientAccreditation, lockDurationSeconds, requiresAmlKyc, isActive)

Errors:

  • EasyAccessControl_DoesNotHaveTransferAdminRole(address): When caller lacks transfer admin role

removeTransferRule(uint256 tokenType, uint256 recipientRegion, uint256 recipientAccreditation)

Removes a transfer rule for a specific token type and recipient identity combination.

Parameters:

  • tokenType (uint256): The token type identifier
  • recipientRegion (uint256): The recipient's region identifier
  • recipientAccreditation (uint256): The recipient's accreditation type

Requirements:

  • Caller must have TRANSFER_ADMIN_ROLE

Emits:

  • TransferRuleRemoved(tokenType, recipientRegion, recipientAccreditation)

Errors:

  • EasyAccessControl_DoesNotHaveTransferAdminRole(address): When caller lacks transfer admin role

transferRuleFor(uint256 tokenType, uint256 recipientRegion, uint256 recipientAccreditation) → TransferRule

Retrieves a transfer rule for a specific token type and recipient identity combination.

Parameters:

  • tokenType (uint256): The token type identifier
  • recipientRegion (uint256): The recipient's region identifier
  • recipientAccreditation (uint256): The recipient's accreditation type

Returns:

  • TransferRule: The transfer rule struct containing lockDurationSeconds, requiresAmlKyc, and isActive

batchSetTransferRules(uint256[] tokenType, uint256[] recipientRegion, uint256[] recipientAccreditation, TransferRule[] rules)

Sets multiple transfer rules in a single transaction.

Parameters:

  • tokenType (uint256[]): Array of token type identifiers
  • recipientRegion (uint256[]): Array of recipient region identifiers
  • recipientAccreditation (uint256[]): Array of recipient accreditation types
  • rules (TransferRule[]): Array of transfer rule structs

Requirements:

  • Caller must have TRANSFER_ADMIN_ROLE
  • All arrays must have the same length

Emits:

  • TransferRuleSet(tokenType, recipientRegion, recipientAccreditation, lockDurationSeconds, requiresAmlKyc, isActive) for each rule

Errors:

  • EasyAccessControl_DoesNotHaveTransferAdminRole(address): When caller lacks transfer admin role
  • TransferRules_InvalidArrayLengths(): When arrays have different lengths

Transfer Validation (API)

detectTransferRestriction(address tokenAddr, address from, address to, uint256 value) → uint8

Performs comprehensive transfer restriction detection including holding period checks.

Parameters:

  • tokenAddr (address): The token contract address
  • from (address): The sender address
  • to (address): The recipient address
  • value (uint256): The transfer amount

Returns:

  • uint8: Restriction code (0 for success, non-zero for various restrictions)

Logic:

  1. Performs basic transfer checks via detectTransferRestrictionBasic
  2. Calculates transferable amounts from timelocks and holdings
  3. Validates holding periods for each token type
  4. Returns appropriate restriction code

detectTransferRestrictionBasic(address tokenAddr, address from, address to, uint256 value) → uint8

Performs basic transfer restriction checks without holding period validation.

Parameters:

  • tokenAddr (address): The token contract address
  • from (address): The sender address
  • to (address): The recipient address
  • value (uint256): The transfer amount

Returns:

  • uint8: Restriction code (0 for success, non-zero for various restrictions)

Checks:

  • Token not paused
  • Recipient not zero address
  • Recipient not token contract
  • Sender and recipient not frozen
  • Sender has AML/KYC
  • Sufficient unlocked balance

checkTransferAllowed(uint256 tokenType, uint256 mintTimestamp, IdentityInfo recipientIdentity, bool isAmlKycPassed) → uint8

Checks if a transfer is allowed for a specific holding based on transfer rules.

Parameters:

  • tokenType (uint256): The token type of the holding
  • mintTimestamp (uint256): When the tokens were minted
  • recipientIdentity (IdentityInfo): The recipient's identity information
  • isAmlKycPassed (bool): Whether the recipient has passed AML/KYC

Returns:

  • uint8: Restriction code (0 for success, non-zero for restrictions)

Logic:

  1. Iterates through recipient's regions to find matching transfer rules
  2. Checks if rule is active
  3. Validates AML/KYC requirements
  4. Validates holding period requirements
  5. Returns SUCCESS if any region allows the transfer

getUnlockTimestamp(uint256 tokenType, uint256 mintTimestamp, address recipient, IIdentityRegistry identityRegistry) → uint256

Calculates when tokens of a specific type will be unlocked for transfer to a recipient.

Parameters:

  • tokenType (uint256): The token type identifier
  • mintTimestamp (uint256): When the tokens were minted
  • recipient (address): The intended recipient address
  • identityRegistry (IIdentityRegistry): The identity registry contract

Returns:

  • unlockTimestamp (uint256): The earliest timestamp when transfer is allowed (0 if no restrictions)

Utility Functions

messageForTransferRestriction(uint8 restrictionCode) → string

Returns a human-readable message for a restriction code.

Parameters:

  • restrictionCode (uint8): The restriction code to get message for

Returns:

  • string: Human-readable description of the restriction

Errors:

  • TransferRules_BadRestrictionCode(): When restrictionCode exceeds MAX_RESTRICTION_CODE

checkSuccess(uint8 restrictionCode) → bool

Checks if a restriction code indicates success.

Parameters:

  • restrictionCode (uint8): The restriction code to check

Returns:

  • isSuccess (bool): True if the code equals SUCCESS (0)

accessControl() → IAccessControl

Returns the address of the AccessControl contract.

Returns:

  • IAccessControl: The AccessControl contract interface

ERC-2771 Meta-Transaction Support

isTrustedForwarder(address forwarder) → bool

Checks if an address is the trusted forwarder for meta-transactions.

Parameters:

  • forwarder (address): The address to check

Returns:

  • bool: True if the address is the trusted forwarder

trustedForwarder() → address

Returns the address of the trusted forwarder.

Returns:

  • address: The trusted forwarder address

ERC-165 Interface Support

supportsInterface(bytes4 interfaceId) → bool

Checks if the contract supports a specific interface.

Parameters:

  • interfaceId (bytes4): The interface identifier to check

Returns:

  • bool: True if the interface is supported

Supported Interfaces:

  • ITransferRules: The main transfer rules interface
  • IERC165: The interface detection standard

Events

Token Type Rule Events (API)

TokenTypeRuleSet(uint256 indexed region, uint256 indexed accreditation, uint256 indexed tokenType, bool requiresAmlKyc, bool isActive)

Emitted when a token type rule is set or updated.

Parameters:

  • region (uint256, indexed): The region identifier
  • accreditation (uint256, indexed): The accreditation type identifier
  • tokenType (uint256, indexed): The assigned token type
  • requiresAmlKyc (bool): Whether AML/KYC is required
  • isActive (bool): Whether the rule is active

TokenTypeRuleRemoved(uint256 indexed region, uint256 indexed accreditation)

Emitted when a token type rule is removed.

Parameters:

  • region (uint256, indexed): The region identifier
  • accreditation (uint256, indexed): The accreditation type identifier

DefaultTokenTypeRuleSet(uint256 indexed tokenType, bool requiresAmlKyc, bool isActive)

Emitted when the default token type rule is set or updated.

Parameters:

  • tokenType (uint256, indexed): The default token type
  • requiresAmlKyc (bool): Whether AML/KYC is required for the default type
  • isActive (bool): Whether the default rule is active

Transfer Rule Events (API)

TransferRuleSet(uint256 indexed tokenType, uint256 recipientRegion, uint256 recipientAccreditation, uint256 lockDurationSeconds, bool requiresAmlKyc, bool isActive)

Emitted when a transfer rule is set or updated.

Parameters:

  • tokenType (uint256, indexed): The token type identifier
  • recipientRegion (uint256): The recipient's region identifier
  • recipientAccreditation (uint256): The recipient's accreditation type
  • lockDurationSeconds (uint256): The holding period in seconds
  • requiresAmlKyc (bool): Whether AML/KYC is required for recipients
  • isActive (bool): Whether the rule is active

TransferRuleRemoved(uint256 indexed tokenType, uint256 indexed recipientRegion, uint256 indexed recipientAccreditation)

Emitted when a transfer rule is removed.

Parameters:

  • tokenType (uint256, indexed): The token type identifier
  • recipientRegion (uint256, indexed): The recipient's region identifier
  • recipientAccreditation (uint256, indexed): The recipient's accreditation type

Custom Errors

Access Control Errors

EasyAccessControl_DoesNotHaveTransferAdminRole(address addr)

Thrown when an address attempts to call a transfer admin function without the required role.

Parameters:

  • addr (address): The address that lacks the transfer admin role

Validation Errors

TransferRules_BadRestrictionCode()

Thrown when an invalid restriction code is provided to messageForTransferRestriction.

TransferRules_InvalidAccessControl()

Thrown when the constructor is called with a zero address for the access control parameter.

TransferRules_InvalidArrayLengths()

Thrown when batch functions are called with arrays of different lengths.

TransferRules_InvalidTokenType()

Thrown when an invalid token type is provided (currently unused in the contract).

TransferRules_RecipientNotAmlKycPassed()

Thrown when a recipient doesn't meet AML/KYC requirements for token type determination.

TransferRules_TokenTypeRuleNotFound()

Thrown when no applicable token type rule is found for a wallet during token type determination.


Data Structures

TokenTypeRule

struct TokenTypeRule {
uint256 tokenType; // The token type to assign
bool requiresAmlKyc; // Whether AML/KYC is required
bool isActive; // Whether this rule is active
}

Used to map investor identity (region + accreditation) to appropriate token types during minting.

TransferRule

struct TransferRule {
uint256 lockDurationSeconds; // Holding period from mint timestamp
bool requiresAmlKyc; // Whether recipient must have AML/KYC
bool isActive; // Whether this rule is active
}

Used to define transfer restrictions based on token type and recipient identity.

IdentityInfo

struct IdentityInfo {
uint256[] regions; // Array of region identifiers
uint256 accreditationType; // Accreditation type
uint256 lastAmlKycChangeTimestamp; // Last AML/KYC status change
uint256 lastAccreditationChangeTimestamp; // Last accreditation change
bool amlKycPassed; // Current AML/KYC status
}

Identity information structure from the IdentityRegistry contract, used for validation.