0% found this document useful (0 votes)
212 views57 pages

07 Ethereum Smart Contracts

Uploaded by

Tessa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
212 views57 pages

07 Ethereum Smart Contracts

Uploaded by

Tessa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

Ethereum Smart Contracts

Blockchain-Based Systems Engineering

Chair of Software Engineering for Business Information Systems (sebis)


Faculty of Informatics
Technische Universität München
wwwmatthes.in.tum.de
Outline
1. Solidity Introduction
§ Definition
§ Anatomy of a Smart Contract
§ Language Features
§ Functions
§ Modifiers
§ Inheritance
§ Abstract Contracts and Interfaces

2. Designing Smart Contracts


§ Problem Assessment
§ Modelling Entities
§ Modelling Transactions

3. Cross-contract and Blockchain Interaction


§ EVM Contract Function Execution
§ Transactions and Messages
§ Address Class
§ Re-entrancy Attack
§ Message Object
§ Block Object
§ Transaction Object

07 Ethereum Smart Contracts © sebis 2


Definition

§ Solidity is a high-level language to write smart contracts for Ethereum.

§ Contracts1 can be defined as encapsulated units, similar to classes in


traditional object-oriented programming languages like Java.

§ A contract has its own, persistent state on the blockchain which is


defined by state variables in the contract.

§ Functions are used to change the state of the contract or to perform


other computations.

§ Solidity is compiled to bytecode which is persistent and immutable once


deployed to the blockchain:
è No patch deployment possible
è Smart contracts must be perfect before using them in production!

1
”Contract” is used as a short form of “smart contract”.
07 Ethereum Smart Contracts © sebis 3
Source Code

• Source code is typically not stored on


the blockchain, only byte code.

• Without further analysis, the purpose of


this smart contract is unclear.

• Source code can be made publicly


available.

• Etherscan.io is the only service which


verifies source codes and the respective
byte code.

07 Ethereum Smart Contracts © sebis 4


From Solidity Source Code to a Deployed Smart Contract

1. Contract development 2. Compilation 3. Transaction creation 4. Transaction mined

Smart Contract
code is written in Compiler takes the
Solidity (.sol file) Solidity code and
produces EVM The hex encoded
bytecode bytecode is sent
The bytecode is
as transaction to
put into a block and
the network
mined. The contract
can now be used!

These steps are running on a private These steps are executed and stored in the
machine and are therefore not available to Blockchain and therefore available for
the public. everyone.

07 Ethereum Smart Contracts © sebis 5


Anatomy of a Solidity Smart Contract File
File: BBSE.sol
contract BBSE {

struct Tutor {
string firstName;
State variables
string lastName; § State variables are permanently stored in
}
mapping (address => Tutor) tutors; the contract’s storage.
address professor; § Changing the state requires a transactions
modifier onlyProfessor { and therefore costs ether.
require(msg.sender == professor);
_; § Reading the state of a contract is free and
} does not require a transaction.
constructor() public {
professor = msg.sender;
}

function getProfessor() view returns (address) {


return professor;
}

// This function adds a new tutor


function addTutor(address tutorAddress,
string firstName, string lastName) onlyProfessor {
Tutor tutor = tutors[tutorAddress];
tutor.firstName = firstName;
tutor.lastName = lastName;
}

}
07 Ethereum Smart Contracts © sebis 6
Anatomy of a Solidity Smart Contract File (cont.)
File: BBSE.sol
contract BBSE {

struct Tutor {
string firstName;
Function modifiers
string lastName; § Function modifiers are a convenient way to
}
mapping (address => Tutor) tutors; reuse pieces of code.
address professor; § Changes the behavior of a function.
modifier onlyProfessor { § Can execute code either before and/or
require(msg.sender == professor);
_; after the actual function execution.
} § The low dash _ indicates where the actual
constructor() public { function code is injected.
professor = msg.sender;
}
§ Often used for authentication.
function getProfessor() view returns (address) {
return professor;
}

// This function adds a new tutor


function addTutor(address tutorAddress,
string firstName, string lastName) onlyProfessor {
Tutor tutor = tutors[tutorAddress];
tutor.firstName = firstName;
tutor.lastName = lastName;
}

}
07 Ethereum Smart Contracts © sebis 7
Anatomy of a Solidity Smart Contract File (cont.)
File: BBSE.sol
contract BBSE {

struct Tutor {
string firstName;
Constructor
string lastName; § The constructor function is executed once
}
mapping (address => Tutor) tutors; when the contract is created through a
address professor; transaction.
modifier onlyProfessor { § The function cannot be called after the
require(msg.sender == professor);
_; creation of the contract.
} § Usually used to initialize the state of a
constructor() public { contract.
professor = msg.sender;
}
§ Execution costs gas and more complex
constructors lead to higher deployment
function getProfessor() view returns (address) {
return professor; costs.
}

// This function adds a new tutor


function addTutor(address tutorAddress,
string firstName, string lastName) onlyProfessor {
Tutor tutor = tutors[tutorAddress];
tutor.firstName = firstName;
tutor.lastName = lastName;
}

}
07 Ethereum Smart Contracts © sebis 8
Anatomy of a Solidity Smart Contract File (cont.)
File: BBSE.sol
contract BBSE {

struct Tutor {
string firstName;
Functions
string lastName; § Functions are used to change the state of
}
mapping (address => Tutor) tutors; a contract.
address professor; § Can also be used to read the state of the
modifier onlyProfessor { contract.
require(msg.sender == professor);
_; § Consist of a name, a signature, a visibility,
} a type, a list of modifiers, and a return
constructor() public { type.
professor = msg.sender;
}
Formal definition:
function getProfessor() view returns (address) {
return professor; function (<parameter types>)
} {internal|external|public|private}
// This function adds a new tutor
[pure|constant|view|payable]
function addTutor(address tutorAddress, [(modifiers)]
string firstName, string lastName) onlyProfessor {
Tutor tutor = tutors[tutorAddress];
[returns (<return types>)]
tutor.firstName = firstName;
tutor.lastName = lastName;
}

}
07 Ethereum Smart Contracts © sebis 9
Language Features Overview
Solidity is inspired by JavaScript and comes with a very similar syntax. Furthermore, it implements the
standard set of features for high-level (object-oriented) programming languages. Compared to the
dynamically-typed JavaScript, Solidity uses static types.

