Skip to main content

Advanced Usage (Going Beyond The Defaults)

The Transfer Validator gives creators complete control over their token ecosystem. This section explores the customization options available to creators.

1. Select A Ruleset

Transfer Validator Version 5 currently includes four ruleset modules.

RulesetId BindingGlobal OptionsRuleset OptionsDefault RulesetDescription
Whitelist0, 4GO0/1/2/3WLO0/1/2/3/4/5Encompasses Security Levels 3 through 8 from prior validators. Blocks all transfers, unless allowed through an authorizer, a whitelist, or other whitelisting option.
Vanilla1NoneNoneEquivalent to Security Level 1 from prior validators. Allows all transfers.
Soulbound2NoneNoneEquivalent to Security Level 9 from prior validators. Blocks all transfers.
Blacklist3GO0/1/2/3NoneEquivalent to Security Level 2 from prior validators. Allows all transfers, unless the operator (msg.sender) is explicitly blocked by address or codehash.

2. Set Global and Ruleset-Specific Options

Note: By default, all options bits are set to zero (off).

Global Options Table

Option CodeOption NameBitRulesets
GO0Global Option Disable Authorization Mode0Whitelist
Blacklist
GO1Global Option No Authorizer Wildcard Operators Mode1Whitelist
Blacklist
GO2Global Option Account Freezing Mode2Whitelist
Blacklist
GO3Global Option Default List Extension Mode3Whitelist
Blacklist
GO4Reserved4
GO5Reserved5
GO6Reserved6
GO7Reserved7

Ruleset Whitelist Options Table

Option CodeOption NameBitRulesets
WLO0Whitelist Option Block All OTC0Whitelist
WLO1Whitelist Option Allow OTC For 7702 Delegates1Whitelist
WLO2Whitelist Option Allow OTC For Smart Wallets2Whitelist
WLO3Whitelist Option Block Smart Wallet Receivers3Whitelist
WLO4Whitelist Option Block Unverified EOA Receivers4Whitelist
WLO5Reserved5
WLO6Reserved6
WLO7Reserved7
WLO8Reserved8
WLO9Reserved9
WLO10Reserved10
WLO11Reserved11
WLO12Reserved12
WLO13Reserved13
WLO14Reserved14
WLO15Reserved15

3. Choose A List, Or Default List Extension

Most rulesets use lists of accounts or codehashes to allow or deny transfers. These lists function much like a firewall with an access control list. This on-chain access control list governs what operators are allowed, etc. Lists are identified and accessed by a key derived from two pieces of information. First, the List Id, is a uint48 value ranging from 0 (Default List Id Managed By Limit Break) to 281,474,976,710,655. Second, the List Type, is a uint8 value ranging from 0 to 255 that partitions the List Id into multiple kinds of lists.

List Ids

List IdList ManagerDescription
0Limit BreakDefault List
1 - 281,474,976,710,655Developers / Creators
Exchanges
DAOs / Enterprises
Custom / Community Lists

List Types

Type IdList TypeApplicable Ruleset(s)
0BlacklistBlacklist
1WhitelistWhitelist
2AuthorizersWhitelist
Blacklist
3Whitelist Extension ContractsWhitelist
4EIP-7702 Delegate WhitelistWhitelist
5EIP-7702 Delegate Whitelist Extension ContractsWhitelist
6-255Reserved for Future Validator ExpansionTBD
Blacklists

Blacklists, applicable only to the Blacklist ruleset, contain a set of account addresses and codehashes. The blacklist ruleset allows all transfers unless the operator (msg.sender) address is explicitly specified in the blacklist or the codehash of the operator is explicitly specified in the blacklist. Blacklists may extend the default blacklist, in which case the collection owner can specify a custom list id to be combined with the contents of the default blacklist with list id 0.

Whitelists, Whitelist Extension Contracts, and EIP-7702 Delegate Whitelists

Whitelists, applicable only to the Whitelist ruleset, contain a set of account addresses and codehashes that are explicitly allowed to be the operator on transfers, or explicit accounts that can perform OTC transfers in all circumstances, or carveouts to smart contract receiver constraints.

A whitelist extension contract is an external contract that can be queried to perform a check more advanced than a simple account or codehash comparison. For example, lets say that a whitelist should include any smart wallet contract that originated from a specific trusted wallet factory. An extension contract that checks to see if an account address was created by the trusted factory could be deployed and added to the whitelist extension contracts list.

The following table shows how various options block transfers and how whitelists can be applied to allow the transfer in a controlled manner.

