diff --git a/ARCs/arc-1644.md b/ARCs/arc-1644.md new file mode 100644 index 000000000..482c58fb8 --- /dev/null +++ b/ARCs/arc-1644.md @@ -0,0 +1,137 @@ +--- +arc: 1644 +title: Controller Operations for Security Tokens +description: Forced transfer and redemption controller interface for regulated tokens +author: Ludovit Scholtz (@scholtz) +discussions-to: https://github.com/algorandfoundation/ARCs/discussions +status: Draft +type: Standards Track +category: Interface +sub-category: Application +created: 2025-09-03 +requires: 88, 200 +replaces: +--- + +# ARC-1644: Controller Operations for Security Tokens + +## Abstract + +ARC-1644 defines standardized controller powers for security tokens on Algorand, enabling forced transfers and redemptions under strictly governed conditions (e.g., court order, regulatory action, error remediation). It mirrors Ethereum's ERC-1644 while adapting privilege enforcement to Algorand's ARC-200 token control and smart contract mechanism. + +## Motivation + +Certain regulated events necessitate administrative intervention. A predictable, auditable interface reduces systemic risk and ensures interoperability across custodians and secondary trading platforms. + +## Specification + +### Controller Authorization + +Global state MUST store `controller` (address) OR a list of controllers in a box `controllers`. A multi-sig or logic signature is RECOMMENDED. Changes to controller set SHOULD be timelocked via `pending-controller` + `activate-round` pattern. + +### Required Methods (snake_case, ARC-4 types) + +Canonical ERC-1644 defines 3 functions: `controllerTransfer`, `controllerRedeem`, `isControllable`. Base ARC-1644 mirrors that minimal surface; controller management is an extension (see 3.4). + +All base methods are namespaced with `arc1644_`. + +- `arc1644_controller_transfer(from: address, to: address, amount: uint64, data: bytes, operator_data: bytes) -> (code: uint64)` + - Forces a transfer of `amount` from `from` to `to`. + - MUST return a status / reason code consistent with ARC-1594. +- `arc1644_controller_redeem(from: address, amount: uint64, operator_data: bytes) -> (code: uint64)` + - Forces redemption (burn) from `from`. +- `arc1644_is_controllable() -> (flag: uint64)` + - Returns 1 iff controller operations are currently enabled. + +Partition awareness is intentionally NOT in the base interface (matches ERC-1644). A Partition Controller Extension is defined in section 3.5. + +### Semantics (Base) + +Controller operations bypass standard sender consent but MUST still respect partition invariants and reason codes. Forced actions SHOULD emit logs referencing `operator_data` justification. + +### Controller Governance Extension (Optional) + +If an implementation wishes to expose on-chain controller set governance, it MAY add: + +- `arc1644_set_controller(new_controller: address)` (timelocked commit pattern RECOMMENDED) +- Or multi-controller form: + - `arc1644_add_controller(addr: address)` + - `arc1644_remove_controller(addr: address)` + +Timelock pattern: store `pending_controller`, `pending_set_round`, enforce activation after `pending_set_round + min_delay`. + +Disabling control: A governance call MAY irreversibly set `controllable = 0` and zero out controller address(es); afterwards `arc1644_is_controllable` MUST return 0 permanently. + +### Partition Controller Extension (Optional) + +For tokens implementing ARC-1410 partitions, the following extension functions MAY be added (mirroring ARC-1410 semantics): + +- `arc1644_controller_transfer_partition(from: address, to: address, partition: bytes32, amount: uint64, data: bytes, operator_data: bytes) -> (code: uint64)` +- `arc1644_controller_redeem_partition(from: address, partition: bytes32, amount: uint64, operator_data: bytes) -> (code: uint64)` + +Reason code mapping MUST remain consistent with ARC-1594; partition not found or insufficient balance codes SHOULD reuse existing insufficiency codes. + +If extension is absent, attempts to call these methods MUST reject. + +### Semantics (Partition Extension) + +Controller partition operations bypass holder consent but MUST maintain partition accounting invariants identical to standard partition transfers/redemptions. + +### Execution Pattern + +Implementation configures ARC-200 transfer authority such that only application-governed logic can perform forced movements (e.g., via a logic-controlled clawback equivalent or authority address). `arc1644_controller_transfer` constructs an inner ARC-200 transfer `from -> to`. If using an external authority address, ensure it is rekeyed / restricted to contract governance. + +### Events (Logs) + +Base (no partition): + +- Tag 0x31 arc1644_controller_transfer | controller | from | to | amount | code +- Tag 0x32 arc1644_controller_redeem | controller | from | amount | code +- Tag 0x33 arc1644_controller_changed | old | new + +Partition Extension (if implemented): + +- Tag 0x34 arc1644_controller_transfer_partition | controller | from | to | partition | amount | code +- Tag 0x35 arc1644_controller_redeem_partition | controller | from | partition | amount | code + +### Reason Codes + +Implementations MUST reuse ARC-1594 codes. Recommended additional (extension) codes if not already allocated: + +- `50` ControllerUnauthorized (caller not an authorized controller) +- `51` ControllerDisabled (controllable flag off) +- `52` JustificationRequired (non-empty operator_data required) + +These codes SHOULD NOT collide with existing ARC-1594 numeric assignments; if conflicts arise, implementers MAY shift into an unused high range (e.g., >= 200) but MUST document mapping. + +### Safeguards + +- Mandatory justification: if global `require-just` == 1, `operator_data` MUST contain a non-empty explanation or legal reference identifier. +- Rate limiting (optional): store last controller action round; enforce minimum interval. +- Audit trail: append structured log with reason code + hashed justification docs. + +### Disabling Control + +`arc1644_is_controllable` may return 0 after a governance decision to renounce override powers. Implementation sets `controller` to zero-address and `controllable` = 0 (immutable). + +## Security Considerations + +- Ensure controller cannot mint (that's issuance) unless explicitly allowed; separation of duties. +- Timelock controller changes to mitigate key compromise. +- Make justification transparent while avoiding sensitive full-text storage (hash large documents). + +## Backwards Compatibility + +If not implemented, `arc1644_is_controllable` MUST return 0 and controller methods MUST revert / reject with `51`. + +## Reference Implementation + +[arc1644.algo.ts](https://github.com/scholtz/arc-1400/blob/main/projects/arc-1400/smart_contracts/security_token/arc1644.algo.ts) + +## Rationale + +Partition-neutral base mirrors Ethereum minimalism; extension keeps core lightweight while enabling regulated partition operations when ARC-1410 present. + +## Copyright + +CC0 1.0 Universal.