Skip to content

Commit 3df37f9

Browse files
authored
Update index.md
1 parent 727804b commit 3df37f9

File tree

1 file changed

+192
-0
lines changed
  • src/content/developers/docs/standards/tokens/erc-223

1 file changed

+192
-0
lines changed
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,193 @@
1+
---
2+
title: ERC-223 Token Standard
3+
description: An overview of the ERC-223 fungible token standard, how it works, and a comparison to ERC-20.
4+
lang: en
5+
---
16

7+
## Introduction {#introduction}
8+
9+
**What is ERC-223?**
10+
11+
The ERC-223 is another standard for fungible tokens, like the ERC-20. The key difference is that ERC-223 defines not only the token API, but also the logic of how tokens should be transferred from sender to recipient and introduces a communication model that allows token transfers to be handled on the recipients side.
12+
13+
**How is it different from ERC-20 and why we need another token standard?**
14+
15+
ERC-223 addresses some limitations of ERC-20 and introduces a new method of interactions between token contract and a contract that may receive the tokens. There are few things that are possible with ERC-223 but not with ERC-20:
16+
17+
- Token transfer handling on the recipient's side. Recipient can detect that an ERC-223 token is being deposited.
18+
- Rejection of improperly sent tokens. If a user sent ERC-223 tokens to a contract that is not supposed to receive tokens then the contract can reject the transaction and the tokens will not be lost.
19+
- The transfer of ERC-223 tokens may contain metadata, which allows arbitrary information to be attached to the token transactions.
20+
21+
## Prerequisites {#prerequisites}
22+
23+
- [Accounts](/developers/docs/accounts)
24+
- [Smart Contracts](/developers/docs/smart-contracts/)
25+
- [Token standards](/developers/docs/standards/tokens/)
26+
- [ERC-20](/developers/docs/standards/tokens/erc-20/)
27+
28+
## Body {#body}
29+
30+
The ERC-223 (Ethereum Request for Comments 223), proposed by Dexaran in March 2017, is a token standard that
31+
implements an API for tokens within smart contracts and declares API for a contract that is supposed to receive ERC-223 tokens. Any contract that does not support ERC-223 Receiver API can not receive ERC-223 tokens which prevents the most common user mistakes.
32+
33+
If a smart contract implements the following methods and events it can be called an ERC-223 compatible token contract. Once deployed, it
34+
will be responsible to keep track of the created tokens on Ethereum.
35+
36+
The contract is not obligated to have only these functions and a developer can add any other feature from different token standards to this contract. For example, `approve` and `transferFrom` functions are not part of ERC-223 standard but these functions could be implemented should it be necessary.
37+
38+
From [EIP-223](https://eips.ethereum.org/EIPS/eip-223):
39+
40+
#### Methods {#methods}
41+
42+
ERC-223 token must implement the following methods:
43+
44+
```solidity
45+
function name() public view returns (string)
46+
function symbol() public view returns (string)
47+
function decimals() public view returns (uint8)
48+
function totalSupply() public view returns (uint256)
49+
function balanceOf(address _owner) public view returns (uint256 balance)
50+
function transfer(address _to, uint256 _value) public returns (bool success)
51+
function transfer(address _to, uint256 _value, bytes calldata _data) public returns (bool success)
52+
```
53+
54+
A contract that is supposed to receive ERC-223 tokens must implement the following method:
55+
56+
```solidity
57+
function tokenReceived(address _from, uint _value, bytes calldata _data)
58+
```
59+
60+
If ERC-223 tokens are sent to a contract that doesn't implement the `tokenReceived(..)` function then the transfer must fail and the tokens must not be moved from the sender's balance.
61+
62+
#### Events {#events}
63+
64+
```solidity
65+
event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes calldata _data)
66+
```
67+
68+
### Examples {#examples}
69+
70+
The API of ERC-223 token is similar to that of ERC-20, so from UI development point of view there is no difference. The only exception here is that ERC-223 tokens may not have `approve` + `transferFrom` functions as these are optional for this standard.
71+
72+
### Solidity examples {#solidity-example}
73+
74+
The purpose of this example is to illustrate how a contract must work with ERC-223 tokens.
75+
76+
Assume that we have a very basic ERC-223 token:
77+
78+
```solidity
79+
pragma solidity ^0.8.19;
80+
abstract contract IERC223Recipient {
81+
function tokenReceived(address _from, uint _value, bytes memory _data) public virtual;
82+
}
83+
contract VeryBasicERC223Token {
84+
event Transfer(address indexed from, address indexed to, uint value, bytes data);
85+
string private _name;
86+
string private _symbol;
87+
uint8 private _decimals;
88+
uint256 private _totalSupply;
89+
mapping(address => uint256) private balances;
90+
function name() public view returns (string memory) { return _name; }
91+
function symbol() public view returns (string memory) {return _symbol; }
92+
function decimals() public view returns (uint8) { return _decimals; }
93+
function totalSupply() public view returns (uint256) { return _totalSupply; }
94+
function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; }
95+
function isContract(address account) internal view returns (bool) {
96+
uint256 size;
97+
assembly { size := extcodesize(account) }
98+
return size > 0;
99+
}
100+
function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success){
101+
balances[msg.sender] = balances[msg.sender] - _value;
102+
balances[_to] = balances[_to] + _value;
103+
if(isContract(_to)) {
104+
IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data);
105+
}
106+
emit Transfer(msg.sender, _to, _value, _data);
107+
return true;
108+
}
109+
function transfer(address _to, uint _value) public returns (bool success){
110+
bytes memory _empty = hex"00000000";
111+
balances[msg.sender] = balances[msg.sender] - _value;
112+
balances[_to] = balances[_to] + _value;
113+
if(isContract(_to)) {
114+
IERC223Recipient(_to).tokenReceived(msg.sender, _value, _empty);
115+
}
116+
emit Transfer(msg.sender, _to, _value, _empty);
117+
return true;
118+
}
119+
}
120+
```
121+
122+
Now we want another contract to accept deposits of `tokenA` assuming that tokenA is an ERC-223 token. The contract must accept only tokenA and reject any other tokens. When the contract receives tokenA it must emit a `Deposit()` event and increase the value of the internal `deposits` variable.
123+
124+
Here is the code:
125+
126+
```solidity
127+
contract RecipientContract is IERC223Recipient {
128+
event Deposit(address whoSentTheTokens);
129+
uint256 deposits = 0;
130+
address tokenA; // The only token that we want to accept.
131+
function tokenReceived(address _from, uint _value, bytes memory _data) public override
132+
{
133+
// It is important to understand that within this function
134+
// msg.sender is the address of a token that is being received,
135+
// msg.value is always 0 as the token contract does not own or send Ether in most cases,
136+
// _from is the sender of the token transfer,
137+
// _value is the amount of tokens that was deposited.
138+
require(msg.sender == tokenA);
139+
deposits += _value;
140+
emit Deposit(_from);
141+
}
142+
}
143+
```
144+
145+
## Frequently asked questions {#faq}
146+
147+
### What will happen if we send some tokenB to the contract? {#sending-tokens}
148+
149+
The transaction will fail and the transfer of tokens will simply not happen. The tokens will be returned to the sender's address.
150+
151+
### How can we make a deposit to this contract? {#contract-deposits}
152+
153+
We can simply call the `transfer(address,uint256)` or `transfer(address,uint256,bytes)` function of the ERC-223 token and tell it to transfer some tokens to the address of the `RecipientContract`. That's it.
154+
155+
### What will happen if we transfer an ERC-20 token to this contract? {#erc-20-transfers}
156+
157+
The ERC-20 standard supports two methods of transferring tokens: `transfer` function and `approve + transferFrom` pattern. This is not possible to make a deposit with `transferFrom` function as the `RecipientContract` does not have any functions that subsequently call `transferFrom`. If an ERC-20 token is sent with `transfer` function to the address of the `RecipientContract` then unfortunately the tokens will be transferred from the sender's address to the address of the `RecipientContract` but the transfer will not be recognized i.e. `Deposit()` event will not be fired and `deposits` value will not change. There is also no way to filter or prevent unwanted ERC-20 deposits that are made with the `transfer` function.
158+
159+
### What if we want to execute some function after the token deposit is completed? {#function-execution}
160+
161+
There are multiple ways of doing so. In this example we will follow the method which makes ERC-223 transfers identical to Ether transfers:
162+
163+
```solidity
164+
contract RecipientContract is IERC223Recipient {
165+
event Foo();
166+
event Bar(uint256 someNumber);
167+
address tokenA; // The only token that we want to accept.
168+
function tokenReceived(address _from, uint _value, bytes memory _data) public override
169+
{
170+
require(msg.sender == tokenA);
171+
address(this).call(_data); // Handle incoming transaction and perform a subsequent function call.
172+
}
173+
function foo() public
174+
{
175+
emit Foo();
176+
}
177+
function bar(uint256 _someNumber) public
178+
{
179+
emit Bar(_someNumber);
180+
}
181+
}
182+
```
183+
184+
When the `RecipientContract` will receive a ERC-223 token the contract will execute a function encoded as `_data` parameter of the token transaction, identical to how Ether transactions encode function calls as transaction `data`. Read [the data field](https://ethereum.org/en/developers/docs/transactions/#the-data-field) for more information.
185+
186+
In the above example an ERC-223 token must be transferred to the address of the `RecipientContract` with the `transfer(address,uin256,bytes calldata _data)` function. If the data parameter will be `0xc2985578` (the signature of a `foo()` function) then the function foo() will be invoked after the token deposit is received and the event Foo() will be fired.
187+
188+
Parameters can be encoded in the `data` of the token transfer as well, for example we can call the bar() function with 12345 value for `_someNumber`. In this case the `data` must be `0x0423a13200000000000000000000000000000000000000000000000000000000000004d2` where `0x0423a132` is the signature of the `bar(uint256)` function and `00000000000000000000000000000000000000000000000000000000000004d2` is 12345 as uint256.
189+
190+
## Further reading {#further-reading}
191+
192+
- [EIP-223: ERC-223 Token Standard](https://eips.ethereum.org/EIPS/eip-223)
193+
- [Initial ERC-223 proposal](https://github.com/ethereum/eips/issues/223)

0 commit comments

Comments
 (0)