ERC-7943 Universal Real-World Asset Token Interface (uRWA - Universal Real World Asset Interface)

Final · Tokens · created 2025-06-10

Defines a common interface for real-world asset (RWA) tokens such as securities and real estate. It adds the regulatory compliance features these tokens need, namely transferability checks, asset freezing, and forced transfers, on top of existing token standards such as ERC-20, ERC-721, and ERC-1155.

Why it is needed

Tokenizing real-world assets such as securities or real estate brings regulation with it. Transfers may need to be allowed only to permitted users, and assets may need to be frozen and forcibly moved for law enforcement. Existing token standards such as ERC-20, ERC-721, and ERC-1155 have no structure to carry these requirements. As a result, each issuer attached compliance features in its own way, and a decentralized finance (DeFi) protocol that wanted to integrate with RWA tokens had to learn each token's different approach individually. Earlier attempts at a universal RWA standard enforced fine-grained role-based access control, mandatory on-chain allowlists, specific on-chain identity systems, and metadata handling, which imposed unnecessary complexity and gas costs even on simple use cases that need none of those features. The assets are also so varied that a single comprehensive framework that specifies everything is hard to build. What was needed was a minimal common interface that leaves implementation to each party and unifies only the outward appearance.

What to implement

In depth

One standard, three interfaces

An ERC-7943 token must extend one of the base token interfaces: ERC-20, ERC-721, ERC-1155, or ERC-6909. Three interfaces are defined to match the base standards: IERC7943Fungible (for ERC-20), IERC7943NonFungible (for ERC-721), and IERC7943MultiToken (for ERC-1155 and ERC-6909). The function set is the same, but the parameters differ. Fungible tokens use an amount, NFTs use a tokenId and a frozen flag (bool), and multi-tokens use a tokenId and an amount. ERC-165 supportsInterface must return true for the interfaceId 0x3edbb4c4 for the fungible interface, 0xbf1ef5fe for the non-fungible interface, and 0x41c4fbad for the multi-token interface. Sensitive functions such as forcedTransfer and setFrozenTokens must have access restrictions such as onlyOwner or role-based access control, and this standard does not specify which approach to use.

canSend and canReceive are account-level eligibility checks

canSend and canReceive check an account's own eligibility, regardless of individual transfer conditions such as the counterparty, amount, or tokenId. They are commonly used for allowlists or KYC/KYB/AML checks. Both functions MUST NOT revert and MUST NOT change contract storage, but they MAY depend on on-chain state such as the current timestamp, block number, or msg.sender. Per-transfer or amount-based rules such as balance checks or quantity limits must not be placed here, and such rules belong in canTransfer. Splitting sending and receiving makes one-directional restrictions possible, such as blocking receiving while still allowing sending. This can express situations common in regulated environments, such as KYC expiry, AML alerts, and jurisdictional constraints.

canTransfer is a transfer-level permission check

canTransfer evaluates whether a specific transfer is possible under the permissioned compliance rules. It MUST NOT revert and MUST NOT change storage. It must verify that the transfer amount does not exceed the unfrozen amount (the current balance minus the frozen amount), and it must perform the canSend check on from and the canReceive check on to. ERC-3643 does not perform these checks inside canTransfer, which is an explicitly noted difference. It must return false whenever a pause mechanism or any permissioned rule involving an authorized party would block the transfer. Conversely, it must not return false because of non-permissioned validation that belongs to the base token standard, such as balance or allowance checks. Public transfer functions such as transfer, transferFrom, and safeTransferFrom must not succeed in a situation where canTransfer would return false, or where canSend on from or canReceive on to is false.

Behavior rules for forcedTransfer

forcedTransfer must move the asset from from to to by directly manipulating balances or ownership, and it may do so either by a direct transfer or by burning from from and minting to to. Access must be restricted, validations such as balance sufficiency must be performed, and the base standard's transfer event matching the method used must be emitted together with the ForcedTransfer event. In a single-party permission environment the canTransfer check may be skipped. If tokens counted as frozen are involved in that case, the freeze must first be released and the Frozen event must be emitted before the base transfer event. This ordering matters for preventing reentrancy attacks on tokens such as ERC-721 and ERC-1155, which make external calls to the recipient. Even in this case, the canReceive check on to SHOULD still be performed. In a multi-party permission environment, the canTransfer check should be performed and the freeze constraint should not be bypassed. If validation or the canReceive check fails, it must revert. The name was chosen as a neutral expression for the act itself rather than a specific motive such as seizure or recovery, and forcedTransfer rather than forceTransfer is used for compatibility with ERC-3643.

setFrozenTokens overwrites with an absolute value

setFrozenTokens is a single function that overwrites the frozen amount with a new value, like ERC-20's approve, instead of splitting into freeze and unfreeze. A single function and a single Frozen event were chosen to keep the standard concise. It must emit the Frozen event, must have restricted access, and must revert on a logical problem or validation failure. In particular, it must allow freezing an amount larger than the current holdings, in order to lock up balances that arrive later. Because overwriting with an absolute value can cause races when there are multiple authorized accounts, the original text shows, as extension examples, setFrozenTokensIf, which checks an expected value, and setFrozenTokensDelta, which adjusts by an increment. It notes, however, that such helper functions still cannot prevent same-block conflicts or mempool ordering races. Extensions such as setFrozenTokensWithProof, which attaches legal evidence, and a multicall pattern similar to ERC-6357 are also given as examples.

Rules also apply to minting and burning

Permissionless minting, such as a public mint function, must not succeed if the recipient's canReceive is false. Permissioned minting performed by an authorized role SHOULD respect canReceive, but MAY skip it when operations or compliance require. Permissionless burning, such as a public burn function, must follow the canTransfer check and the canSend check on the holder, and must not allow burning more than the unfrozen amount. Permissioned burning may succeed even if the holder's canSend is false and may burn beyond the frozen amount. In that case the contract must update the frozen state and must emit the Frozen event before the base token's transfer event.

The error scheme favors specificity

The standard defines four errors: ERC7943CannotSend, ERC7943CannotReceive, ERC7943CannotTransfer, and ERC7943InsufficientUnfrozenBalance. The first three MAY be used as general revert mechanisms when canSend, canReceive, or canTransfer return false internally, and may be replaced by more specific errors or not used at all, depending on the checks performed. The overall principle is that error specificity comes first. ERC7943InsufficientUnfrozenBalance SHOULD be used when the transfer amount is less than or equal to the balance but greater than the unfrozen balance, or when an attempt is made to transfer a frozen tokenId. For failures unrelated to freezing, such as a transfer amount exceeding the entire balance or an account not holding that tokenId, the more specific errors of the base standard SHOULD be used. The error names follow the ERC-6093 guidelines. The status of this standard is finalized as Final.

Things to watch out for

Original ERC · ← ERCs