OptionScenarioWhitelisting Checks
WLO0When Block All OTC is enabled, and caller equals from (token owner calls transfer directly)...Check if caller (owner/sender) is a whitelisted address. If not, check if codehash of caller is whitelisted. If not, iterate over whitelist extensions and check if caller is whitelisted by any extension in the list. When options include default list extension mode, repeat checks for the default list as well. If all applicable whitelist checks fail, block the transfer.
WLO0When Block All OTC is enabled, and caller does not equal from (operator/protocol-initiated transfer)...Check if caller or from (operator/protocol/sender) is a whitelisted address. If not, check if codehash of caller or from is whitelisted. If not, iterate over whitelist extensions and check if caller or from is whitelisted by any extension in the list. When options include default list extension mode, repeat checks for the default list as well. If all applicable whitelist checks fail, block the transfer.
WLO0When Block All OTC is disabled, and caller does not equal from (operator/protocol-initiated transfer)...Check if caller (operator/protocol) is a whitelisted address. If not, check if codehash of caller is whitelisted. If not, iterate over whitelist extensions and check if caller is whitelisted by any extension in the list. When options include default list extension mode, repeat checks for the default list as well. If all applicable whitelist checks fail, block the transfer.
WLO3When Block Smart Wallet Receivers is enabled, and the codelength of to is greater than zero...Check if to (receiver) is a whitelisted address. If not, check if codehash of to is whitelisted. If not, iterate over whitelist extensions and check if to is whitelisted by any extension in the list. When options include default list extension mode, repeat checks for the default list as well. If all applicable whitelist checks fail, block the transfer.
WLO4When Block Unverified EOA Receivers is enabled, and the to account has not verified a signature with the EOA registry...Check if to (receiver) is a whitelisted address. If not, check if codehash of to is whitelisted. If not, iterate over whitelist extensions and check if to is whitelisted by any extension in the list. When options include default list extension mode, repeat checks for the default list as well. If all applicable whitelist checks fail, block the transfer.
WLO1When Block All OTC is disabled and Allow OTC For 7702 Delegates is disabled, and caller equals from (token owner calls transfer directly), and caller has an EIP-7702 delegation attached...Get the address of the delegation attached to caller. Check if delegation is a whitelisted address in the delegate whitelist. If not, check if codehash of delegation is whitelisted in the delegate whitelist. If not, iterate over delegate whitelist extensions and check if delegation is whitelisted by any extension in the list. When options include default list extension mode, repeat checks for the default list as well. If all applicable delegate whitelist checks fail, block the transfer.
WLO2When Block All OTC is disabled and Allow OTC For Smart Wallets is disabled, and caller equals from (token owner calls transfer directly), and the caller has code, but is not an EIP-7702 delegate...Check if caller (owner/sender) is a whitelisted address. If not, check if codehash of caller is whitelisted. If not, iterate over whitelist extensions and check if caller is whitelisted by any extension in the list. When options include default list extension mode, repeat checks for the default list as well. If all applicable whitelist checks fail, block the transfer.
Authorizers

Authorizers are trusted smart contracts that have special permissions to override blacklist and whitelist restrictions. Special care must be taken to only add well-trusted authorizers. At the current time, the Seaport Royalty Enforcing Zone is the only contract that implements the required interfaces for an authorizer contract. The Seaport Royalty Enforcing Zone relies on an oracle to examine the royalties included in Seaport orders and sign a message authenticating that royalties are properly included in the order. The Royalty Enforcing Zone verifies the oracles signature, and once authenticated the zone uses authorization functions on the Transfer Validator to temporarily override blacklist or whitelist restrictions to allow Seaport trades that properly include full creator royalties. At the current time, OpenSea and Reservoir operate the two default trusted authorizer zones/oracles.

4. Choose Automatic or Manual Updates

By default, Transfer Validator Version 5 allows Limit Break to upgrade and/or patch rulesets. This allows creators to have improved rulesets automatically applied to their collections without any action on their part. Some creators may prefer not to receive automatic updates. In this case, the creator can specify an exact version of registered ruleset to apply to their collections. If/when Limit Break updates ruleset bindings, collections that have specified an exact version of ruleset will not receive the update without manual action on their part.

5. Apply Desired Settings from Steps 1-4

Limit Break provides a convenient Developer Tools UI to configure validator settings. However, developers can apply desired settings by interacting directly with the contract on Etherscan, My Ether Wallet, Gnosis Safe, etc by calling the following list and collection management functions.

Collection-Specific Function Calls

    /**
* @notice Set the ruleset id, global / ruleset options, fixed / custom ruleset for a collection.
*
* @dev Throws when the caller is neither collection contract, nor the owner or admin of the specified collection.
* @dev Throws when setting a custom ruleset to an unregistered ruleset address.
* @dev Throws when setting a ruleset id that is not bound to a ruleset address.
* @dev Throws when setting a custom ruleset with a managed ruleset id.
*
* @dev <h4>Postconditions:</h4>
* 1. The ruleset of the specified collection is set to the new value.
* 2. Global options and ruleset-specific options of the specified collection are set to the new value.
* 3. A `SetCollectionRuleset` event is emitted.
* 4. A `SetCollectionSecurityPolicyOptions` event is emitted.
*
* @param collection The address of the collection.
* @param rulesetId The new ruleset id to apply.
* @param customRuleset The address of the custom ruleset to apply. Must be address(0) unless ruleset
* id is RULESET_ID_FIXED_OR_CUSTOM (255).
* @param globalOptions The global options to apply.
* @param rulesetOptions The ruleset-specific options to apply.
*/
function setRulesetOfCollection(address collection, uint8 rulesetId, address customRuleset, uint8 globalOptions, uint16 rulesetOptions) external;

