Skip to content

Commit 88aaafb

Browse files
authored
Update ERC-7943: Move to Last Call
Merged by EIP-Bot.
1 parent 2fc421e commit 88aaafb

2 files changed

Lines changed: 32 additions & 28 deletions

File tree

ERCS/erc-7943.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
eip: 7943
33
title: uRWA - Universal Real World Asset Interface
44
description: Interfaces for common base tokens defining compliance checks, transfer controls, and enforcement actions for Real World Assets (RWAs).
5-
author: Dario Lo Buglio (@xaler5)
5+
author: Dario Lo Buglio (@xaler5), Tino Martinez Molina (@tinom9), Mihai Colceriu (@mihaic195)
66
discussions-to: https://ethereum-magicians.org/t/erc-universal-rwa-interface/23972
7-
status: Review
7+
status: Last Call
8+
last-call-deadline: 2026-01-30
89
type: Standards Track
910
category: ERC
1011
created: 2025-06-10
@@ -74,15 +75,15 @@ interface IERC7943Fungible is IERC165 {
7475
/// @param from The address from which `amount` is taken.
7576
/// @param to The address that receives `amount`.
7677
/// @param amount The amount to force transfer.
77-
/// @return result True if the transfer executed correctly, false otherwise.
78+
/// @return result True if the transfer executed correctly. Reverts on failure.
7879
function forcedTransfer(address from, address to, uint256 amount) external returns(bool result);
7980
8081
/// @notice Changes the frozen status of `amount` tokens belonging to `account`.
8182
/// This overwrites the current value, similar to an `approve` function.
8283
/// @dev Requires specific authorization. Frozen tokens cannot be transferred by the account.
8384
/// @param account The address of the account whose tokens are to be frozen.
8485
/// @param amount The amount of tokens to freeze. It can be greater than account balance.
85-
/// @return result True if the freezing executed correctly, false otherwise.
86+
/// @return result True if the freezing executed correctly. Reverts on failure.
8687
function setFrozenTokens(address account, uint256 amount) external returns(bool result);
8788
8889
/// @notice Checks if a specific account is allowed to transact according to token rules.
@@ -140,7 +141,7 @@ interface IERC7943NonFungible is IERC165 {
140141
/// @param from The address from which `tokenId` is taken.
141142
/// @param to The address that receives `tokenId`.
142143
/// @param tokenId The ID of the token being transferred.
143-
/// @return result True if the transfer executed correctly, false otherwise.
144+
/// @return result True if the transfer executed correctly. Reverts on failure.
144145
function forcedTransfer(address from, address to, uint256 tokenId) external returns(bool result);
145146
146147
/// @notice Changes the frozen status of `tokenId` belonging to an `account`.
@@ -149,7 +150,7 @@ interface IERC7943NonFungible is IERC165 {
149150
/// @param account The address of the account whose tokens are to be frozen.
150151
/// @param tokenId The ID of the token to freeze.
151152
/// @param frozenStatus Whether `tokenId` is being frozen or not.
152-
/// @return result True if the freezing executed correctly, false otherwise.
153+
/// @return result True if the freezing executed correctly. Reverts on failure.
153154
function setFrozenTokens(address account, uint256 tokenId, bool frozenStatus) external returns(bool result);
154155
155156
/// @notice Checks if a specific account is allowed to transact according to token rules.
@@ -213,7 +214,7 @@ interface IERC7943MultiToken is IERC165 {
213214
/// @param to The address that receives `amount`.
214215
/// @param tokenId The ID of the token being transferred.
215216
/// @param amount The amount to force transfer.
216-
/// @return result True if the transfer executed correctly, false otherwise.
217+
/// @return result True if the transfer executed correctly. Reverts on failure.
217218
function forcedTransfer(address from, address to, uint256 tokenId, uint256 amount) external returns(bool result);
218219
219220
/// @notice Changes the frozen status of `amount` of `tokenId` tokens belonging to an `account`.
@@ -222,7 +223,7 @@ interface IERC7943MultiToken is IERC165 {
222223
/// @param account The address of the account whose tokens are to be frozen.
223224
/// @param tokenId The ID of the token to freeze.
224225
/// @param amount The amount of tokens to freeze. It can be greater than account balance.
225-
/// @return result True if the freezing executed correctly, false otherwise.
226+
/// @return result True if the freezing executed correctly. Reverts on failure.
226227
function setFrozenTokens(address account, uint256 tokenId, uint256 amount) external returns(bool result);
227228
228229
/// @notice Checks if a specific account is allowed to transact according to token rules.
@@ -259,7 +260,8 @@ These provide views into the implementing contract's compliance, transfer policy
259260
- The `canTransfer`
260261
- MUST validate that the `amount` being transferred doesn't exceed the unfrozen amount (which is the difference between the current balance and the frozen balance).
261262
- MUST perform a `canTransact` check on the `from` and `to` parameters. An important documentation note is that [ERC-3643](./eip-3643.md) doesn't perform a `canTransact` check within `canTransfer` as required.
262-
- MUST return false in general, if any permissioned rule will would prevent a given transfer from succeeding. A transfer refers to any operation that emits the token’s canonical transfer event. A permissioned check can be a pausing mechanism, a call to `canTransact` or anything else that requires privileged actors.
263+
- MUST return false in general, if any permissioned rule would prevent a given transfer from succeeding. A transfer refers to any operation that emits the token’s canonical transfer event. A permissioned check can be a pausing mechanism, a call to `canTransact` or anything else that requires privileged actors.
264+
263265
- `getFrozenTokens` will return the absolute frozen amount, which MAY exceed the account's current balance. In [ERC-721](./eip-721.md) tokens, it MAY return true even if the account does not hold the token.
264266

265267
### `forcedTransfer`
@@ -271,10 +273,11 @@ This function provides a standard mechanism for forcing a transfer from a `from`
271273
- MUST perform necessary validation checks (e.g., sufficient balance/ownership of a specific token).
272274
- MUST emit both the standard transfer event (from the base standard) and the `ForcedTransfer` event.
273275
- In single-party permissioned contexts:
274-
- It MAY bypass the `canTransfer` checks. If this happens, it MUST unfreeze the assets first and emit a `Frozen` event before the underlying base token transfer event reflecting the change. Having the unfrozen amount changed before the actual transfer is critical for tokens that might be susceptible to reentrancy attacks doing external checks on recipients as it is the case for [ERC-721](./eip-721.md) and [ERC-1155](./eip-1155.md) tokens.
276+
- It MAY bypass the `canTransfer` checks. If this happens, and the transfer involves tokens that are currently counted as frozen, it MUST unfreeze the assets first and emit a `Frozen` event before the underlying base token transfer event reflecting the change. Having the unfrozen amount changed before the actual transfer is critical for tokens that might be susceptible to reentrancy attacks doing external checks on recipients as it is the case for [ERC-721](./eip-721.md) and [ERC-1155](./eip-1155.md) tokens.
275277
- It SHOULD at least perform a `canTransact` check on the `to` parameter to ensure compliance.
276278
- In multi-party permissioned contexts:
277-
- It MUST perform the `canTransfer` checks.
279+
- It SHOULD perform the `canTransfer` checks and SHOULD NOT bypass the frozen constraints.
280+
- MUST revert in cases where validations and/or `canTransact` checks return false or fail.
278281

279282
### `setFrozenTokens`
280283

@@ -283,6 +286,7 @@ It provides a way to freeze or unfreeze assets held by a specific account. This
283286
- MUST emit the `Frozen` event.
284287
- MUST be restricted in access.
285288
- MUST allow freezing more assets than those held. This allows for future balances withholding.
289+
- MUST revert in cases of logical issues or validation checks failure.
286290

287291
### Additional Specifications
288292

@@ -291,7 +295,7 @@ The contract MUST implement the [ERC-165](./eip-165.md) `supportsInterface` func
291295
- `0xa8fdc849` for the non-fungible interface.
292296
- `0x5627c61a` for the multi token interface.
293297

294-
Implementations of these interfaces MUST implement the necessary functions of their chosen base standard (e.g., [ERC-20](./eip-20.md) for the fungible interface, [ERC-721](./eip-721.md) for the non fungible interface and [ERC-1155](./eip-1155.md) for the multi token interface) and MUST also restrict access to sensitive functions like `forcedTransfer` and `setFrozenTokens` using an appropriate access control mechanism (e.g., `onlyOwner`, Role-Based Access Control). The specific mechanism is NOT mandated by this interface standard.
298+
Implementations of these interfaces MUST implement the necessary functions of their chosen base standard (e.g., [ERC-20](./eip-20.md) for the fungible interface, [ERC-721](./eip-721.md) for the non-fungible interface and [ERC-1155](./eip-1155.md) for the multi token interface) and MUST also restrict access to sensitive functions like `forcedTransfer` and `setFrozenTokens` using an appropriate access control mechanism (e.g., `onlyOwner`, Role-Based Access Control). The specific mechanism is NOT mandated by this interface standard.
295299

296300
Implementations MUST ensure their transfer methods exhibit the following behavior:
297301

assets/erc-7943/contracts/interfaces/IERC7943.sol

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ interface IERC7943Fungible is IERC165 {
3737
/// @param from The address from which `amount` is taken.
3838
/// @param to The address that receives `amount`.
3939
/// @param amount The amount to force transfer.
40-
/// @return result True if the transfer executed correctly, false otherwise.
40+
/// @return result True if the transfer executed correctly. Reverts on failure.
4141
function forcedTransfer(address from, address to, uint256 amount) external returns(bool result);
4242

4343
/// @notice Changes the frozen status of `amount` tokens belonging to `account`.
4444
/// This overwrites the current value, similar to an `approve` function.
4545
/// @dev Requires specific authorization. Frozen tokens cannot be transferred by the account.
46-
/// @param account The address of the account whose tokens are to be frozen/unfrozen.
46+
/// @param account The address of the account whose tokens are to be frozen.
4747
/// @param amount The amount of tokens to freeze. It can be greater than account balance.
48-
/// @return result True if the freezing executed correctly, false otherwise.
48+
/// @return result True if the freezing executed correctly. Reverts on failure.
4949
function setFrozenTokens(address account, uint256 amount) external returns(bool result);
5050

5151
/// @notice Checks if a specific account is allowed to transact according to token rules.
@@ -61,7 +61,7 @@ interface IERC7943Fungible is IERC165 {
6161
function getFrozenTokens(address account) external view returns (uint256 amount);
6262

6363
/// @notice Checks if a transfer is currently possible according to token rules. It enforces validations on the frozen tokens.
64-
/// @dev This may involve checks like allowlists, blocklists, transfer limits and other policy-defined restrictions.
64+
/// @dev This can involve checks like allowlists, blocklists, transfer limits and other policy-defined restrictions.
6565
/// @param from The address sending tokens.
6666
/// @param to The address receiving tokens.
6767
/// @param amount The amount being transferred.
@@ -95,24 +95,24 @@ interface IERC7943NonFungible is IERC165 {
9595

9696
/// @notice Error reverted when a transfer is attempted from `account` with a `tokenId` which has been previously frozen.
9797
/// @param account The address holding the token with `tokenId`.
98-
/// @param tokenId The Id of the token being frozen and unavailable to be transferred.
98+
/// @param tokenId The ID of the token being frozen and unavailable to be transferred.
9999
error ERC7943InsufficientUnfrozenBalance(address account, uint256 tokenId);
100100

101101
/// @notice Takes `tokenId` from one address and transfers it to another.
102102
/// @dev Requires specific authorization. Used for regulatory compliance or recovery scenarios.
103103
/// @param from The address from which `tokenId` is taken.
104104
/// @param to The address that receives `tokenId`.
105105
/// @param tokenId The ID of the token being transferred.
106-
/// @return result True if the transfer executed correctly, false otherwise.
106+
/// @return result True if the transfer executed correctly. Reverts on failure.
107107
function forcedTransfer(address from, address to, uint256 tokenId) external returns(bool result);
108108

109109
/// @notice Changes the frozen status of `tokenId` belonging to an `account`.
110110
/// This overwrites the current value, similar to an `approve` function.
111111
/// @dev Requires specific authorization. Frozen tokens cannot be transferred by the account.
112-
/// @param account The address of the account whose tokens are to be frozen/unfrozen.
113-
/// @param tokenId The ID of the token to freeze/unfreeze.
112+
/// @param account The address of the account whose tokens are to be frozen.
113+
/// @param tokenId The ID of the token to freeze.
114114
/// @param frozenStatus Whether `tokenId` is being frozen or not.
115-
/// @return result True if the freezing executed correctly, false otherwise.
115+
/// @return result True if the freezing executed correctly. Reverts on failure.
116116
function setFrozenTokens(address account, uint256 tokenId, bool frozenStatus) external returns(bool result);
117117

118118
/// @notice Checks if a specific account is allowed to transact according to token rules.
@@ -129,7 +129,7 @@ interface IERC7943NonFungible is IERC165 {
129129
function getFrozenTokens(address account, uint256 tokenId) external view returns (bool frozenStatus);
130130

131131
/// @notice Checks if a transfer is currently possible according to token rules. It enforces validations on the frozen tokens.
132-
/// @dev This may involve checks like allowlists, blocklists, transfer limits and other policy-defined restrictions.
132+
/// @dev This can involve checks like allowlists, blocklists, transfer limits and other policy-defined restrictions.
133133
/// @param from The address sending tokens.
134134
/// @param to The address receiving tokens.
135135
/// @param tokenId The ID of the token being transferred.
@@ -165,7 +165,7 @@ interface IERC7943MultiToken is IERC165 {
165165

166166
/// @notice Error reverted when a transfer is attempted from `account` with an `amount` of `tokenId` less than or equal to its balance, but greater than its unfrozen balance.
167167
/// @param account The address holding the `amount` of `tokenId` tokens.
168-
/// @param tokenId The Id of the token being transferred.
168+
/// @param tokenId The ID of the token being transferred.
169169
/// @param amount The amount of `tokenId` tokens being transferred.
170170
/// @param unfrozen The amount of tokens that are unfrozen and available to transfer.
171171
error ERC7943InsufficientUnfrozenBalance(address account, uint256 tokenId, uint256 amount, uint256 unfrozen);
@@ -176,16 +176,16 @@ interface IERC7943MultiToken is IERC165 {
176176
/// @param to The address that receives `amount`.
177177
/// @param tokenId The ID of the token being transferred.
178178
/// @param amount The amount to force transfer.
179-
/// @return result True if the transfer executed correctly, false otherwise.
179+
/// @return result True if the transfer executed correctly. Reverts on failure.
180180
function forcedTransfer(address from, address to, uint256 tokenId, uint256 amount) external returns(bool result);
181181

182182
/// @notice Changes the frozen status of `amount` of `tokenId` tokens belonging to an `account`.
183183
/// This overwrites the current value, similar to an `approve` function.
184184
/// @dev Requires specific authorization. Frozen tokens cannot be transferred by the account.
185-
/// @param account The address of the account whose tokens are to be frozen/unfrozen.
186-
/// @param tokenId The ID of the token to freeze/unfreeze.
185+
/// @param account The address of the account whose tokens are to be frozen.
186+
/// @param tokenId The ID of the token to freeze.
187187
/// @param amount The amount of tokens to freeze. It can be greater than account balance.
188-
/// @return result True if the freezing executed correctly, false otherwise.
188+
/// @return result True if the freezing executed correctly. Reverts on failure.
189189
function setFrozenTokens(address account, uint256 tokenId, uint256 amount) external returns(bool result);
190190

191191
/// @notice Checks if a specific account is allowed to transact according to token rules.
@@ -202,7 +202,7 @@ interface IERC7943MultiToken is IERC165 {
202202
function getFrozenTokens(address account, uint256 tokenId) external view returns (uint256 amount);
203203

204204
/// @notice Checks if a transfer is currently possible according to token rules. It enforces validations on the frozen tokens.
205-
/// @dev This may involve checks like allowlists, blocklists, transfer limits and other policy-defined restrictions.
205+
/// @dev This can involve checks like allowlists, blocklists, transfer limits and other policy-defined restrictions.
206206
/// @param from The address sending tokens.
207207
/// @param to The address receiving tokens.
208208
/// @param tokenId The ID of the token being transferred.

0 commit comments

Comments
 (0)