[Solidity] Introduction to Smart Contracts

Basic Example

This is a basic example that sets the value of a variable and exposes it for other contracts to access.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// SPDX-License-Identifier: GPL-3.0 // the source code is licensed under the GPL version 3.0
pragma solidity >=0.4.16 <0.9.0; // 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.

contract SimpleStorage { // contract name
// declares a state variable called storedData of type uint (unsigned integer of 256 bits)
uint storedData;

// set that can be used to modify the value of the variable
function set(uint x) public {
storedData = x;
}

// get that can be used to retrieve the value of the variable
function get() public view returns (uint) {
return storedData;
}
}

The first line Machine-readable license specifiers are important in a setting where publishing the source code is the default.

pragma - are common instructions for compilers about how to treat the source code (e.g. pragma once - https://en.wikipedia.org/wiki/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.

In this example, the contract declares a state variable called storedData of type uint (unsigned integer of 256 bits), and defines the functions set and get that can be used to modify or retrieve the value of the variable.

Anyone could call set again with a different value and overwrite your number, and 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.


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 contract allows only its creator to create new coins (different issuance schemes are possible). Anyone can send coins to each other

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

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);
require(amount < 1e60);
balances[receiver] += amount;
}

// Sends an amount of existing coins
// from any caller to an address
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Insufficient balance.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}

The line address public minter; declares a state variable of type address - https://docs.soliditylang.org/en/v0.8.3/types.html#address. The address type is a 160-bit value that does not allow any arithmetic operations. It is suitable for storing addresses of contracts, or a hash of the public half of a keypair belonging to external accounts - https://docs.soliditylang.org/en/v0.8.3/introduction-to-smart-contracts.html#accounts.

The keyword public automatically generates a function that allows you to access the current value of the state variable from outside of the contract. Without this keyword, other contracts have no way to access the variable. The code of the function generated by the compiler is equivalent to the following

1
function minter() external view returns (address) { return minter; }