/**
* @notice Applies the specified list to a collection.
*
* @dev Throws when the caller is neither collection contract, nor the owner or admin of the specified collection.
* @dev Throws when the specified list id does not exist.
*
* @dev <h4>Postconditions:</h4>
* 1. The list of the specified collection is set to the new value.
* 2. An `AppliedListToCollection` event is emitted.
*
* @param collection The address of the collection.
* @param id The id of the operator whitelist.
*/
function applyListToCollection(address collection, uint48 id) external;

Creating and Managing Custom Lists

    /**
* @notice Creates a new list id. The list id is a handle to allow editing of blacklisted and whitelisted accounts
* and codehashes.
*
* @dev <h4>Postconditions:</h4>
* 1. A new list with the specified name is created.
* 2. The caller is set as the owner of the new list.
* 3. A `CreatedList` event is emitted.
* 4. A `ReassignedListOwnership` event is emitted.
*
* @param name The name of the new list.
* @return id The id of the new list.
*/
function createList(string calldata name) external returns (uint48 id);

/**
* @notice Creates a new list id, and copies all blacklisted and whitelisted accounts and codehashes from the
* specified source list.
*
* @dev <h4>Postconditions:</h4>
* 1. A new list with the specified name is created.
* 2. The caller is set as the owner of the new list.
* 3. A `CreatedList` event is emitted.
* 4. A `ReassignedListOwnership` event is emitted.
* 5. All blacklisted and whitelisted accounts and codehashes from the specified source list are copied
* to the new list.
* 6. An `AddedAccountToList` event is emitted for each blacklisted and whitelisted account copied.
* 7. An `AddedCodeHashToList` event is emitted for each blacklisted and whitelisted codehash copied.
*
* @param name The name of the new list.
* @param sourceListId The id of the source list to copy from.
* @return id The id of the new list.
*/
function createListCopy(string calldata name, uint48 sourceListId) external returns (uint48 id);

/**
* @notice Creates a new list id, and copies all accounts and codehashes from the
* specified source list for each specified list type.
*
* @dev <h4>Postconditions:</h4>
* 1. A new list with the specified name is created.
* 2. The caller is set as the owner of the new list.
* 3. A `CreatedList` event is emitted.
* 4. A `ReassignedListOwnership` event is emitted.
* 5. All accounts and codehashes from the specified source list / list types are copied
* to the new list.
* 6. An `AddedAccountToList` event is emitted for each account copied.
* 7. An `AddedCodeHashToList` event is emitted for each codehash copied.
*
* @param name The name of the new list.
* @param sourceListId The id of the source list to copy from.
* @param listTypes The list types to copy from the source list.
* @return id The id of the new list.
*/
function createListCopy(string calldata name, uint48 sourceListId, uint8[] calldata listTypes) external returns (uint48 id);

/**
* @notice Transfer ownership of a list to a new owner.
*
* @dev Throws when the new owner is the zero address.
* @dev Throws when the caller does not own the specified list.
*
* @dev <h4>Postconditions:</h4>
* 1. The list ownership is transferred to the new owner.
* 2. A `ReassignedListOwnership` event is emitted.
*
* @param id The id of the list.
* @param newOwner The address of the new owner.
*/
function reassignOwnershipOfList(uint48 id, address newOwner) external;

/**
* @notice Renounce the ownership of a list, rendering the list immutable.
*
* @dev Throws when the caller does not own the specified list.
* @dev Throws when list id is zero (default list).
*
* @dev <h4>Postconditions:</h4>
* 1. The ownership of the specified list is renounced.
* 2. A `ReassignedListOwnership` event is emitted.
*
* @param id The id of the list.
*/
function renounceOwnershipOfList(uint48 id) external;

/**
* @notice Adds one or more accounts to a list of specified list type.
*
* @dev Throws when the caller does not own the specified list.
* @dev Throws when the accounts array is empty.
*
* @dev <h4>Postconditions:</h4>
* 1. Accounts not previously in the list are added.
* 2. An `AddedAccountToList` event is emitted for each account that is newly added to the list.
*
* @param id The id of the list.
* @param listType The type of the list.
* @param accounts The addresses of the accounts to add.
*/
function addAccountsToList(uint48 id, uint8 listType, address[] calldata accounts) external;

