Draft ERC (part of the ERC-1400 security-token family) that partitions a holder's balance into multiple `bytes32` partitions, each carrying its own metadata, transfer rules, and operator permissions. Enables tranched, restricted, and lockup-bearing balances inside a single token contract.
- 01security tokens with tranches
- 02vesting / lockup partitions on the same token
- 03regulatory transfer restrictions per partition
- 04differentiated voting rights per share class
- 05ERC-1400 security-token suites
- pnpm add @consensys/erc1400
- forge install ConsenSys/UniversalToken
- pnpm add @openzeppelin/contracts
Implement balances as `mapping(address => mapping(bytes32 => uint256))` keyed by partition, plus `mapping(address => bytes32[]) partitionsOf`. Expose `balanceOfByPartition(bytes32 partition, address holder)`, `partitionsOf(address holder)`, `transferByPartition(bytes32 partition, address to, uint256 value, bytes data) returns (bytes32)` (returning the destination partition), `issueByPartition`, `redeemByPartition`, and the operator family `authorizeOperatorByPartition` / `operatorTransferByPartition` / `isOperatorForPartition`. Aggregate `balanceOf(holder)` MUST equal the sum of `balanceOfByPartition` across all partitions. Pair with ERC-1594 (transfer restrictions) and ERC-1643 (document registry) under the ERC-1400 umbrella for a full security-token implementation.
- ⚑Partitions are `bytes32` — choose a stable encoding (e.g. `keccak256('locked-2027-Q1')`) and document it; arbitrary string-to-bytes32 packing breaks indexers and front-ends.
- ⚑`transferByPartition` MAY change the destination partition (e.g. unlocked tokens move to a 'liquid' partition) — front-ends that assume source partition == destination partition will mis-render balances; always read the returned `bytes32`.
- ⚑`balanceOf` aggregates across partitions, but ERC-20 `transfer` SHOULD pick a default partition — if you also implement ERC-20, document and enforce which partition `transfer` debits, or you'll silently move locked tokens.
- ⚑Operator authorization is dual: global operators authorized via ERC-777-style `authorizeOperator` may NOT have partition-level rights — verify via `isOperatorForPartition` before allowing a partition-scoped action.
- ⚑ERC-1410 is Draft and ConsenSys's reference moved to the 'Universal Token'/CMTAT lineage — pick a single implementation (Tokeny T-REX, ConsenSys UniversalToken, CMTAT) and stick with it; cross-mixing leads to selector collisions.
- ⚑Audit logs must emit partition-tagged `TransferByPartition` events — generic ERC-20 `Transfer` listeners will under-count and miscategorize movements.