Built-in data types


int, uint, bool, array, struct, enum, mapping

Built-in first level objects


block, msg, tx, address

Built-in functions
Error handling: assert(), require(), revert()
Math & Crypto: addmod(), mulmod(), sha3(), keccak256(), sha256(), ripemd160(), ecrecover()
Information: gasleft(), blockhash()
Contract related: selfdestruct()

A set of literals
Solidity comes with some Ethereum specific literals (like eth for units, e.g., int a = 5 eth)

Flow control
if, else, do, while, break, continue, for, return, ? … : … (ternary operator)
07 Ethereum Smart Contracts © sebis 10
Function and Variable Visibility

In Solidity, functions can be declared with four different visibility types.

External
External methods can be called by other contracts and via transactions issued by a certain wallet.
Methods declared as external are always publicly visible and can’t be called directly by the
contract itself.

Public
Public can be called internally by the contract itself but also externally by other contracts and via
transactions. State variable which are defined as public will by default have getter method created
automatically by the compiler.

Internal
Internal methods can only be accessed by the contract itself or by any contract derived from it. They
are not callable from other contracts nor via transactions.

Private
Private methods can only be called internally by the contract who owns the method. Derived
contracts cannot access a private method of their parent contract.
07 Ethereum Smart Contracts © sebis 11
Data Storage in EVM
EVM can store data in three different places; storage, memory, and the stack.
Storage Memory Stack
§ The storage is comparable to a hard drive. § The memory is comparable to a § Because the EVM is a stack machine
It keeps data between function calls and is computer's RAM. It is a temporary storage rather than a register machine, all
persistent for each smart contract. This location for data. During execution, the computations are done on a data region
way, every execution on the contract has contract can use any amount of memory, called the stack. It has a maximum of
access to the data previously saved on the but once the execution is complete, the 1024 elements and comprises 256-bit
storage area. memory is cleaned for the next execution. words.

§ Reading the storage is expensive. § Memory is linear and can be addressed at § Moving stack items to storage or memory
Initializing and modifying storage is even the byte level, however, reads are limited to provide deeper access to the stack is
more expensive. Thus, you should limit the to 256 bits wide, but writing can be 8 bits possible.
amount of data you keep in persistent or 256 bits wide.
storage to what the contract requires.

Where do variables and function arguments get stored?


As we have seen, every transaction on EVM costs some amount of gas. The lower the gas consumption, the better is the Solidity code. When
compared to the gas consumption of storage, memory has a relatively low consumption. As a result, it is always preferable to do intermediate
calculations in memory and then save the result to storage.
§ State variables and local variables are saved in storage by default.
§ Memory can only be used inside a function (either for newly instantiated complex types like array and struct or for storage referenced
variables)
§ Function arguments are saved in memory by default.
https://docs.soliditylang.org/en/develop/introduction-to-smart-contracts.html#storage-memory-and-the-stack
07 Ethereum Smart Contracts © sebis 12
Examples for Storage and Memory
Storage Memory
In this example, a contract is formed to demonstrate the use of “storage”: In this example, a contract is formed to demonstrate the use of “memory”:

Output of
numbers:
Output of [1,2]. In this case,
numbers: changing the
[0,2] and not [1,2]. value of myArray
does not affect
the value in the
numbers array.

§ myArray is pointer to the numbers array’s storage location


§ If storage keyword was not used, Solidity would still have created
myArray as a pointer to the numbers array’s storage location § The keyword memory must be used in order to make sure myArray
only exists locally

numbers Storage Memory Storage


int[] int[] int[]
shallow
myArray copy

myArray numbers

07 Ethereum Smart Contracts © sebis 13


Special Function Types

Solidity provides two special function type declaration besides the default one.

View function
Functions which are declared as view are read only, i.e. they do not modify any state variable nor alter
the state of the blockchain. However, they can read from state variables.
uint state = 5;
function add(uint a, uint b) public view returns (uint sum) { return a + b + state }

Pure function
Pure functions can be seen as a subset of view functions which don’t modify the state but also don’t
read from the state.
function add(uint a, uint b) public pure returns (uint sum) { return a +b }

Fallback function
A contract can have one unnamed fallback function. The fallback function is called when no other
function matches the function call (e.g., when Ether is sent to a contract without a receive function). A
special feature of this function is that it can’t have any parameters and doesn’t return anything.
function() { /* … */ }

07 Ethereum Smart Contracts © sebis 14