/**
* @notice Removes one or more accounts from a list of the specified list type.
*
* @dev Throws when the caller does not own the specified list.
* @dev Throws when the accounts array is empty.
*
* @dev <h4>Postconditions:</h4>
* 1. Accounts previously in the list are removed.
* 2. A `RemovedAccountFromList` event is emitted for each account that is removed from the list.
*
* @param id The id of the list.
* @param listType The type of the list.
* @param accounts The addresses of the accounts to remove.
*/
function removeAccountsFromList(uint48 id, uint8 listType, address[] calldata accounts) external;

/**
* @notice Adds one or more codehashes to a list of specified list type.
*
* @dev Throws when the caller does not own the specified list.
* @dev Throws when the codehashes array is empty.
* @dev Throws when a codehash is zero.
*
* @dev <h4>Postconditions:</h4>
* 1. Codehashes not previously in the list are added.
* 2. An `AddedCodeHashToList` event is emitted for each codehash that is newly added to the list.
*
* @param id The id of the list.
* @param listType The type of the list.
* @param codehashes The codehashes to add.
*/
function addCodeHashesToList(uint48 id, uint8 listType, bytes32[] calldata codehashes) external;

/**
* @notice Removes one or more codehashes from a list of the specified list type.
*
* @dev Throws when the caller does not own the specified list.
* @dev Throws when the codehashes array is empty.
*
* @dev <h4>Postconditions:</h4>
* 1. Codehashes previously in the list are removed.
* 2. A `RemovedCodeHashFromList` event is emitted for each codehash that is removed from the list.
*
* @param id The id of the list.
* @param listType The type of the list.
* @param codehashes The codehashes to remove.
*/
function removeCodeHashesFromList(uint48 id, uint8 listType, bytes32[] calldata codehashes) external;

Checking List and Collection Settings

    /**
* @notice Returns the owner of the specified list id.
*/
function listOwners(uint48 id) external view returns (address);

/**
* @notice Get the security policy of the specified collection.
* @param collection The address of the collection.
* @return The security policy of the specified collection, which includes:
* Ruleset id, list id, global options, ruleset-specific options, optional custom ruleset address,
* and token type (if registered).
*/
function getCollectionSecurityPolicy(address collection) external view returns (CollectionSecurityPolicy memory);

/**
* @notice Get accounts by list id and list type.
* @param id The id of the list.
* @param listType The type of the list.
* @return An array of accounts in the list of the specified type.
*/
function getListAccounts(uint48 id, uint8 listType) external view returns (address[] memory);

/**
* @notice Get codehashes by list id and list type.
* @param id The id of the list.
* @param listType The type of the list.
* @return An array of codehashes in the list of the specified type.
*/
function getListCodeHashes(uint48 id, uint8 listType) external view returns (bytes32[] memory);

/**
* @notice Check if an account is found in a specified list id / list type.
* @param id The id of the list.
* @param listType The type of the list.
* @param account The address of the account to check.
* @return True if the account is in the specified list / type, false otherwise.
*/
function isAccountInList(uint48 id, uint8 listType, address account) external view returns (bool);

/**
* @notice Check if a codehash is in a specified list / type.
* @param id The id of the list.
* @param listType The type of the list.
* @param codehash The codehash to check.
* @return True if the codehash is in the specified list / type, false otherwise.
*/
function isCodeHashInList(uint48 id, uint8 listType, bytes32 codehash) external view returns (bool);

/**
* @notice Get accounts in list by collection and list type.
* @param collection The address of the collection.
* @param listType The type of the list.
* @return An array of accounts.
*/
function getListAccountsByCollection(address collection, uint8 listType) external view returns (address[] memory);

/**
* @notice Get codehashes in list by collection and list type.
* @param collection The address of the collection.
* @param listType The type of the list.
* @return An array of codehashes.
*/
function getListCodeHashesByCollection(address collection, uint8 listType) external view returns (bytes32[] memory);

/**
* @notice Check if an account is in the list by a specified collection and list type.
* @param collection The address of the collection.
* @param listType The type of the list.
* @param account The address of the account to check.
* @return True if the account is in the list / list type of the specified collection, false otherwise.
*/
function isAccountInListByCollection(address collection, uint8 listType, address account) external view returns (bool);

/**
* @notice Check if a codehash is in the list by a specified collection / list type.
* @param collection The address of the collection.
* @param listType The type of the list.
* @param codehash The codehash to check.
* @return True if the codehash is in the list / list type of the specified collection, false otherwise.
*/
function isCodeHashInListByCollection(address collection, uint8 listType, bytes32 codehash) external view returns (bool);

Limit Break

TwitterLimitBreak.comMedium

© 2026 Limit Break International, Inc. All rights reserved.

Privacy PolicyTerms of ServiceCookie PolicyDo Not Sell My Info