From 5baec85580cda5f2a6773a412e6a1af8e86fc92a Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 08:34:34 +0400 Subject: [PATCH 01/11] Create index.md --- .../docs/standards/tokens/erc-223/index.md | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/content/developers/docs/standards/tokens/erc-223/index.md diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md new file mode 100644 index 00000000000..3ac65e173a8 --- /dev/null +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -0,0 +1,155 @@ +--- +title: ERC-223 Token Standard +description: +lang: en +--- + +## Introduction {#introduction} + +**What is a Token?** + +Tokens can represent virtually anything in Ethereum: + +- reputation points in an online platform +- skills of a character in a game +- lottery tickets +- financial assets like a share in a company +- a fiat currency like USD +- an ounce of gold +- and more... + +Such a powerful feature of Ethereum must be handled by a robust standard, right? That's exactly +where the ERC-20 plays its role! This standard allows developers to build token applications that are interoperable with other products and services. + +**What is ERC-20?** + +The ERC-20 introduces a standard for Fungible Tokens, in other words, they have a property that makes each Token be exactly +the same (in type and value) as another Token. For example, an ERC-20 Token acts just like the ETH, meaning that 1 Token +is and will always be equal to all the other Tokens. + +## Prerequisites {#prerequisites} + +- [Accounts](/developers/docs/accounts) +- [Smart Contracts](/developers/docs/smart-contracts/) +- [Token standards](/developers/docs/standards/tokens/) +- [ERC-20](/developers/docs/standards/tokens/erc-20/) + +## Body {#body} + +The ERC-20 (Ethereum Request for Comments 20), proposed by Fabian Vogelsteller in November 2015, is a Token Standard that +implements an API for tokens within Smart Contracts. + +Example functionalities ERC-20 provides: + +- transfer tokens from one account to another +- get the current token balance of an account +- get the total supply of the token available on the network +- approve whether an amount of token from an account can be spent by a third-party account + +If a Smart Contract implements the following methods and events it can be called an ERC-20 Token Contract and, once deployed, it +will be responsible to keep track of the created tokens on Ethereum. + +From [EIP-20](https://eips.ethereum.org/EIPS/eip-20): + +#### Methods {#methods} + +```solidity +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 transferFrom(address _from, address _to, uint256 _value) public returns (bool success) +function approve(address _spender, uint256 _value) public returns (bool success) +function allowance(address _owner, address _spender) public view returns (uint256 remaining) +``` + +#### Events {#events} + +```solidity +event Transfer(address indexed _from, address indexed _to, uint256 _value) +event Approval(address indexed _owner, address indexed _spender, uint256 _value) +``` + +### Examples {#web3py-example} + +Let's see how a Standard is so important to make things simple for us to inspect any ERC-20 Token Contract on Ethereum. +We just need the Contract Application Binary Interface (ABI) to create an interface to any ERC-20 Token. As you can +see below we will use a simplified ABI, to make it a low friction example. + +#### Web3.py Example {#web3py-example} + +First, make sure you have installed [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation) Python library: + +``` +pip install web3 +``` + +```python +from web3 import Web3 + + +w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com")) + +dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI +weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Wrapped ether (WETH) + +acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 2 + +# This is a simplified Contract Application Binary Interface (ABI) of an ERC-20 Token Contract. +# It will expose only the methods: balanceOf(address), decimals(), symbol() and totalSupply() +simplified_abi = [ + { + 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}], + 'name': 'balanceOf', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'decimals', + 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'symbol', + 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'totalSupply', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + } +] + +dai_contract = w3.eth.contract(address=w3.toChecksumAddress(dai_token_addr), abi=simplified_abi) +symbol = dai_contract.functions.symbol().call() +decimals = dai_contract.functions.decimals().call() +totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals +addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals + +# DAI +print("===== %s =====" % symbol) +print("Total Supply:", totalSupply) +print("Addr Balance:", addr_balance) + +weth_contract = w3.eth.contract(address=w3.toChecksumAddress(weth_token_addr), abi=simplified_abi) +symbol = weth_contract.functions.symbol().call() +decimals = weth_contract.functions.decimals().call() +totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals +addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals + +# WETH +print("===== %s =====" % symbol) +print("Total Supply:", totalSupply) +print("Addr Balance:", addr_balance) +``` + +## Further reading {#further-reading} + +- [EIP-223: ERC-223 Token Standard](https://eips.ethereum.org/EIPS/eip-223) +- [Initial ERC-223 proposal](https://github.com/ethereum/eips/issues/223) From 00e50f5b8e4474972a0177766ee29d095e95e3a0 Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 08:58:23 +0400 Subject: [PATCH 02/11] First paragraph --- .../docs/standards/tokens/erc-223/index.md | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index 3ac65e173a8..3112563e98e 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -6,26 +6,17 @@ lang: en ## Introduction {#introduction} -**What is a Token?** +**What is ERC-223?** -Tokens can represent virtually anything in Ethereum: +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. -- reputation points in an online platform -- skills of a character in a game -- lottery tickets -- financial assets like a share in a company -- a fiat currency like USD -- an ounce of gold -- and more... +**How is it different from ERC-20 and why we need another token standard?** -Such a powerful feature of Ethereum must be handled by a robust standard, right? That's exactly -where the ERC-20 plays its role! This standard allows developers to build token applications that are interoperable with other products and services. +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: -**What is ERC-20?** - -The ERC-20 introduces a standard for Fungible Tokens, in other words, they have a property that makes each Token be exactly -the same (in type and value) as another Token. For example, an ERC-20 Token acts just like the ETH, meaning that 1 Token -is and will always be equal to all the other Tokens. +- Token transfer handling on the recipient's side. Recipient can detect that a ERC-223 token is being deposited. +- 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. +- The transfer of ERC-223 tokens may contain metadata, which allows arbitrary information to be attached to the token transactions. ## Prerequisites {#prerequisites} From 319090c057307772666543d56646f169b066198d Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 09:15:54 +0400 Subject: [PATCH 03/11] Update index.md --- .../docs/standards/tokens/erc-223/index.md | 107 +++--------------- 1 file changed, 18 insertions(+), 89 deletions(-) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index 3112563e98e..e8a5ce0027c 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -27,23 +27,20 @@ ERC-223 addresses some limitations of ERC-20 and introduces a new method of inte ## Body {#body} -The ERC-20 (Ethereum Request for Comments 20), proposed by Fabian Vogelsteller in November 2015, is a Token Standard that -implements an API for tokens within Smart Contracts. +The ERC-223 (Ethereum Request for Comments 223), proposed by Dexaran in March 2017, is a Token Standard that +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. -Example functionalities ERC-20 provides: - -- transfer tokens from one account to another -- get the current token balance of an account -- get the total supply of the token available on the network -- approve whether an amount of token from an account can be spent by a third-party account - -If a Smart Contract implements the following methods and events it can be called an ERC-20 Token Contract and, once deployed, it +If a Smart Contract implements the following methods and events it can be called a ERC-223 compatible token contract and, once deployed, it will be responsible to keep track of the created tokens on Ethereum. -From [EIP-20](https://eips.ethereum.org/EIPS/eip-20): +The contract is not obligated to have only this 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. + +From [EIP-223](https://eips.ethereum.org/EIPS/eip-223): #### Methods {#methods} +ERC-223 token must implement the following methods: + ```solidity function name() public view returns (string) function symbol() public view returns (string) @@ -51,94 +48,26 @@ 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 transferFrom(address _from, address _to, uint256 _value) public returns (bool success) -function approve(address _spender, uint256 _value) public returns (bool success) -function allowance(address _owner, address _spender) public view returns (uint256 remaining) +function transfer(address _to, uint256 _value, bytes calldata _data) public returns (bool success) ``` -#### Events {#events} +A contract that is supposed to receive ERC-223 tokens must implement the following method: ```solidity -event Transfer(address indexed _from, address indexed _to, uint256 _value) -event Approval(address indexed _owner, address indexed _spender, uint256 _value) +function tokenReceived(address _from, uint _value, bytes calldata _data) ``` -### Examples {#web3py-example} - -Let's see how a Standard is so important to make things simple for us to inspect any ERC-20 Token Contract on Ethereum. -We just need the Contract Application Binary Interface (ABI) to create an interface to any ERC-20 Token. As you can -see below we will use a simplified ABI, to make it a low friction example. +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. -#### Web3.py Example {#web3py-example} - -First, make sure you have installed [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation) Python library: +#### Events {#events} -``` -pip install web3 +```solidity +event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes calldata _data) ``` -```python -from web3 import Web3 - - -w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com")) - -dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI -weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Wrapped ether (WETH) - -acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 2 - -# This is a simplified Contract Application Binary Interface (ABI) of an ERC-20 Token Contract. -# It will expose only the methods: balanceOf(address), decimals(), symbol() and totalSupply() -simplified_abi = [ - { - 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}], - 'name': 'balanceOf', - 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], - 'stateMutability': 'view', 'type': 'function', 'constant': True - }, - { - 'inputs': [], - 'name': 'decimals', - 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}], - 'stateMutability': 'view', 'type': 'function', 'constant': True - }, - { - 'inputs': [], - 'name': 'symbol', - 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}], - 'stateMutability': 'view', 'type': 'function', 'constant': True - }, - { - 'inputs': [], - 'name': 'totalSupply', - 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], - 'stateMutability': 'view', 'type': 'function', 'constant': True - } -] - -dai_contract = w3.eth.contract(address=w3.toChecksumAddress(dai_token_addr), abi=simplified_abi) -symbol = dai_contract.functions.symbol().call() -decimals = dai_contract.functions.decimals().call() -totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals -addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals - -# DAI -print("===== %s =====" % symbol) -print("Total Supply:", totalSupply) -print("Addr Balance:", addr_balance) - -weth_contract = w3.eth.contract(address=w3.toChecksumAddress(weth_token_addr), abi=simplified_abi) -symbol = weth_contract.functions.symbol().call() -decimals = weth_contract.functions.decimals().call() -totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals -addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals - -# WETH -print("===== %s =====" % symbol) -print("Total Supply:", totalSupply) -print("Addr Balance:", addr_balance) -``` +### Examples {#web3py-example} + +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. ## Further reading {#further-reading} From 614c7f334ed4a63cf8140e95b682149e5d6bb43b Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 09:44:27 +0400 Subject: [PATCH 04/11] Example solidity --- .../docs/standards/tokens/erc-223/index.md | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index e8a5ce0027c..420ce161eb3 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -69,6 +69,89 @@ event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes 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. +### Examples {#solidity-example} + +The purpose of this example is to illustrate how a contract must work with ERC-223 tokens. + +Assume that we have a very basic ERC-223 token: + +```solidity +pragma solidity ^0.8.19; + +abstract contract IERC223Recipient { + function tokenReceived(address _from, uint _value, bytes memory _data) public virtual; +} + +contract VeryBasicERC223Token { + event Transfer(address indexed from, address indexed to, uint value, bytes data); + + string private _name; + string private _symbol; + uint8 private _decimals; + uint256 private _totalSupply; + + mapping(address => uint256) public balances; + + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { size := extcodesize(account) } + return size > 0; + } + function name() public view returns (string memory){ + return _name; + } + function symbol() public view returns (string memory){ + return _symbol; + } + function decimals() public view returns (uint8){ + return _decimals; + } + function totalSupply() public view returns (uint256){ + return _totalSupply; + } + function balanceOf(address _owner) public view returns (uint256){ + return balances[_owner]; + } + function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success){ + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + if(isContract(_to)) { + IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data); + } + emit Transfer(msg.sender, _to, _value, _data); + return true; + } + function transfer(address _to, uint _value) public returns (bool success){ + bytes memory _empty = hex"00000000"; + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + if(isContract(_to)) { + IERC223Recipient(_to).tokenReceived(msg.sender, _value, _empty); + } + emit Transfer(msg.sender, _to, _value, _empty); + return true; + } +} +``` + +Now we want another contract to accept deposits of `tokenA` assuming that tokenA is a 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. + +Here is the code: + +```solidity +contract Recipient is IERC223Recipient { + event Deposit(); + uint256 deposits = 0; + address tokenA; // The only token that we want to accept. + function tokenReceived(address _from, uint _value, bytes memory _data) public override + { + require(msg.sender == tokenA); + deposits += _value; + emit Deposit(); + } +} +``` + ## Further reading {#further-reading} - [EIP-223: ERC-223 Token Standard](https://eips.ethereum.org/EIPS/eip-223) From 7745caac01bb22d5e796ee748f1fd9f45c2344fc Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 09:46:20 +0400 Subject: [PATCH 05/11] Update code formatting --- .../docs/standards/tokens/erc-223/index.md | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index 420ce161eb3..479ff8cd946 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -97,21 +97,11 @@ contract VeryBasicERC223Token { assembly { size := extcodesize(account) } return size > 0; } - function name() public view returns (string memory){ - return _name; - } - function symbol() public view returns (string memory){ - return _symbol; - } - function decimals() public view returns (uint8){ - return _decimals; - } - function totalSupply() public view returns (uint256){ - return _totalSupply; - } - function balanceOf(address _owner) public view returns (uint256){ - return balances[_owner]; - } + function name() public view returns (string memory) { return _name; } + function symbol() public view returns (string memory) {return _symbol; } + function decimals() public view returns (uint8) { return _decimals; } + function totalSupply() public view returns (uint256) { return _totalSupply; } + function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; } function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success){ balances[msg.sender] = balances[msg.sender] - _value; balances[_to] = balances[_to] + _value; From 93fe8ee45ac1f3cff62d1dc176cd3b85839a7096 Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 09:47:32 +0400 Subject: [PATCH 06/11] Update code readability --- .../docs/standards/tokens/erc-223/index.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index 479ff8cd946..3fdf22bb1ff 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -90,18 +90,18 @@ contract VeryBasicERC223Token { uint8 private _decimals; uint256 private _totalSupply; - mapping(address => uint256) public balances; + mapping(address => uint256) private balances; + function name() public view returns (string memory) { return _name; } + function symbol() public view returns (string memory) {return _symbol; } + function decimals() public view returns (uint8) { return _decimals; } + function totalSupply() public view returns (uint256) { return _totalSupply; } + function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; } function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } - function name() public view returns (string memory) { return _name; } - function symbol() public view returns (string memory) {return _symbol; } - function decimals() public view returns (uint8) { return _decimals; } - function totalSupply() public view returns (uint256) { return _totalSupply; } - function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; } function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success){ balances[msg.sender] = balances[msg.sender] - _value; balances[_to] = balances[_to] + _value; From 310ab158dd024e5166311bdf134bc19fd5e6fa54 Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 09:50:34 +0400 Subject: [PATCH 07/11] Update the code --- .../developers/docs/standards/tokens/erc-223/index.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index 3fdf22bb1ff..f6ff9198c1a 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -130,14 +130,19 @@ Here is the code: ```solidity contract Recipient is IERC223Recipient { - event Deposit(); + event Deposit(address whoSentTheTokens); uint256 deposits = 0; address tokenA; // The only token that we want to accept. function tokenReceived(address _from, uint _value, bytes memory _data) public override { + // It is important to understand that within this function + // msg.sender is the address of a token that is being received, + // msg.value is always 0 as the token contract does not own or send Ether in most cases, + // _from is the sender of the token transfer, + // _value is the amount of tokens that was deposited. require(msg.sender == tokenA); deposits += _value; - emit Deposit(); + emit Deposit(_from); } } ``` From 7554c384f70ec8c225f0331b366e4540b1d16990 Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 09:58:59 +0400 Subject: [PATCH 08/11] Update index.md --- .../developers/docs/standards/tokens/erc-223/index.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index f6ff9198c1a..c1583d7a68d 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -129,7 +129,7 @@ Now we want another contract to accept deposits of `tokenA` assuming that tokenA Here is the code: ```solidity -contract Recipient is IERC223Recipient { +contract RecipientContract is IERC223Recipient { event Deposit(address whoSentTheTokens); uint256 deposits = 0; address tokenA; // The only token that we want to accept. @@ -147,6 +147,12 @@ contract Recipient is IERC223Recipient { } ``` +What will happen if we send some tokenB to the contract? - The transaction will fail and the transfer of tokens will simply not happen. The tokens will be returned to the sender's address. + +How can we make a deposit to this contract? - 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. + +What will happen if we transfer a ERC-20 token to this contract? - Well, 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 a 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. + ## Further reading {#further-reading} - [EIP-223: ERC-223 Token Standard](https://eips.ethereum.org/EIPS/eip-223) From 1641dd8e4c5974f126d1b39c880eb08c86ddc83f Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 10:20:03 +0400 Subject: [PATCH 09/11] Update index.md --- .../docs/standards/tokens/erc-223/index.md | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index c1583d7a68d..c50dea5071b 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -147,11 +147,37 @@ contract RecipientContract is IERC223Recipient { } ``` -What will happen if we send some tokenB to the contract? - The transaction will fail and the transfer of tokens will simply not happen. The tokens will be returned to the sender's address. +- **What will happen if we send some tokenB to the contract?** - The transaction will fail and the transfer of tokens will simply not happen. The tokens will be returned to the sender's address. +- **How can we make a deposit to this contract?** - 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. +- **What will happen if we transfer a ERC-20 token to this contract?** - Well, 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 a 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. +- **What if we want to execute some function after the token deposit is completed?** + +There are multiple ways of doing so. In this example we will follow the method which makes ERC-223 transfers identical to Ether transfers: + +```solidity +contract RecipientContract is IERC223Recipient { + event Foo(); + event Bar(); + address tokenA; // The only token that we want to accept. + function tokenReceived(address _from, uint _value, bytes memory _data) public override + { + require(msg.sender == tokenA); + address(this).call(_data); // Handle incoming transaction and perform a subsequent function call. + } + function foo() public + { + emit Foo(); + } + function bar() public + { + emit Bar(); + } +} +``` + +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. -How can we make a deposit to this contract? - 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. -What will happen if we transfer a ERC-20 token to this contract? - Well, 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 a 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. ## Further reading {#further-reading} From 45ef3f67409dcca3fb24059d8ee3b51a7f9176dc Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 10:25:49 +0400 Subject: [PATCH 10/11] Update index.md --- .../developers/docs/standards/tokens/erc-223/index.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/content/developers/docs/standards/tokens/erc-223/index.md b/src/content/developers/docs/standards/tokens/erc-223/index.md index c50dea5071b..d6457fbb1d6 100644 --- a/src/content/developers/docs/standards/tokens/erc-223/index.md +++ b/src/content/developers/docs/standards/tokens/erc-223/index.md @@ -157,7 +157,7 @@ There are multiple ways of doing so. In this example we will follow the method w ```solidity contract RecipientContract is IERC223Recipient { event Foo(); - event Bar(); + event Bar(uint256 someNumber); address tokenA; // The only token that we want to accept. function tokenReceived(address _from, uint _value, bytes memory _data) public override { @@ -168,16 +168,18 @@ contract RecipientContract is IERC223Recipient { { emit Foo(); } - function bar() public + function bar(uint256 _someNumber) public { - emit Bar(); + emit Bar(_someNumber); } } ``` 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. +In the above example a 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. +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. ## Further reading {#further-reading} From 16728772cce588c6345c73713d9d67c31e0b95c8 Mon Sep 17 00:00:00 2001 From: Dexaran Date: Tue, 7 Mar 2023 10:29:53 +0400 Subject: [PATCH 11/11] Update standards section --- src/content/developers/docs/standards/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/content/developers/docs/standards/index.md b/src/content/developers/docs/standards/index.md index cc58fce6ec0..edb849441ab 100644 --- a/src/content/developers/docs/standards/index.md +++ b/src/content/developers/docs/standards/index.md @@ -40,10 +40,11 @@ More detailed information on these different types and categories can be found i ### Token standards {#token-standards} - [ERC-20](/developers/docs/standards/tokens/erc-20/) - A standard interface for fungible (interchangeable) tokens, like voting tokens, staking tokens or virtual currencies. - - [ERC-1363](https://eips.ethereum.org/EIPS/eip-1363) - Defines a token interface for ERC-20 tokens that supports executing recipient code after transfer or transferFrom, or spender code after approve + - [ERC-1363](https://eips.ethereum.org/EIPS/eip-1363) - Defines a token interface for ERC-20 tokens that supports executing recipient code after transfer or transferFrom, or spender code after approve. +- [ERC-223](/developers/docs/standards/tokens/erc-223/) - A fungible tokens standard that makes tokens behave identical to plain Ether and supports token transfers handling on the recipients side. - [ERC-721](/developers/docs/standards/tokens/erc-721/) - A standard interface for non-fungible tokens, like a deed for artwork or a song. - [ERC-2309](https://eips.ethereum.org/EIPS/eip-2309) - A standardized event emitted when creating/transferring one, or many non-fungible tokens using consecutive token identifiers. - - [ERC-4400](https://eips.ethereum.org/EIPS/eip-4400) - Interface extension for EIP-721 consumer role + - [ERC-4400](https://eips.ethereum.org/EIPS/eip-4400) - Interface extension for EIP-721 consumer role. - [ERC-4907](https://eips.ethereum.org/EIPS/eip-4907) - Add a time-limited role with restricted permissions to ERC-721 tokens. - [ERC-777](/developers/docs/standards/tokens/erc-777/) - **(NOT RECOMMENDED)** A token standard improving over ERC-20. - [ERC-1155](/developers/docs/standards/tokens/erc-1155/) - A token standard which can contain both fungible and non-fungible assets.