Special Function Types (cont.)
Payable function
By default, it is not possible to send ether to a function because the function will by default revert the
transaction. The behavior is intentional, it should prevent Ether that is accidentally sent from being
lost. However, sometimes it is necessary to pay a contract, e.g. in case of an ICO. Therefore, Solidity
implements so-called payable functions.

Example
function buyInICO() public payable { /* … */ }

§ The keyword payable is also required for declaring constructors and addresses that can receive
Ether (e.g., constructor payable { /* … */ }, function withdraw (address payable _to) public { /* … */ }).

§ While implicit conversions are allowed from address payable to address, a casting function called
payable (<address>) must be used for conversions from address to address payable.

address public customer;

function transfer (uint amount) public {


payable(customer). transfer(amount);
}

07 Ethereum Smart Contracts © sebis 15


Function Modifiers

Sometimes it is required to check whether a certain condition is true or false before executing a
function. For instance, an authentication mechanism prior to the function call. Writing code twice
makes it harder to maintain and prone to security vulnerabilities. Therefore, Solidity implements the
concept of modifiers which are basically a reusable piece of code.

Modifiers are defined with the keyword modifier:


contract owned {
address public owner;

constructor() public {
owner = msg.sender;
}

modifier onlyOwner {
require(msg.sender == owner);
_;
}

function kill() public onlyOwner {


selfdestruct(owner);
}
}

07 Ethereum Smart Contracts © sebis 16


Example of Function Modifiers

Internally, the actual function body is injected where _ is placed in the modifier.

The code snippets below are equal.

contract owned { contract owned {


address public owner; address public owner;

constructor() public { constructor() public {


owner = msg.sender; owner = msg.sender;
} }
===
modifier onlyOwner { function kill() public {
require(msg.sender == owner); require(msg.sender == owner);
_; // Injection here selfdestruct(owner);
} }
}
function kill() public onlyOwner {
selfdestruct(owner);
}
}

07 Ethereum Smart Contracts © sebis 17


Chaining of Function Modifiers

It is possible to apply multiple modifiers to a function. The modifiers will be resolved sequentially,
starting from left to right. In the example below, a user can only call the kill function if he/she is the
owner of the contract and has an account balance with more than 1337 ETH.
contract owned {
address public owner;

constructor() public {
owner = msg.sender;
}

modifier onlyOwner {
require(msg.sender == owner);
_; // Actual function code is injected here
}

modifier isRich {
require(msg.sender.balance > 1337 ether);
_; // Actual function code is injected here
}

function kill() public onlyOwner isRich {


selfdestruct(owner);
}
}
07 Ethereum Smart Contracts © sebis 18
Function Overloading

Solidity allows to overload functions, i.e. to define the same function twice with a different signature.
This can be helpful if a method needs to be adapted to certain situations.

Example
function sendEther(uint amount) {
require(this.balance >= amount);
payable(msg.sender).transfer(amount);
}

function sendEther(uint amount, address payable to) {


require(this.balance >= amount);
to.transfer(amount);
}

If sendEther() is called without the address argument, the Ether will be sent to the caller.
Otherwise, it will be sent to the address passed as parameter to the function.

07 Ethereum Smart Contracts © sebis 19


Named Function Calls

Usually, function parameters are passed by their defined signature order. Solidity supports the
concept of named calls. The named calls principle allows to pass function parameters explicitly
via a dictionary.

Example 1, without a named call: Example 2, using a named call:


function myAddFunction(uint a, uint b) returns (uint result) { function myAddFunction(uint a, uint b) returns (uint result) {
return a+b; return a+b;
} }

function fourPlusTwo() returns (uint result) { function fourPlusTwo() returns (uint result) {
return myAddFunction(4, 2); return myAddFunction({b: 2, a:4});
} }

The order of the parameters is defined by the The function fourPlusTwo passes a dictionary with
function’s signature. keys that match the signature of myAddFunction. The
order within the dictionary does not matter.

07 Ethereum Smart Contracts © sebis 20


Inheritance
Solidity supports inheritance of contracts. Technically, the solidity compiler copies the code from
the parent contract to the sub contract and creates a single piece of bytecode which is deployed on
the blockchain.

Solidity also supports multiple inheritance for a contract. In this case, the compiler just copies all
parent contracts together and creates a single contract that is compiled to bytecode and deployed to
the blockchain. Once a contract is deployed, it is not possible to detect from the bytecode whether a
contract made use of inheritance or not.

If a parent contract contains a function that is also present in the sub contract, then the functions are
overloaded. In case both functions have the same signature, the sub contract’s function will override
the parent’s function. However, the parent function can still be explicitly accessed using the super
keyword.

Use Cases:
SafeMath, Authentification

07 Ethereum Smart Contracts © sebis 21


Multiple Inheritance

Solidity uses, similar to Python, the C3 superclass linearization algorithm to define the order
of the inherited functions. There is no implicit order for parent classes, the order is defined by
the developer.

Assume the following inheritance graph

A B C

Y inherits from X D E

F
07 Ethereum Smart Contracts © sebis 22
Multiple Inheritance (cont.)
In Solidity, contracts can inherit from other contracts by using the keyword is.

Example
contract A {}
contract B {}
contract C {}
contract D is A, B {}
contract E is B, C {}
contract F is D, E {}

The function resolution order (FRO) of the example above would be:
F, D, E, A, B, C

The keyword super always references the next contract in the FRO. If super would be called in F, it would
reference to D and super in D would reference to E and so on.

