Lecture 16 (Solidity Programming)
Lecture 16 (Solidity Programming)
https://docs.soliditylang.org/en/v0.8.10/
Solidity Programming
• It is an object-oriented programming language that was
specially built by the Ethereum team itself to enable
developing and designing smart contracts on Blockchain
platforms.
• Solidity programming language is used to write smart
contracts to implement business logic in the system to
generate a chain of transaction records.
• Solidity is a curly-bracket language. It is influenced by C++,
Python and JavaScript, and is designed to target the
Ethereum Virtual Machine.
• Not only a language, but Solidity programming is also a tool
that generates machine-level code and compiles the code
Solidity Programming
• Having similarities with C and C++, Solidity programming is
simple to learn and understand.
• Any developer with knowledge of C, C++ or Python for that
matter, can quickly familiarize with the concepts and syntax of
Solidity, which is very similar to those languages. For example,
a “main” in C is equivalent to a “contract” in Solidity.
• Solidity is statically typed, supports inheritance, libraries and
complex user-defined types among other features.
• Like other languages, Solidity programming has variables,
functions, classes, arithmetic operations, string manipulation
and many other concepts that are available in other modern
programming languages. https://docs.soliditylang.org/en/v0.8.10/
Layout of a Solidity Source File
Source files can contain an arbitrary number of
• contract definitions,
• import directives,
• pragma directives,
• struct, enum, function, error and
• constant variable definitions.
Layout of a Solidity Source File
SPDX License Identifier
• Making source code available always touches on legal problems with regards to
copyright, the Solidity compiler encourages the use of machine-readable SPDX license
identifiers.
• Every source file should start with a comment indicating its license:
// SPDX-License-Identifier: MIT
• The compiler does not validate that the license is part of the list allowed by SPDX, but
it does include the supplied string in the bytecode metadata.
• If you do not want to specify a license or if the source code is not open-source, please use
the special value UNLICENSED.
• Supplying this comment of course does not free you from other obligations related to licensing like
having to mention a specific license header in each source file or the original copyright holder.
• The comment is recognized by the compiler anywhere in the file at the file level, but it is
recommended to put it at the top of the file.
Layout of a Solidity Source File
Pragmas
• The pragma keyword is used to enable certain compiler
features or checks.
• A pragma directive is always local to a source file, so you have
to add the pragma to all your files if you want to enable it in
your whole project.
• If you import another file, the pragma from that file does not
automatically apply to the importing file.
Layout of a Solidity Source File
Version Pragma
• Source files can (and should) be annotated with a version pragma to
reject compilation with future compiler versions that might bring
incompatible changes.
• It is always a good idea to read through the changelog at least for
releases that contain breaking changes.
• These releases always have versions of the form 0.x.0 or x.0.0.
• The version pragma is used as follows: pragma solidity ^0.5.2;
• A source file with the line above does not compile with a compiler earlier than version
0.5.2, and it also does not work on a compiler starting from version 0.6.0 (this second
condition is added by using ^). Because there will be no breaking changes until
version 0.6.0, you can be sure that your code compiles the way you intended.
Layout of a Solidity Source File
Importing other Source Files
• Solidity supports import statements to help modularise your code that are
similar to those available in JavaScript.
• However, Solidity does not support the concept of a default export.
• At a global level, you can use import statements of the following form:
import "filename";
• The filename part is called an import path.
• This statement imports all global symbols from “filename” (and symbols
imported there) into the current global scope so it is better to import specific
symbols explicitly.
• The following example creates a new global symbol symbolName whose
members are all the global symbols from "filename":
import * as symbolName from "filename";
Layout of a Solidity Source File
Comments
• Single-line comments (//) and multi-line comments (/*...*/) are possible.
Smart Contacts in Solidity
• A simple example
Smart Contacts in Solidity
Pragmas are common instructions for
compilers about how to treat the source code. source code is licensed under the GPL
version 3.0
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.
• A detailed example
Smart Contacts in Solidity
o The line address public minter; declares a state variable of type
address.
o It is a 160-bit value that does not allow any arithmetic
operations.
o It is suitable for storing addresses of contracts, or a hash of the
public half of a keypair belonging to external accounts.
o Keyword public automatically generates a function that allows you to
access the current value of the state variable from outside of the
contract.
o Without this, other contracts have no way to access the
variable.
o The next line, mapping (address => uint) public balances; also creates
a public state variable, but it is a more complex datatype.
o The mapping type maps addresses to unsigned integers.
o Mappings can be seen as hash tables which are virtually
initialised such that every possible key exists from the start and
is mapped to a value whose byte-representation is all zeros.
Smart Contacts in Solidity
o The line event Sent(address from, address to, uint amount);
declares an “event”, which is emitted in the last line of the
function send.
o Ethereum clients such as web applications can listen for these
events emitted on the blockchain without much cost.
o As soon as it is emitted, the listener receives the arguments
from, to and amount, which makes it possible to track
transactions.
o Errors allow you to provide more information to the caller about why
a condition or operation failed. Errors are used together with the
revert statement.
o The revert statement unconditionally aborts and reverts all changes
similar to the require function, but it also allows you to provide the
name of an error and additional data which will be supplied to the
caller so that a failure can more easily be debugged or reacted upon.
Smart Contacts in Solidity
o The send function can be used by anyone (who already has
some of these coins) to send coins to anyone else.
o If the sender does not have enough coins to send, the if
condition evaluates to true.
o As a result, the revert will cause the operation to fail while
providing the sender with error details using the
InsufficientBalance error.
Basics of Solidity
Programming
Types
https://docs.soliditylang.org/en/v0.8.10/
types.html
Value Types
Fixed Point Numbers
• fixed / ufixed: Signed and unsigned fixed-point number of
various sizes.
• Fixed point numbers are not fully supported by Solidity yet.
They can be declared but cannot be assigned to or from.
• Operators:
Value Types
Address
• The address type comes in two flavors, which are largely
identical:
• address: Holds a 20-byte value (size of an Ethereum address).
• address payable: Same as address, but with the additional
members transfer and send.
For example:
address payable x = address(0x123);
address myAddress = address(this);
Value Types
Address
• Members of Address-
• balance and transfer
For example:
address payable x = address(0x123);
address myAddress = address(this);
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);
Value Types
Address
• Members of Address-
• send
Send is the low-level counterpart of transfer. If the execution
fails, the current contract will not stop with an exception, but
send will return false.
For example:
contract FixedArrays{
bytes2 public x; //fixed-size array of 2 octets
bytes3 public y; //fixed-size array of 3 bytes
}
Value Types
Arrays
• Dynamic: In dynamic array, bytes represents the
dynamically-sized byte array whereas string represents the
dynamically-sized UTF-8-encoded string.
For example:
Contract dynamic array{
uint[] public myArray = [1, 2, 3, 4];
}
Value Types
Enum
• It is one way to create a user-defined type in Solidity.
• They are explicitly convertible to and from all integer types,
but implicit conversion is not allowed.
• The explicit conversion from integer checks at runtime that
the value lies inside the range of the enum and causes a
failing assert otherwise.
• Enums needs at least one member, and its default value when
declared is the first member.
• Enums cannot have more than 256 members.
For example:
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
Value Types
Functions
• Function types are the types of functions.
• Variables of function type can be assigned from functions and
function parameters of function type can be used to pass
functions to and return functions from function calls.
• Function types come in two flavors
- internal and external functions.
For example:
function (<parameter types>) {internal|external} [pure|view|
payable] [returns (<return types>)]
• pure functions can be declared in which case they promise not to read
from or modify the state.
• view functions can be declared in which case they promise not to modify
Value Types
Functions
• Functions must be specified as being external, public, internal
or private. For state variables, external is not possible.
o external: External functions are part of the contract interface,
which means they can be called from other contracts and via
transactions.
o public: These functions are part of the contract interface and can
be either called internally or via messages. For public state
variables, an automatic getter function is generated.
o internal: Those functions and state variables can only be accessed
internally (i.e., from within the current contract or contracts deriving
from it, without using this.
o private: These functions and state variables are only visible for the
contract they are defined in and not in derived contracts.
Value Types
Modifier
• Typically, a modifier ensures the logicality of any condition
before executing the code for a smart contract.
For example:
modifier priceGreaterThan10000{
require(price > 10000);
_;}
function setPrice(uint _price) public onlyOwner
priceGreaterThan10000{
require(_price > price);
price = _price;
}
Value Types
Mapping
• mapping types with the syntax mapping
(_KeyType => _ValueType).
• The _KeyType can be any elementary type.
• This means it can be any of the built-in value types
plus bytes and string.
For example:
pragma solidity >=0.4.0 <0.6.0;
contract MappingExample {
mapping(address => uint) public balances;
function update(uint newBalance) public {
balances[msg.sender] = newBalance; } }
Basic Data Types
State variables
• The variables whose values are permanently stored in
contract storage.
For example:
pragma solidity >=0.4.0 <0.6.0;
contract SimpleStorage {
uint storedData; // State variable //
... }
Basic Data Types
Events
• They are convenience interfaces with the EVM logging
facilities.
For example:
pragma solidity >=0.4.21 <0.6.0;
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() public payable {
// ...
emit HighestBidIncreased(msg.sender, msg.value ); // Triggering event } }
Basic Data Types
Structures
• Structs are custom defined types that can group several
variables.
For example:
pragma solidity >=0.4.0 <0.6.0;
contract Ballot {
struct Voter { // Struct
uint weight;
bool voted;
address delegate;
uint vote; }
}
Advantages of Solidity
Programming
• Solidity programming, apart from the basic data types, also supports
complex data types and member variables. As read above, data
structures like mapping are compatible with Solidity programming.
• To enable type-safety, Solidity programming provides an ABI. The ABI
issues an error if the compiler encounters a data type mismatch for
any variable.
• Solidity supports multiple inheritance with C3 linearization which
follows an algorithm to determine the method that should be used in
case of multiple inheritance.
• Solidity programming refers to the ‘Natural Language Specification,’
for converting user-centric specifications to machine understandable
language.
Advantages of Solidity
Programming
Solidity Programming
• Create account with metamask chrome extension
(Ethereum wallet)
• Switch to Ropsten test network
• Get coins from ropsten faucet
class Block:
def __init__(self, previous_block_hash, data, timestamp):
self.previous_block_hash = previous_block_hash
self.data = data
self.timestamp = timestamp
self.hash = self.get_hash()
• #function to create our own hash this hash will be take all the data in the block header and run
SHA 256 two time (inner and outer encryption)
• #Only considered the previous block hash, data and timestamp to be part of block for simplicity.
Step 1: Define the structure of a block
• Define a class:
Step 2: Define the function to perform the
hashing of block components
def get_hash(self): #will take only object self as it has all we need for this
function
#generating binary representation of the header
header_bin = (str(self.previous_block_hash) +
str(self.data) +
str(self.timestamp)).encode() #encode function
#we convert all the data in strings to feed it as input for hash function SHA256 (in this
function two-level hashing is illustrated in the from of inner hash and outer hash)
#encode() is used to encode the code into unicode
inner_hash = hashlib.sha256(header_bin.encode()).hexdigest().encode()
#hexdigest() convert the data in hexadecimal format
#hashlib.sha256 is used for hashing using SHA256 from library hashlib
outer_hash = hashlib.sha256(inner_hash).hexdigest()
return outer_hash
Step 2: Define the function to perform the
hashing of block components
Step 3: Creating a genesis block (Static
Coding Method)
def create_genesis_block():
return Block("0", "0", datetime.datetime.now())
A static method is bound to a class rather than the objects for that class. This means that a static
method can be called without an object for that class. This also means that static methods cannot
modify the state of an object as they are not bound to it.
Step 3: Creating a genesis block (Static
Coding Method)
Resultant of Step1, 2 and 3 (block.py)
b1 = Block.create_genesis_block()
Print(b1.hash)
Creating Blockchain
• Generate the Genesis block and print its hash on
screen
Creating Blockchain
• Lets add some elements to our blockchain
• For simplicity, lets fix the number of blocks
num_blocks_to_add = 10
Creating Blockchain
• Lets add some elements to our blockchain
• Initialize the loop and append the blocks
datetime.datetime.now()))
Creating Blockchain
• Lets add some elements to our blockchain
• Initialize the loop and append the blocks
Adding more blocks to
Blockchain