# Solidity: Programmiersprache für Smart Contracts

Mit Solidity lassen sich ausgefeilte **Smart Contracts für den Betrieb auf der Ethereum-[Blockchain](https://www.ionos.de/digitalguide/online-marketing/verkaufen-im-internet/blockchain/ "Blockchain") programmieren**. Die Sprache bietet einige interessante Ansätze, die sie von anderen Sprachen abheben.

## Was ist Solidity?

Solidity ist eine High-Level-Programmiersprache für die Erstellung von Smart Contracts auf der Ethereum-Blockchain. Bei Smart Contracts, zu Deutsch „intelligente Verträge“, handelt es sich um **selbstausführende Verträge, die den Austausch von Vermögenswerten zwischen Parteien automatisieren**. Das Besondere dabei ist, dass keine Mittelsleute benötigt werden, um die Einhaltung des Smart Contract sicherzustellen.

Solidity-[Quellcode](https://www.ionos.de/digitalguide/websites/web-entwicklung/quellcode/ "Quellcode") wird in Bytecode kompiliert und **auf der Ethereum-Blockchain als Smart Contract bereitgestellt**. Ist dies geschehen, lässt sich der Smart Contract von jedem Knoten im Netzwerk ausführen, wobei der Zustand auf der Blockchain gespeichert wird. Wir zeigen exemplarisch einen simplen Vertrag, der eine NFT-Verkaufsmaschine modelliert:

```solidity
pragma Solidity 0.8.7;
contract NFTVendingMachine {
    // Declare state variables
    address public owner;
    mapping (address => uint) public nftBalance;
    // Run on deployment
    constructor() {
        owner = msg.sender;
        nftBalance[address(this)] = 100;
    }
    // Allow the owner to restock the NFT balance
    function restock(uint amount) public {
        require(msg.sender == owner, "Only the owner can restock.");
        nftBalance[address(this)] += amount;
    }
    // Allow anyone to purchase NFTs
    function purchase(uint amount) public payable {
        require(msg.value >= amount * 1 ether, "You must pay at least 1 ETH per NFT");
        require(nftBalance[address(this)] >= amount, "Not enough NFTs in stock to complete this purchase");
        nftBalance[address(this)] -= amount;
        nftBalance[msg.sender] += amount;
    }
}
```

## Für welche Anwendungen kommt Solidity zum Einsatz?

Solidity wurde speziell für die **Erstellung von dezentralen Anwendungen** („Distributed Applications“, [DApps](https://www.ionos.de/digitalguide/websites/web-entwicklung/dapp/) konzipiert, die auf der Ethereum Virtual Machine (EVM) betrieben werden. Smart Contracts eignen sich u. a. für das Verwalten digitaler Assets, die Erstellung von dezentralen Börsen und die Implementierung von Abstimmungssystemen.

### Dezentrale Finanzen (DeFi)

Solidity kommt zum Einsatz für die Entwicklung von DeFi-Anwendungen wie **dezentralen Börsen, Kredit- und Verleihplattformen, Vorhersagemärkten und [Kryptowährungen](https://www.ionos.de/digitalguide/online-marketing/verkaufen-im-internet/kryptowaehrung/ "Kryptowährungen")**. DeFi hat sich zu einem der beliebtesten Anwendungsfälle für Blockchain-Technologie entwickelt. Solidity ist dabei zu einem unverzichtbaren Werkzeug zum Aufbau von DeFi-Anwendungen im Ethereum-Netzwerk geworden.

### Non-Fungible Tokens

Das [Non-Fungible Token](https://www.ionos.de/digitalguide/online-marketing/verkaufen-im-internet/nft-non-fungible-token/ "NFT - Non-Fungible Token") (NFT), zu Deutsch „nicht austauschbares Token“, erfreut sich seit den 2020er Jahren großer Beliebtheit. NFTs sind einzigartige digitale Assets, die auf der Blockchain gespeichert sind. Dabei kann es sich etwa um **digitale Kunstwerke, Sportmemorabilia oder Artefakte aus der Gaming-Industrie** handeln. Solidity wird verwendet, um die Smart Contracts zu erstellen, die NFTs antreiben.

### Lieferkettenmanagement

Mithilfe von Solidity lassen sich Smart Contracts zur **Überwachung und Verwaltung von Lieferketten** erstellen. Die Verträge kommen zum Einsatz, um verschiedene Prozesse der Lieferkette zu automatisieren. Dazu zählen die Verfolgung der Warenbewegung, die Überprüfung der Echtheit von Produkten und die Abwicklung von Zahlungen zwischen den Parteien.

### Abstimmungssysteme

Mit Solidity lassen sich Smart Contracts erstellen, die **sichere und transparente Abstimmungssysteme auf der Blockchain implementieren**. Die Verträge können verwendet werden, um sicherzustellen, dass Stimmen korrekt gezählt und dass der Abstimmungsprozess fair und transparent ist.

## Welche Vor- und Nachteile hat Solidity?

Insgesamt ist Solidity eine leistungsstarke Sprache zum Erstellen von Smart Contracts auf der Ethereum-Blockchain. Wie jede Technologie hat Solidity jedoch spezifische Vor- und Nachteile, deren sich Entwickler und Entwicklerinnen beim Erstellen von Smart Contracts bewusst sein sollten. In jedem Fall erfordert die Entwicklung sicherer Smart Contracts ein gewisses Maß an **Fachwissen und Sorgfalt**.

Exemplarisch zeigen wir einen **Smart Contract, der als schwarzes Loch fungiert**: Jeglicher an den Contract gesendete Ether wird unwiederbringlich geschluckt. Es besteht keine Möglichkeit, den Ether wieder auszuzahlen:

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.9.0;
// This contract swallows all Ether sent to it
contract Blackhole {
    event Received(address, uint);
    receive() external payable {
            emit Received(msg.sender, msg.value);
    }
}
```

### Vorteile von Solidity

- **Flexibilität**: Solidity ist eine vielseitige Sprache. Sie lässt sich verwenden, um ganz unterschiedliche Smart Contracts mit einer Vielzahl an Anwendungsfällen zu entwickeln.
- **Sicherheit**: Solidity wurde mit Blick auf Sicherheit entwickelt. Die Sprache enthält Funktionen wie Zugriffskontrollen, Ausnahmebehandlung und Ausfallmechanismen, die Entwicklern und Entwicklerinnen helfen, sichere Verträge zu schreiben.
- **Ethereum-Kompatibilität**: Solidity ist die derzeitig vorrangige Sprache zur Erstellung von Smart Contracts auf der Ethereum-Blockchain.
- **Ausgeprägte Community**: Rund um Solidity existiert eine große Community von Blockchain-Entwicklern und -Entwicklerinnen. So finden sich zahlreiche Ressourcen zum Lernen und Lösen von Problemen.

### Nachteile von Solidity

- **Lernkurve**: Solidity hat eine relativ steile Lernkurve für Entwickler und Entwicklerinnen, die neu in der Blockchain- und Smart-Contract-Entwicklung sind.
- **Unveränderlichkeit**: Sobald ein Smart Contract auf der Blockchain bereitgestellt wird, kann er nicht weiter verändert werden. Daraus folgt, dass Entwickler und Entwicklerinnen beim Schreiben und Testen äußerst vorsichtig sein müssen.
- **Fehlende formale Überprüfung**: Solidity verfügt über keine integrierten Tools zur formalen Überprüfung des Codes. Das bedeutet, dass Entwickler und Entwicklerinnen auf externe Tools angewiesen sind, um die Korrektheit ihrer Verträge sicherzustellen.
- **Begrenztes Tooling**: Soliditys Tooling-Ökosystem ist noch relativ wenig ausgeprägt. Daraus ergeben sich möglicherweise Probleme mit IDEs, Test-Frameworks und anderen Entwicklungstools.

## Wie sieht die grundlegende Syntax von Solidity aus?

Solidity ist eine **auf Smart Contracts spezialisierte, objektorientierte Sprache**, die von JavaScript, Python und C++ beeinflusst wurde. Die Syntax der Sprache ähnelt JavaScript, wobei es einige interessante Eigenheiten gibt.

### Variablen in Solidity

Zunächst scheinen Variablen in Solidity genauso zu funktionieren wie in vergleichbaren Sprachen. Jedoch ergibt sich ein wichtiger Unterschied daraus, dass die Ethereum Virtual Machine (EVM) als Ausführungsumgebung zum Einsatz kommt. Alle **Operationen auf der EVM sowie die Speicherung von Daten kosten eine gewisse Menge „Gas“**. D. h. man muss bei der Programmierung ggf. abwägen, wie eine Operation möglichst effizient implementiert werden kann.

Neben „normalen“ Variablen kennt Solidity **Konstanten, die bei der Kompilierung definiert** sein müssen. Konstanten benötigen weniger Gas für die Speicherung:

```solidity
// Regular variable can be declared without defining
int a;
// Constant needs to be defined at declaration
int constant b = 51;
```

Ähnlich verhält es sich mit den `immutable`-Variablen. Diese verbrauchen ebenfalls weniger Gas und **lassen sich nach der Zuweisung nicht verändern**. Im Gegensatz zu `constant`-Variablen darf die Zuweisung zur Laufzeit erfolgen.

### Kontrollanweisungen in Solidity

Als imperative Programmiersprache unterstützt Solidity die bekannten Kontrollanweisungen, etwa **Verzweigungen und Schleifen**. Wir zeigen den Code zur Auswahl der größeren von zwei Zahlen, `a` und `b`:

```solidity
int largerNumber = 0;
// If-else statement
if (a > b) {
    largerNumber = a;
} else {
        largerNumber = b;
}
```

Die **`for`-Schleife in Solidity** entspricht der aus aus JavaScript oder C++ bekannten Syntax:

```solidity
// Loop 10 times
for (int i = 0; i < 10; i++) {
    // …
}
```

Auch die **`while`-Schleife funktioniert wie gewohnt**. Wir kombinieren eine Abbruchbedingung mit einer numerischen Counter-Variable:

```solidity
bool continueLoop = true;
int counter = 0;
// Loop at most 10 times
while (continueLoop && counter < 10) {
    // …
    counter++;
}
```

### Simple Typen in Solidity

Solidity ist eine **statisch-typisierte Sprache** und unterstützt die üblicherweise in Programmiersprachen vorhandenen Typen. Zu den simplen Typen, die einzelne Werte abbilden, gehören Booleans, Zahlen und Strings.

Booleans in Solidity bilden die Werte `true` und `false` ab. Sie lassen sich über die **einschlägig bekannten booleschen Operatoren** verknüpfen und in `if`-Anweisungen einsetzen:

```solidity
bool paymentReceived = true;
bool itemsStocked = true;
bool continueTransaction = paymentReceived && itemsStocked;
if (continueTransaction) {
    // ...
}
```

Solidity unterstützt ein **breites Spektrum numerischer Typen**. Bei Integer-Zahlen lässt sich zwischen signierten (`int`) und unsignierten (`uint`) Zahlen unterscheiden, wobei letztere nur positiv sein dürfen. Ferner lässt sich der Bereich einer Zahl in Schritten von 8 bit festlegen, von `int8` über `int16` bis hin zu `int265`:

```solidity
uint8 smallNumber = 120;
int8 negativeNumber = -125;
int8 result = smallNumber + negativeNumber;
assert(result == -5)
```

Strings kommen in Solidity vor allem beim Erzeugen von Statusmeldungen zum Einsatz. Die Sprache unterstützt **einzelne und doppelte Anführungszeichen** sowie Unicode-Zeichen:

```Solidity
string message = 'Hello World';
string success = unicode"Transfer sent";
```

### Funktionen in Solidity

Wie in den meisten Programmiersprachen sind **Funktionen ein zentraler Bestandteil von Solidity**. Die Definition einer Funktion erinnert an JavaScript, wobei die Typen der Argumente explizit angegeben werden müssen. Ferner kommt ein `returns`-Schlüsselwort zum Einsatz, um die Typen der Rückgabewerte auszuzeichnen:

```solidity
// Define a function
function addNumbers(int a, int b) returns (int) {
    return a + b;
}
```

Der **Aufruf einer Funktion** erfolgt wie gewohnt:

```solidity
// Call the function
int result = addNumbers(2, 3);
```

Interessanterweise lassen sich **analog zu den benannten Argumenten auch die Rückgabewerte benennen**. In diesem Fall genügt das Zuweisen der entsprechenden Variablen im Körper der Funktion. Eine explizite Rückgabe per `return` ist dann nicht erforderlich:

```solidity
function divideNumbers(int dividend, int divisor) returns (int quotient) {
    quotient = dividend / divisor;
    // No `return` necessary
}
```

Ähnlich wie `constant`- oder `immutable`-Variablen lassen sich in Solidity **Funktionen als nicht zustandsverändernd markieren**. Dabei kommen die Schlüsselwörter `view` und `pure` zum Einsatz. Eine `view`-Funktion verändert den Zustand nicht, während eine `pure`-Funktion zusätzlich garantiert, keine Zustands-Variablen auszulesen.

### Smart Contracts in Solidity

Neben den gängigen Typen kennt Solidity eine Handvoll **auf Smart Contracts spezialisierter Typen**. Der grundlegende Typ ist `address` und bildet Ethereum-Adressen ab. Adressen, die `payable` sind, können Transfers in Ether erhalten. Dazu stellen `payable`-Adressen die Methoden `balance()` und `transfer()` bereit.

```solidity
// Get address of this contract
address mine = address(this);
// Get payable external address
address payable other = payable(0x123);
// Transfer if balances fulfill conditions
if (other.balance < 10 && mine.balance >= 100) {
    other.transfer(10);
}
```

Aufbauend auf dem `address`-Typ gibt es den `contract`-Typ als zentrales Sprachkonstrukt. **Contracts entsprechen in etwa Klassen in objektorientierten Programmiersprachen**. So bündeln Contracts Zustandsdaten und Funktionen und schirmen diese von der Außenwelt ab. Dabei unterstützen Contracts multiple Vererbung, wie aus Python oder C++ bekannt.

Contracts **beginnen für gewöhnlich mit einer `pragma`-Zeile**, die die zulässige Solidity-Version angibt, gefolgt von der eigentlichen Definition:

```solidity
// Make sure Solidity version matches
pragma Solidity >=0.7.1 <0.9.0;
// Contract definition
contract Purchase {
    // Public state variables
    address seller;
    address buyer;
    
    // View-function
    function getSeller() external view returns (address) {
        return seller;
    }
}
```

Smart Contracts können **Zustandsdaten und Funktionen definieren**. Wie aus C++ und Java bekannt, lässt sich jeweils eine von drei Zugriffsstufen festlegen:

- `public`: Auf die Variable kann von **innerhalb des Contracts lesend und schreibend zugegriffen** werden. Zusätzlich wird automatisch eine `view`-Funktion als Getter für den lesenden Zugriff von außen erzeugt.
- `internal`: Die Variable ist **von jeglichem äußeren Zugriff abgeschirmt**. Von innerhalb des Contracts sowie aus erbenden Contracts kann lesend und schreibend zugegriffen werden.
- `private`: wie `internal`, jedoch besteht **kein Zugriff aus erbenden Contracts**

Funktionen lassen sich ferner als `external` auszeichnen. Eine `external`-Funktion **fungiert als Teil der Contract-Schnittstelle** und dient für den Zugriff von außen. Die wichtige `receive`-Funktion für den Empfang von Ether ist ein bekanntes Beispiel:

```solidity
// Define without `function` keyword
receive() external payable {
    // Handle Ether
}
```

### Modifiers in Solidity

Mit den Modifiers existiert ein interessantes Sprachkonstrukt in Solidity. Die Funktionalität erinnert an Pythons Decorators; wie dort kommen Modifiers zum Einsatz, um den **Aufruf einer Funktion zu modifizieren**. Sie werden häufig genutzt, um sicherzustellen, dass vor dem Ausführen einer Funktion eine Bedingung erfüllt ist:

```solidity
contract Sale {
    uint price;
    address payable owner;
    modifier onlyOwner {
        // Will throw error if called by anyone other than the owner
        require(
            msg.sender == owner,
            "Only owner can call this function."
        );
        // The wrapped function's body is inserted here
        _;
    }
    
    // `onlyOwner` wraps `changePrice`
    function changePrice(uint newPrice) public onlyOwner {
        // We'll only get here if the owner called this function
        price = newPrice;
    }
}
```

### Transaktions-Management mit Solidity

Solidity verfügt über ein eingebautes Transaktions-Management. So lässt sich sicherstellen, dass ein **Ether-Transfer entweder komplett oder gar nicht abgewickelt** wird. Die Sprache kennt dafür das spezielle `revert`-Schlüsselwort, das ein „roll-back“ einer Transaktion auslöst. Per `error`-Schlüsselwort lassen sich eigene Fehlercodes definieren:

```solidity
// Custom error definition
error InsufficientPayment(uint256 paid, uint256 required);
// Contract representing a sale
contract Sale {
    uint price;
    // Purchase if enough ether transferred
    function purchase() public payable {
        if (msg.value < price) {
            revert InsufficientPayment(msg.value, price);
        }
        // Complete purchase
    }
}
```

Ein weiteres **häufig anzutreffendes Muster** ist der Einsatz der `require()`-Funktion. Diese lässt sich analog zu `revert` verwenden:

```solidity
// Using `require()` function
if (!condition) revert("Error message");
// Equivalent to
require(condition, "Error message");
```


This is a markdown version of: [https://www.ionos.de/digitalguide/websites/web-entwicklung/solidity-programmiersprache/](https://www.ionos.de/digitalguide/websites/web-entwicklung/solidity-programmiersprache/) for AI/LLM consumption.