07 Ethereum Smart Contracts © sebis 23


Example of Inheritance

contract A { What would happen if Final.getNumber() is called?


function getNumber() returns (uint a) {
return 1337;
} § The function resolution order is:
} Final, C, B, A
§ In Final super will be resolved to C
contract B is A { § In C super will point to B !!!!
function getNumber() returns (uint a) {
§ In B super will point to A
return super.getNumber() + 1;
}
} § The final result is 1337 + 1 + 2 = 1340
contract C is A {
function getNumber() returns (uint a) {
return super.getNumber() + 2;
}
}
contract Final is C, B {
function getNumber() returns (uint a) {
return super.getNumber();
}
}

07 Ethereum Smart Contracts © sebis 24


Abstract Contracts
Solidity supports abstract contracts. A contract is implicitly declared as abstract, if one or more
functions are abstract. A function is considered abstract when it does not have a body.

Example

contract CarInsurance {
function payMonthlyFee() returns (boolean result);
}

Abstract contracts cannot be compiled to bytecode. A contract that inherits from an abstract
contract must implement and override all methods from the base contract to be compliable.

Abstract contracts offer a way to decouple the definition of a contract from its actual implementation.
This provides better extensibility and maintainability, in particular for larger contracts.

07 Ethereum Smart Contracts © sebis 25


Interfaces
Solidity supports the definition of interfaces for contracts. An interface is similar to an abstract class
but is more restrictive. It is not allowed to define a constructor, variables, structs and enums in an
interface. Furthermore, interfaces cannot inherit from a contract or implement another interface.

Example

interface CarInsurance {
function payMonthlyFee() returns (boolean result);
}

A contract can implement multiple interfaces at once. According to the Ethereum foundation, some
of the restrictions for interfaces might be lifted or changed in the future.

07 Ethereum Smart Contracts © sebis 26


Outline
1. Solidity Introduction
§ Definition
§ Anatomy of a Smart Contract
§ Language Features
§ Functions
§ Modifiers
§ Inheritance
§ Abstract Contracts and Interfaces

2. Designing Smart Contracts


§ Problem Assessment
§ Modelling Entities
§ Modelling Transactions

3. Cross-contract and Blockchain Interaction


§ EVM Contract Function Execution
§ Transactions and Messages
§ Address Class
§ Re-entrancy Attack
§ Message Object
§ Block Object
§ Transaction Object

07 Ethereum Smart Contracts © sebis 27


Problem Assessment
The hype of blockchain has led to a large number of software applications
using blockchain technology. Often used by startups or driven by innovation
departments in enterprises.

