What is a smart contract? What is a hybrid smart contract?

When deployed to a blockchain, a smart contract is a set of instructions that can be executed without intervention from third parties. The smart contract code defines how it responds to input, just like the code of any other computer program.

A valuable feature of smart contracts is that they can store and manage on-chain assets (like ETH or ERC20 tokens), just like you can with an Ethereum wallet. Because they have an on-chain address like a wallet, they can do everything any other address can. This enables you to program automated actions when receiving and transferring assets.

Smart contracts can connect to real-world market prices of assets to produce powerful applications. Securely connecting smart contracts with off-chain data and services is what makes them hybrid smart contracts. This is done using oracles.

A Simple Smart Contract

Let us begin with a basic example that sets the value of a variable and exposes it for other contracts to access. It is fine if you do not understand everything right now, we will go into more detail later.

Storage Example

*// SPDX-License-Identifier: GPL-3.0*
**pragma solidity** >=**0.4.16** <**0.9.0**;

**contract** **SimpleStorage** {
    uint storedData;

    function set(uint x) public {
        storedData = x;
    }

    function get() public view returns (uint) {
        return storedData;
    }
}

The first line tells you that the source code is licensed under the GPL version 3.0. Machine-readable license specifiers are important in a setting where publishing the source code is the default.

The next line specifies that the source code is written for Solidity version 0.4.16, or a newer version of the language up to, but not including version 0.9.0. This is to ensure that the contract is not compilable with a new (breaking) compiler version, where it could behave differently. Pragmas are common instructions for compilers about how to treat the source code (e.g. pragma once).

A contract in the sense of Solidity is a collection of code (its functions) and data (its state) that resides at a specific address on the Ethereum blockchain. The line uint storedData; declares a state variable called storedData of type uint (unsigned integer of 256 bits). You can think of it as a single slot in a database that you can query and alter by calling functions of the code that manages the database. In this example, the contract defines the functions set and get that can be used to modify or retrieve the value of the variable.

To access a member (like a state variable) of the current contract, you do not typically add the this. prefix, you just access it directly via its name. Unlike in some other languages, omitting it is not just a matter of style, it results in a completely different way to access the member, but more on this later.

This contract does not do much yet apart from (due to the infrastructure built by Ethereum) allowing anyone to store a single number that is accessible by anyone in the world without a (feasible) way to prevent you from publishing this number. Anyone could call set again with a different value and overwrite your number, but the number is still stored in the history of the blockchain. Later, you will see how you can impose access restrictions so that only you can alter the number.

Warning

Be careful with using Unicode text, as similar looking (or even identical) characters can have different code points and as such are encoded as a different byte array.

Note

All identifiers (contract names, function names and variable names) are restricted to the ASCII character set. It is possible to store UTF-8 encoded data in string variables.

Subcurrency Example

The following contract implements the simplest form of a cryptocurrency. The contract allows only its creator to create new coins (different issuance schemes are possible). Anyone can send coins to each other without a need for registering with a username and password, all you need is an Ethereum keypair.

*// SPDX-License-Identifier: GPL-3.0*
**pragma solidity** ^**0.8.4**;

**contract** **Coin** {
    *// The keyword "public" makes variables*    
		*// accessible from other contracts*    
	address **public** minter;
	mapping (address => uint) public balances;

    *// Events allow clients to react to specific*    
		*// contract changes you declare*    
event Sent(address from, address to, uint amount);

    *// Constructor code is only run when the contract*    
		*// is created*    
constructor() {
        minter = **msg.sender**;
    }

    *// Sends an amount of newly created coins to an address*    
		*// Can only be called by the contract creator*    
function mint(address receiver, uint amount) public {
        require(**msg.sender** == minter);
        balances[receiver] += amount;
    }

    *// Errors allow you to provide information about*    
		*// why an operation failed. They are returned*    
		*// to the caller of the function.*    
		error InsufficientBalance(uint requested, uint available);

    *// Sends an amount of existing coins*    
		*// from any caller to an address*    
function send(address receiver, uint amount) public {
        if (amount > balances[**msg.sender**])
            revert InsufficientBalance({
                requested: amount,
                available: balances[**msg.sender**]
            });

        balances[**msg.sender**] -= amount;
        balances[receiver] += amount;
        emit Sent(**msg.sender**, receiver, amount);
    }
}