Weiter zum Hauptinhalt
Change page

ERC-223 Token-Standard

Seite zuletzt aktualisiert: 6. September 2025

Einführung

Was ist ERC-223?

ERC-223 ist ein Standard für Fungible Tokens, ähnlich dem ERC-20-Standard. Der Hauptunterschied besteht darin, dass ERC-223 nicht nur die Token-API definiert, sondern auch die Logik für die Übertragung von Token vom Absender zum Empfänger. Es führt ein Kommunikationsmodell ein, das ermöglicht, dass Token-Übertragungen auf der Empfängerseite verarbeitet werden können.

Unterschiede zu ERC-20

ERC-223 behebt einige Einschränkungen von ERC-20 und führt eine neue Methode der Interaktion zwischen dem Token-Contract und einem Contract, der Token empfangen kann, ein. Es gibt einige Dinge, die mit ERC-223 möglich sind, nicht jedoch mit ERC-20:

  • Verarbeitung von Token-Übertragungen auf der Empfängerseite: Empfänger können erkennen, dass ein ERC-223-Token eingezahlt wird.
  • Ablehnung falsch gesendeter Token: Wenn ein Nutzer ERC-223-Token an einen Contract sendet, der keine Token empfangen soll, kann der Contract die Transaktion ablehnen und so Token-Verluste verhindern.
  • Metadaten in Übertragungen: ERC-223-Token können Metadaten enthalten, wodurch beliebige Informationen an Token-Transaktionen angehängt werden können.

Voraussetzungen

Hauptteil

ERC-223 ist ein Token-Standard, der eine Programmierschnittstelle (API) für Token innerhalb von Smart Contracts implementiert. Zudem legt er eine API für Contracts fest, die ERC-223-Tokens empfangen sollen. Contracts, die die ERC-223-Empfänger-API nicht unterstützen, können keine ERC-223-Token empfangen, wodurch Nutzerfehler vermieden werden.

Ein Smart Contract kann als ERC-223-kompatibler Token-Contract bezeichnet werden, wenn er die folgenden Methoden und Ereignisse implementiert. Nach der Bereitstellung ist er dafür verantwortlich, die erstellten Token auf Ethereum zu verwalten.

Der Contract ist nicht verpflichtet, ausschließlich diese Funktionen zu enthalten; Entwickler:innen können beliebige weitere Funktionen aus anderen Token-Standards hinzufügen. Beispielsweise gehören die Funktionen approve und transferFrom nicht zum ERC-223-Standard, können jedoch bei Bedarf implementiert werden.

Von EIP-223 (opens in a new tab):

Methoden

ERC-223-Token müssen die folgenden Methoden implementieren:

1function name() public view returns (string)
2function symbol() public view returns (string)
3function decimals() public view returns (uint8)
4function totalSupply() public view returns (uint256)
5function balanceOf(address _owner) public view returns (uint256 balance)
6function transfer(address _to, uint256 _value) public returns (bool success)
7function transfer(address _to, uint256 _value, bytes calldata _data) public returns (bool success)

Ein Contract, der ERC-223-Token empfangen soll, muss die folgende Methode implementieren:

1function tokenReceived(address _from, uint _value, bytes calldata _data)

Wenn ERC-223-Token an einen Contract gesendet werden, der die Funktion tokenReceived(..) nicht implementiert, muss die Übertragung fehlschlagen und die Token dürfen nicht vom Guthaben des Absenders abgebucht werden.

Ereignisse

1event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes calldata _data)

Beispiele

Die API des ERC-223-Tokens ist ähnlich der von ERC-20, sodass es aus Sicht der UI-Entwicklung keinen Unterschied gibt. Die einzige Ausnahme ist hier, dass ERC-223-Token möglicherweise keine approve + transferFrom-Funktionen haben, da diese für diesen Standard optional sind.

Solidity-Beispiele

Das folgende Beispiel veranschaulicht, wie ein einfacher ERC-223-Token-Contract funktioniert:

1pragma solidity ^0.8.19;
2abstract contract IERC223Recipient {
3 function tokenReceived(address _from, uint _value, bytes memory _data) public virtual;
4}
5contract VeryBasicERC223Token {
6 event Transfer(address indexed from, address indexed to, uint value, bytes data);
7 string private _name;
8 string private _symbol;
9 uint8 private _decimals;
10 uint256 private _totalSupply;
11 mapping(address => uint256) private balances;
12 function name() public view returns (string memory) { return _name; }
13 function symbol() public view returns (string memory) {return _symbol; }
14 function decimals() public view returns (uint8) { return _decimals; }
15 function totalSupply() public view returns (uint256) { return _totalSupply; }
16 function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; }
17 function isContract(address account) internal view returns (bool) {
18 uint256 size;
19 assembly { size := extcodesize(account) }
20 return size > 0;
21 }
22 function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success){
23 balances[msg.sender] = balances[msg.sender] - _value;
24 balances[_to] = balances[_to] + _value;
25 if(isContract(_to)) {
26 IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data);
27 }
28 emit Transfer(msg.sender, _to, _value, _data);
29 return true;
30 }
31 function transfer(address _to, uint _value) public returns (bool success){
32 bytes memory _empty = hex"00000000";
33 balances[msg.sender] = balances[msg.sender] - _value;
34 balances[_to] = balances[_to] + _value;
35 if(isContract(_to)) {
36 IERC223Recipient(_to).tokenReceived(msg.sender, _value, _empty);
37 }
38 emit Transfer(msg.sender, _to, _value, _empty);
39 return true;
40 }
41}
Alles anzeigen