However, the real-world adoption of contracts still is negligible. Currently, the Do you need a
largest dApp1 using an Ethereum smart contract has less than ~11000 blockchain?
transactions per day (https://dappradar.com/rankings/protocol/ethereum).

Finding a use case


§ Understand the problem domain and the blockchain technology well
§ Blockchain might be a potential solution if:
§ Multiple parties are involved and
No
§ The parties do not trust each other or have different interests and
§ Shared write access is required and (Joke) Model by Dave Birch (https://twitter.com/dgwbirch?lang=de)
§ All writes to the database need to be (publicly) verifiable

§ Evaluate alternative solutions.

1 Decentralized application.
07 Ethereum Smart Contracts © sebis 28
Model the Business Process

As in traditional software engineering, the first step for creating an application is to model the business process.

Identification
§ Identify the involved parties, systems, and their relationship.
§ Identify the necessary interactions between the parties and systems.
§ Identify the information that is exchanged between the parties and systems.
§ Identify the system boundaries.
§ Diagrams can help to get the big picture.

Modelling
§ Derive concrete models from the identified parties and systems.
§ Define concrete messages that are exchanged between the systems and parties.
§ Define a concrete data model used by the system.
§ Derive concrete interfaces for interaction with the systems and parties.
§ The overall architecture is usually modeled at a high abstraction level using architecture diagrams.
§ The concrete software is modeled at a lower abstraction level using class diagrams.

07 Ethereum Smart Contracts © sebis 29


Fictional Example
Blood Donation
The DRK (“Deutsches Rotes Kreuz”) wants to digitize the blood donation process and make it more transparent.
Therefore, it analyzes different technological solutions. As a first step, the DRK wants to track the supply chain
from the blood extraction to the transfusion. The overall process is listed below.

Current simplified process: Involved Systems:


§ Person goes to the DRK and donates blood § Laboratory management system (LMS) in
§ Blood is analyzed in laboratory and labeled the laboratory that analyzes the blood.
§ Blood product is sent to hospital § The hospital information system (HIS) used in
§ Hospital checks if a patients blood is the hospital to manage patients and
compatible with the product processes.
§ Blood is transfused

Involved Parties: Interactions:


§ DRK – Extracts the blood from the donor § DRK extracts blood from Donor
§ Laboratory – Analyzes the blood and creates § DRK sends blood to laboratory
blood products § Laboratory analyzes blood
§ Donor – Donates his/her blood § Hospital sends request to laboratory
§ Hospital – Transfuses the blood § Laboratory sends blood to hospital
§ Patient – Receives the blood transfusion § Hospital transfuses blood to patient
07 Ethereum Smart Contracts © sebis 30
Fictional Example (cont.)
Blood Donation
Assessing blockchain and contracts as potential solution architecture.

Multiple parties are involved ✔


§ At least four parties are involved

The parties do not trust each other or have different interests –


§ Questionable, some patients might not trust the DRK and therefore do not donate.

Shared write access is required ✔


§ DRK needs to read and write
§ The laboratory needs to read and write
§ The hospital needs to read and write

All writes to the database need to be publicly verifiable ✔


§ The donor needs to be able to track what happened with his/her donation.
§ In case of an accident, the blockchain could help to identify the root cause and the responsible party.

07 Ethereum Smart Contracts © sebis 31


Fictional Example (cont.)
Blood Donation Entities
In the Ethereum ecosystem two kinds of entities exist, externally owned accounts (EOAs) and contracts.
Transactions are always issued by EOAs and usually controlled by an individual or a party. If an entity needs to
be interactive and provide some on-chain functionality it is a candidate for a contract.

EOAs
Donor – Person who donates blood identified by their unique wallet address
DRK – Institution that runs blood donation events
Laboratory – Laboratory that takes the blood donation and creates blood products out of it
Hospital – The institution that transfuses the blood of the donor to a patient
Patient – The patient who gets a blood transfusion

Contracts
Blood Donation – Contract owned by the DRK, it tracks the time and date of the donation. Additionally, it records
whenever the donation is passed to another party, e.g., from the DRK to the laboratory.

07 Ethereum Smart Contracts © sebis 32


Fictional Example (cont.)
Blood Donation Transactions

In the Ethereum ecosystem transactions and messages are the only way for entities to interact.
Interactions
DRK à CONTRACT_CREATION:
Creates a blood donation (BD) and deploys it on the blockchain. The address of the donor is passed via
constructor and unchangeable.

DRK à BD.sendToLaboratory(address laboratory):


The DRK issues a transaction to the BD when the blood donation is sent to the laboratory. The state variable for
the laboratory is set.

Laboratory à BD.sendToHospital(address hospital):


The Laboratory issues a transaction to the BD when the blood donation is sent to the hospital. The state
variable for the hospital is set. Only the hospital can do the transfusion.

Hospital à BD.transfuse(address patient):


The hospital issues a transaction to the BD when the blood is transfused to a patient. A transfusion can only
happen once.
07 Ethereum Smart Contracts © sebis 33
Fictional Example (cont.)
Blood Donation EOAs

DRK: 0x91A0639dDe409c126f058e33D743b1253738C8b9
PK: 0x3aae751e36ddffd4f7d5ff4bee409583a54df823111a30f780c18cd73ebb02f8

Laboratory: 0x3aDDBa6E0C56EE1357Bb9796b20480880cA37E81
PK: 0xdbe7d4d5460f6a6e086579a0acf071b652b6ed5ae0374d704a949cbb0b740a65

Hospital: 0x582FFFacdBFDaF1936672886035ea561FF669a44
PK: 0x8ae80121c7bc29a51eb4401754928051063a8dace9d35496dd26d0c4a1a0640c

Patient: 0x0780aFf9177d78E86Fc03158D504652f88c4D1bc
PK: 0x0a18f4e53a62e97b613ed94d0f411de327e0d1a0d5533c685042cae420aacbfb

Donor: 0x39bc67dBb1f5203AF048699233b29Dec903389A4
PK: 0x5aed62bff0a98533345482fb91ac80388869e6bdd5ad53c19b54a37468a5cb2d

07 Ethereum Smart Contracts © sebis 34


Fictional Example (cont.)
Blood Donation Contract
// File: BloodDonation.sol
pragma solidity >=0.4.22 <0.6.0;
// ... con^nues here
contract BloodDonation {
constructor(address _donor) public {
address donor;
drk = msg.sender;
address drk;
donor = _donor;
address laboratory;
}
address hospital;
funcOon sendToLaboratory(address _laboratory) onlyDRK {
address patient;
laboratory = _laboratory;
bool isTransfused = false;
}
modifier onlyDRK() {
require(msg.sender == drk);_;
funcOon sendToHospital(address _hospital) onlyLaboratory {
} hospital = _hospital;
modifier onlyLaboratory() {
}
require(msg.sender == laboratory);_;
} funcOon transfuse(address _paOent) canTransfuse {
modifier canTransfuse() { paOent = _paOent;
require(!isTransfused); isTransfused = true;
require(msg.sender = hospital); }
_; }
}

// ends here ...

07 Ethereum Smart Contracts © sebis 35


Outline
1. Solidity Introduction
§ Definition
§ Anatomy of a Smart Contract
§ Language Features
§ Functions
§ Modifiers
§ Inheritance
§ Abstract Contracts and Interfaces

2. Designing Smart Contracts


§ Problem Assessment
§ Modelling Entities
§ Modelling Transactions

3. Cross-contract and Blockchain Interaction


§ EVM Contract Function Execution
§ Transactions and Messages
§ Address Class
§ Re-entrancy Attack
§ Message Object
§ Block Object
§ Transaction Object

07 Ethereum Smart Contracts © sebis 36


Overview of EVM Contract Function Execution

Eth.execute(contract c, function f, param a, param b)

Write set
(state changes)

Coinbase Coinbase
Contract Difficulty Difficulty
Gaslimit Gaslimit
Timestamp Timestamp
Block: n-2 Block: n-1 Block: n EVM
TX TX TX Block: n+1 Block: n+1
TX TX TX TX

Block currently being mined Latest mined block

past now

07 Ethereum Smart Contracts © sebis 37


Transactions and Messages

The origin of each contract function call is always a transaction by an externally owned account (EOA).

In more complex systems, multiple contracts communicate with each other. For example, when a contract uses
an oracle contract to get information from the outside world. In such cases, the issuer of the function call must
provide enough gas that also the oracle request can be fulfilled.

Whenever a contract issues a message to another contract, the gas from the origin transaction is just forwarded.
However, sometimes this is not intended, e.g., when only Ether should be transferred. Therefore, the Solidity
address class implements functions specifically for that use case.

Transaction Message Message


to call A.f() Contract A to call B.g() Contract B to call C.h() Contract C
EOA
f(){B.g()} Gas provided g(){C.h()} h()
Gas provided
by origin by origin
transaction is transaction is
forwarded forwarded

07 Ethereum Smart Contracts © sebis 38


Address Class
Some contracts may require information about a specific account, e.g. the current account balance. Solidity
implements a special type for accounts called address. Any Ethereum account, i.e. externally owned, as
well as, contract, can be represented as address object.

An address can be directly defined via a valid 20 byte hex code representation.
address a = 0xd5e7726990fD197005Aae8b3f973e7f2A65b4c18

An address that can receive Ether must either be defined as address payable or it should be cast with
payable (<address>) function while sending Ether to it.

Furthermore, any contract object can be explicitly casted to an address.


contract A {
function f() {}
}
contract B {
function g() {
A a = new A();
address contract_a = address(a);
address self = address(this);
}
}
07 Ethereum Smart Contracts © sebis 39
Working with Addresses
It is also possible to down-cast an address to a contract:

A a = A(0xd5e7726990fD197005Aae8b3f973e7f2A65b4c18)

This only works if the contract identified by the address is an instance of A.

contract A {
function f() {}
}

contract B {
function g() {
A a = new A();
address contract_a = address(a);
address self = address(this);
// B b = B(self) would work
// B b = B(contract_a) would fail
}
}

07 Ethereum Smart Contracts © sebis 40


Address Class
<address>.balance
The balance of the address in Wei returned as 256 bit unsigned integer

<address>.transfer(uint256 value)
Transfers the amount passed as value in Wei to the <address>. The function throws on failure. Forwards 2300 gas
to <address>. (NOTE: Must keep in mind that the called smart contract can quickly run out of gas and make the
transfer impossible)

<address>.send(uint256 value)
Same as <address>.transfer(uint256 value) but returns false on failure

<address>.call(…)
A Low-level function that can be used to invoke functions but also to send Ether. The function returns false on
failure and, by default, forwards all gas to <address> (NOTE: The called contract can execute complex operations
that can spend all of the forwarded gas, causing more cost to the caller). If there is no receive function defined in
the called contract (i.e., if the fallback gets triggered upon Ether received), then, only 2300 gas is forwarded.

<address>.delegatecall(…)
A low-level function that can be used to call a function at <address> in the context/state of the current contract (i.e.,
caller contract delegates the use of its storage to the receiving contract). This function returns false on failure.
(NOTE: Caller contract needs to trust the receiving contract)

07 Ethereum Smart Contracts © sebis 41


Re-entrancy Attack

What is a re-entrancy attack?

§ The re-entrancy attack is one of the most damaging attacks to a Solidity smart contract. When a function makes
an external call to another untrusted contract, it becomes vulnerable to a re-entrancy attack.

§ The untrusted contract can place recursive calls back to the original function, in order to drain all the funds
in the calling contract.

§ This would work if the original function updates the balance of the receiving contract, after transferring the coins.

07 Ethereum Smart Contracts © sebis 42


An Example Re-entrancy Attack Scenario
Let's see how a re-entrancy attack works; A B
10 Ether 0 Ether
B: 1 Ether
§ A is a contract where you can deposit and withdraw ETH. It keeps a record of fallback(){
withdraw(){ A.withdraw()
how much it owes to other contracts. In our case, A owes 1 Ether to contract B check balance>0 }
send Ether attack(){
§ Contract B has two functions: fallback() and attack(). Both functions call balance=0 A.withdraw()
withdraw() on A } }

A B
9 Ether 1 Ether
B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

A B
8 Ether 2 Ether
B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

07 Ethereum Smart Contracts © sebis 43


An Example Re-entrancy Attack Scenario
Let's see how a re-entrancy attack works; A B
10 Ether 0 Ether
B: 1 Ether
§ A is a contract where you can deposit and withdraw ETH. It keeps a record of fallback(){
withdraw(){ A.withdraw()
how much it owes to other contracts. In our case, A owes 1 Ether to contract B check balance>0 }
send Ether attack(){
§ Contract B has two functions: fallback() and attack(). Both functions call balance=0 A.withdraw()
1
withdraw() on A } }

1. First, B executes attack(), which calls withdraw() on A


A B
9 Ether 1 Ether
B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

A B
8 Ether 2 Ether
B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

07 Ethereum Smart Contracts © sebis 44


An Example Re-entrancy Attack Scenario
Let's see how a re-entrancy attack works; A B
10 Ether 0 Ether
B: 1 Ether
§ A is a contract where you can deposit and withdraw ETH. It keeps a record of fallback(){
withdraw(){ A.withdraw()
how much it owes to other contracts. In our case, A owes 1 Ether to contract B check balance>0 }
send Ether attack(){
§ Contract B has two functions: fallback() and attack(). Both functions call balance=0 A.withdraw()
2 1
withdraw() on A } }

1. First, B executes attack(), which calls withdraw() on A


2. A checks that the balance of B is greater than 0 and sends 1 Ether to B A B
9 Ether 1 Ether
(Contract B has 1 Ether, A has 9 Ether left) B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

A B
8 Ether 2 Ether
B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

07 Ethereum Smart Contracts © sebis 45


An Example Re-entrancy Attack Scenario
Let's see how a re-entrancy attack works; A B
10 Ether 0 Ether
B: 1 Ether
§ A is a contract where you can deposit and withdraw ETH. It keeps a record of fallback(){
withdraw(){ A.withdraw()
how much it owes to other contracts. In our case, A owes 1 Ether to contract B check balance>0 }
send Ether attack(){
§ Contract B has two functions: fallback() and attack(). Both functions call balance=0 A.withdraw()
2 1
withdraw() on A } }

1. First, B executes attack(), which calls withdraw() on A


2. A checks that the balance of B is greater than 0 and sends 1 Ether to B A B
9 Ether 1 Ether
(Contract B has 1 Ether, A has 9 Ether left) B: 1 Ether
3. Receiving Ether triggers fallback() on B, which immediately calls fallback(){
withdraw(){ A.withdraw()
withdraw() again check balance>0 3 }
send Ether attack(){
balance=0 A.withdraw()
} }

A B
8 Ether 2 Ether
B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

07 Ethereum Smart Contracts © sebis 46


An Example Re-entrancy Attack Scenario
Let's see how a re-entrancy attack works; A B
10 Ether 0 Ether
B: 1 Ether
§ A is a contract where you can deposit and withdraw ETH. It keeps a record of fallback(){
withdraw(){ A.withdraw()
how much it owes to other contracts. In our case, A owes 1 Ether to contract B check balance>0 }
send Ether attack(){
§ Contract B has two functions: fallback() and attack(). Both functions call balance=0 A.withdraw()
2 1
withdraw() on A } }

1. First, B executes attack(), which calls withdraw() on A


2. A checks that the balance of B is greater than 0 and sends 1 Ether to B A B
9 Ether 1 Ether
(Contract B has 1 Ether, A has 9 Ether left) B: 1 Ether
3. Receiving Ether triggers fallback() on B, which immediately calls withdraw() fallback(){
withdraw(){ A.withdraw()
again check balance>0 3 }
send Ether attack(){
4. withdraw() checks the balance of B and since it is still 1, A sends balance=0
4
A.withdraw()
another Ether to B } }

A B
8 Ether 2 Ether
B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

07 Ethereum Smart Contracts © sebis 47


An Example Re-entrancy Attack Scenario
Let's see how a re-entrancy attack works; A B
10 Ether 0 Ether
B: 1 Ether
§ A is a contract where you can deposit and withdraw ETH. It keeps a record of fallback(){
withdraw(){ A.withdraw()
how much it owes to other contracts. In our case, A owes 1 Ether to contract B check balance>0 }
send Ether attack(){
§ Contract B has two functions: fallback() and attack(). Both functions call balance=0 A.withdraw()
2 1
withdraw() on A } }

1. First, B executes attack(), which calls withdraw() on A


2. A checks that the balance of B is greater than 0 and sends 1 Ether to B A B
9 Ether 1 Ether
(Contract B has 1 Ether, A has 9 Ether left) B: 1 Ether
3. Receiving Ether triggers fallback() on B, which immediately calls withdraw() fallback(){
withdraw(){ A.withdraw()
again check balance>0 3 }
send Ether attack(){
4. withdraw() checks the balance of B and since it is still 1, A sends another balance=0
4
A.withdraw()
Ether to B } }

5. Now, A has 8 Ether and B has 2 Ether, while the balance of contract B in
A is still 1 Ether. B calls withdraw() again. A B
8 Ether 2 Ether
B: 1 Ether
fallback(){
withdraw(){ A.withdraw()
5
check balance>0 }
send Ether attack(){
balance=0 A.withdraw()
} }

07 Ethereum Smart Contracts © sebis 48


An Example Re-entrancy Attack Scenario
Let's see how a re-entrancy attack works; A B
10 Ether 0 Ether
B: 1 Ether
§ A is a contract where you can deposit and withdraw ETH. It keeps a record of fallback(){
withdraw(){ A.withdraw()
how much it owes to other contracts. In our case, A owes 1 Ether to contract B check balance>0 }
send Ether attack(){
§ Contract B has two functions: fallback() and attack(). Both functions call balance=0 A.withdraw()
2 1
withdraw() on A } }

1. First, B executes attack(), which calls withdraw() on A


2. A checks that the balance of B is greater than 0 and sends 1 Ether to B A B
9 Ether 1 Ether
(Contract B has 1 Ether, A has 9 Ether left) B: 1 Ether
3. Receiving Ether triggers fallback() on B, which immediately calls withdraw() fallback(){
withdraw(){ A.withdraw()
again check balance>0 3 }
send Ether attack(){
4. withdraw() checks the balance of B and since it is still 1, A sends another balance=0
4
A.withdraw()
Ether to B } }

5. Now, A has 8 Ether and B has 2 Ether, while the balance of contract B in A is
still 1 Ether. B calls withdraw() again. A B
6. withdraw() checks the balance of B and since it is still 1, A sends 8 Ether
B: 1 Ether
2 Ether

another Ether to B fallback(){


withdraw(){ A.withdraw()
5
check balance>0 }
send Ether attack(){
6
balance=0 A.withdraw()
} }

07 Ethereum Smart Contracts © sebis 49


An Example Re-entrancy Attack Scenario
Let's see how a re-entrancy attack works; A B
10 Ether 0 Ether
B: 1 Ether
§ A is a contract where you can deposit and withdraw ETH. It keeps a record of fallback(){
withdraw(){ A.withdraw()
how much it owes to other contracts. In our case, A owes 1 Ether to contract B check balance>0 }
send Ether attack(){
§ Contract B has two functions: fallback() and attack(). Both functions call balance=0 A.withdraw()
2 1
withdraw() on A } }

1. First, B executes attack(), which calls withdraw() on A


2. A checks that the balance of B is greater than 0 and sends 1 Ether to B A B
9 Ether 1 Ether
(Contract B has 1 Ether, A has 9 Ether left) B: 1 Ether
3. Receiving Ether triggers fallback() on B, which immediately calls withdraw() fallback(){
withdraw(){ A.withdraw()
again check balance>0 3 }
send Ether attack(){
4. withdraw() checks the balance of B and since it is still 1, A sends another balance=0
4
A.withdraw()
Ether to B } }

5. Now, A has 8 Ether and B has 2 Ether, while the balance of contract B in A is
still 1 Ether. B calls withdraw() again. A B
6. withdraw() checks the balance of B and since it is still 1, A sends another 8 Ether
B: 1 Ether
2 Ether

Ether to B fallback(){
withdraw(){ A.withdraw()
7. This process between withdraw() and fallback() continues since the check balance>0
5
}
send Ether attack(){
balance reset line in withdraw() cannot be reached. As long as this is balance=0
6
A.withdraw()
the case, B can keep on withdrawing from A }
.
}

.
.
07 Ethereum Smart Contracts © sebis 50
Prevention Measures Against the Re-entrancy Attack

How to prevent a re-entrancy attack?

§ Ensure all state changes happen before calling external contracts (update balances or code internally
before calling external code)

§ Use function modifiers that prevent re-entrancy

https://solidity-by-example.org/hacks/re-entrancy/
07 Ethereum Smart Contracts © sebis 51
Message Object
Some contracts may require information about the caller of a function, e.g. for authentication
purposes. Solidity provides the global msg object that contains information about the caller. It does not
matter whether the caller of the function was an externally owned account or another contract.

The object refers to the last account that was responsible for invoking the function. This can either be
a contract or an externally owned account.

msg.sender
The account address of the function’s caller, which has type address (NOTE: Needs to be cast to
address payable when calling transfer, send, or call).

msg.data
The complete payload of the message/transaction

msg.sig
The function’s hash signature so that the EVM knows which function is called

msg.value
The amount of Wei that is sent with the message

07 Ethereum Smart Contracts © sebis 52


Message Object (cont.)

Since the message object always refers to the last sender, it requires some special attention when used in
combination with this in a contract.

contract A {
function f() public returns (address a) {
return msg.sender;
}

function g() public returns (address a) {


return f(); // f() is called directly msg.sender will be the address which calls g(). f() does not need to be public
}

function h() public returns (address a) {


return this.f(); // f() is called by the current contract instance => msg.sender will always be equal
// to address(this). f() has to be public
}
}

07 Ethereum Smart Contracts © sebis 53


Block Object

Some contracts may require information about the latest mined block, e.g. when a specific function
should be time locked. Solidity provides a global variable called block to access the most recent block
of the blockchain.

block.coinbase
The account address of the current block’s miner

block.difficulty
The current mining difficulty as unsigned integer

block.gaslimit
The current block’s gaslimit (by the miner)

block.timestamp
The UNIX timestamp of the block (in theory, can by manipulated by the miner)

07 Ethereum Smart Contracts © sebis 54


Transaction Object

The global tx is similar to the msg object and provides information about the transaction that triggered
the function call.

The main difference is that tx always refers to a transaction, i.e., its source is always an externally
owned account.

tx.origin
The issuer of the transaction. This is always an externally owned account.
DO NOT USE FOR AUTHENTICATION!

tx.gasprice
Information about the gas price that was used by the issuer of the transaction

Transaction Message Message


to call A.f() Contract A to call B.g() Contract B to call C.h() Contract C
EOA
f(){B.g()} Gas provided g(){C.h()} h()
Gas provided
by origin by origin
tx.origin msg.sender = tx.origin transaction is msg.sender = A transaction is msg.sender = B
forwarded forwarded

07 Ethereum Smart Contracts © sebis 55


Events
§ When a contract wants to communicate with dApps, it emits events.
§ These events are dispatched signals that are fired by contracts, and the developers of the contract decide
when to emit events.
§ dApps or any program using the Ethereum API can read these events.
§ An event attribute can be declared as indexed so that the event history can be efficiently filtered for events
with an exact match on this attribute.

Example
§ As of February 2022, the most common event on the Ethereum blockchain is the Transfer event. It is emitted
when transferring tokens:

§ The emit keyword is used to emit the event parameters, which are declared inside the contract code.
§ The transfer event logs who sent the transfer (from), who it was transmitted to (to), and how many tokens
were sent (value).

https://ethereum.org/de/developers/tutorials/logging-events-smart-contracts/
07 Ethereum Smart Contracts © sebis 56
Example: Defining and emitting an event signaling a change of a counter

07 Ethereum Smart Contracts © sebis 57

You might also like