ERC-223
ERC-223: An Enhanced Token Standard
Introduction
ERC-223 is a token standard for Ethereum, proposed as an improvement to the widely used ERC-20 standard. It introduces mechanisms to address critical shortcomings of ERC-20, such as accidental token losses and inefficient gas usage. By defining a new communication model for token transfers, ERC-223 provides a more robust and user-friendly framework for token interactions.
What is ERC-223?
ERC-223 is similar to ERC-20 but extends its functionality by:
Handling token transfers on the recipient's side.
Preventing the loss of tokens sent to incompatible contracts.
Supporting metadata in token transfers for additional transaction context.
Key Features and Differences
Improvements Over ERC-20
Recipient Awareness
ERC-223 tokens can only be transferred to contracts that implement the
tokenReceived
function.Prevents tokens from being permanently lost if sent to non-compatible contracts.
Efficient Transactions
Uses a single
transfer
method instead of separateapprove
andtransferFrom
.Reduces gas consumption by eliminating unnecessary calls.
Metadata Support
Allows metadata to be included with transfers, enabling context-specific actions.
Workflow Diagram

ERC-223 Implementation
An ERC-223 token must define specific methods and events, as described in EIP-223.
Required Methods
function name() public view returns (string);
function symbol() public view returns (string);
function decimals() public view returns (uint8);
function totalSupply() public view returns (uint256);
function balanceOf(address _owner) public view returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transfer(address _to, uint256 _value, bytes calldata _data) public returns (bool success);
Events
event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes calldata _data);
Recipient Contract Requirements
Contracts receiving ERC-223 tokens must implement:
function tokenReceived(address _from, uint _value, bytes calldata _data);
If the recipient contract does not implement this function, the transaction fails, and tokens remain with the sender.
Example Implementation
ERC-223 Token Contract
pragma solidity ^0.8.19;
abstract contract IERC223Recipient {
function tokenReceived(address _from, uint _value, bytes memory _data) public virtual;
}
contract ERC223Token {
event Transfer(address indexed from, address indexed to, uint value, bytes data);
mapping(address => uint256) private balances;
function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success) {
balances[msg.sender] -= _value;
balances[_to] += _value;
if (isContract(_to)) {
IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data);
}
emit Transfer(msg.sender, _to, _value, _data);
return true;
}
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
}
Recipient Contract
pragma solidity ^0.8.19;
contract RecipientContract is IERC223Recipient {
event Deposit(address indexed sender, uint value);
uint256 public deposits;
function tokenReceived(address _from, uint _value, bytes memory _data) public override {
deposits += _value;
emit Deposit(_from, _value);
}
}
Advantages of ERC-223
Safety: Tokens cannot be accidentally lost by sending them to incompatible contracts.
Efficiency: Reduces gas costs by requiring fewer transactions.
Extensibility: Supports metadata for enhanced functionality.
Limitations
Adoption: ERC-223 is not yet widely adopted, limiting compatibility.
Backward Compatibility: Existing ERC-20 tools and contracts require modifications to support ERC-223.
Gas Costs: The additional recipient checks may increase transaction costs in some scenarios.
Last updated
Was this helpful?