Nun soll ein anderer Contract Einzahlungen von tokenA annehmen, vorausgesetzt, tokenA ist ein ERC-223-Token. Der Contract darf nur tokenA annehmen und alle anderen Token ablehnen. Wenn der Contract tokenA empfängt, muss er ein Deposit()-Ereignis auslösen und den Wert der internen Variable deposits erhöhen.

Hier ist der Code:

1contract RecipientContract is IERC223Recipient {
2 event Deposit(address whoSentTheTokens);
3 uint256 deposits = 0;
4 address tokenA; // Der einzige Token, den wir akzeptieren wollen.
5 function tokenReceived(address _from, uint _value, bytes memory _data) public override
6 {
7 // Es ist wichtig zu verstehen, dass innerhalb dieser Funktion
8 // msg.sender die Adresse des Tokens ist, der empfangen wird,
9 // msg.value immer 0 ist, da der Token-Contract in den meisten Fällen keinen Ether besitzt oder sendet,
10 // _from der Absender der Token-Übertragung ist,
11 // _value die Menge der eingezahlten Token ist.
12 require(msg.sender == tokenA);
13 deposits += _value;
14 emit Deposit(_from);
15 }
16}
Alles anzeigen

Häufig gestellte Fragen

Was passiert, wenn wir tokenB an den Contract senden?

Die Transaktion wird fehlschlagen, und die Übertragung der Token wird nicht stattfinden. Die Token werden an die Adresse des Absenders zurückgegeben.

Wie können wir eine Einzahlung an diesen Contract tätigen?

Rufen Sie die Funktion transfer(address,uint256) oder transfer(address,uint256,bytes) des ERC-223-Tokens auf und geben Sie dabei die Adresse des RecipientContract an.

Was geschieht, wenn wir einen ERC-20-Token an diesen Contract überweisen?

Wenn ein ERC-20-Token an den RecipientContract gesendet wird, werden die Token zwar übertragen, die Übertragung wird jedoch nicht erkannt (es wird kein Deposit()-Event ausgelöst und der Einzahlungswert ändert sich nicht). Unerwünschte ERC-20-Einzahlungen können nicht gefiltert oder verhindert werden.

Was, wenn wir nach Abschluss der Token-Einzahlung eine bestimmte Funktion ausführen möchten?

Dafür gibt es mehrere Möglichkeiten. In diesem Beispiel folgen wir der Methode, die ERC-223-Übertragungen mit Ether-Übertragungen identisch macht:

1contract RecipientContract is IERC223Recipient {
2 event Foo();
3 event Bar(uint256 someNumber);
4 address tokenA; // Der einzige Token, den wir akzeptieren wollen.
5 function tokenReceived(address _from, uint _value, bytes memory _data) public override
6 {
7 require(msg.sender == tokenA);
8 address(this).call(_data); // Eingehende Transaktion verarbeiten und einen nachfolgenden Funktionsaufruf durchführen.
9 }
10 function foo() public
11 {
12 emit Foo();
13 }
14 function bar(uint256 _someNumber) public
15 {
16 emit Bar(_someNumber);
17 }
18}
Alles anzeigen

Wenn der RecipientContract einen ERC-223-Token empfängt, führt der Contract eine Funktion aus, die als _data-Parameter der Token-Transaktion kodiert ist, genauso wie Ether-Transaktionen Funktionsaufrufe als Transaktions-data kodieren. Lesen Sie das Datenfeld für weitere Informationen.

Im obigen Beispiel muss ein ERC-223-Token mit der Funktion transfer(address,uin256,bytes calldata _data) an die Adresse des RecipientContract gesendet werden. Wenn der data-Parameter den Wert 0xc2985578 (die Signatur der Funktion foo()) enthält, wird die Funktion foo() nach dem Empfang der Token-Einzahlung aufgerufen und das Ereignis Foo() ausgelöst.

Parameter können ebenfalls im data-Feld der Token-Überweisung kodiert werden. Beispielsweise lässt sich die Funktion bar() mit dem Wert 12345 für den Parameter _someNumber aufrufen. In diesem Fall muss data den Wert 0x0423a13200000000000000000000000000000000000000000000000000000000000004d2 haben, wobei 0x0423a132 die Signatur der bar(uint256)-Funktion ist und 00000000000000000000000000000000000000000000000000000000000004d2 12345 als uint256 darstellt.

Einschränkungen

Obwohl ERC-223 mehrere Probleme des ERC-20-Standards behebt, hat er auch seine eigenen Einschränkungen:

  • Verbreitung und Kompatibilität: ERC-223 ist noch nicht weit verbreitet, was seine Kompatibilität mit bestehenden Tools und Plattformen einschränken kann.
  • Abwärtskompatibilität: ERC-223 ist nicht abwärtskompatibel zu ERC-20, was bedeutet, dass bestehende ERC-20-Contracts und -Tools ohne Änderungen nicht mit ERC-223-Token funktionieren.
  • Gaskosten: Die zusätzlichen Überprüfungen und Funktionalitäten bei ERC-223-Übertragungen können im Vergleich zu ERC-20-Transaktionen zu höheren Gaskosten führen.

Weiterführende Lektüre

War dieser Artikel hilfreich?