Mastering Ethereum

By Merunas Grincalaitis
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Blockchain Architecture

About this book

Ethereum is one of the commonly used platforms for building blockchain applications. It's a decentralized platform for applications that can run exactly as programmed without being affected by fraud, censorship, or third-party interference.

This book will give you a deep understanding of how blockchain works so that you can discover the entire ecosystem, core components, and its implementations. You will get started by understanding how to configure and work with various Ethereum protocols for developing dApps. Next, you will learn to code and create powerful smart contracts that scale with Solidity and Vyper. You will then explore the building blocks of the dApps architecture, and gain insights on how to create your own dApp through a variety of real-world examples. The book will even guide you on how to deploy your dApps on multiple Ethereum instances with the required best practices and techniques. The next few chapters will delve into advanced topics such as, building advanced smart contracts and multi-page frontends using Ethereum blockchain. You will also focus on implementing machine learning techniques to build decentralized autonomous applications, in addition to covering several use cases across a variety of domains such as, social media and e-commerce.

By the end of this book, you will have the expertise you need to build decentralized autonomous applications confidently.

Publication date:
April 2019
Publisher
Packt
Pages
490
ISBN
9781789531374

 

Chapter 1. Blockchain Architecture

Blockchain architecture covers the fundamentals when it comes to understanding how the blockchain works internally. It is essential to be able to work on different projects that use different areas of Ethereum, because once you have a solid understanding about how everything works together, your mind will begin to see things differently. You will get a high-level overview of what happens in the blockchain when you use it and when you program for it. The moving parts of this complex ecosystem will begin to make so much sense once you go through this chapter, because you'll receive a high-level overview of how smart contracts work and how they are related to the underlying structure.

In this chapter, we will cover the following topics:

  • Beyond Ethereum
  • The EEA
  • Understanding the Ethereum blockchain
  • A high-level overview of how smart contracts work
  • Essential smart contract programming
 

Beyond Ethereum


You probably understand what Ethereum is, but just to make sure that we are on the same page, it's important that you have some background knowledge about what Ethereum really is in order to progress further without too many distractions.

Explaining Ethereum

Ethereum is, first and foremost, a blockchain. Ethereum is a technology that runs on many computers and provides its consumers with a guarantee that they are trusting a solid system that will work as expected.

"Ethereum is the world computer."

-Vitalik Buterin

Note

To learn more about the core Ethereum ideas, check their official website: https://ethereum.org.

A web of thousands of computers connected all over the world are called nodes and they allow others to get the information they need while trusting the code with the goal of decentralizing the internet as we know it.

Why is decentralization so important for the internet? Because we have come to a point where a few big companies control the information that you and I can produce or consume.

Governments have so much power that they are getting out of control with their rules. They are biased toward what benefits them and their governors. And it's understandable—whenever some entity is at the top of the food chain, it is inevitable that they end up controlling the entire system below it sooner or later.

Ethereum's goal is to create a censorship-resistant and open platform that allows people to trust smart contracts that enforce rules that cannot be controlled by third-party entities.

When you publish a smart contract, you have a 100% guarantee that the code will run at any point and nobody will be able to interfere with it, unless the rules of it say so.

Ethereum's history

Ethereum was described in Vitalik Buterin's 2013 whitepaper, which can be found at: https://github.com/ethereum/wiki/wiki/White-Paper. He talked about the need of a scripting language that would run on top of Bitcoin, since he was involved in Bitcoin Magazine and he understood the limitations of the Bitcoin blockchain.

He saw an opportunity to create a platform that would run on decentralized technology to create new types of applications.

Not many believed in his vision, so he decided to create an entire new blockchain by himself with a small team that saw the potential in Vitalik's ideas. He founded the Ethereum Switzerland group and decided to run an Initial Coin Offering (ICO) in July 2014, where he sold Ether in exchange for Bitcoin, raising a total of about $18 million dollars.

He created the smart contracts technology, which is basically programs that run by themselves without requiring a trusted entity to execute them. They are always available, and they run without failure.

The fact that Ethereum provided a system that allows people to create their own applications on top of a blockchain is what made it successful. Before Ethereum, there was no simple way to create decentralizedapplications (dApps) in a decentralized platform. Bitcoin has a protocol to create simple applications using opcodes with a programming language called Script, but it's not capable of much since it is very low level and it's limited by the block size.

Ethereum's development

The development of Ethereum was planned to be done in four different stages, with major changes in each one:

  • Frontier
  • Homestead
  • Metropolis
  • Serenity

It was used to deliver and research innovative solutions as they were required, with a hard fork for functionality that is not backward compatible. In 2015, Frontier was launched as the first version of Ethereum. A year later, Homestead was launched, which included many improvements and made Ethereum a capable system with enough power to process smart contracts.

One of the biggest ICOs conducted on top of Ethereum was the decentralized autonomous organization ICO, also known as the DAO, which raised $150 million dollars with contributions from more than 11,000 people. The problem is that it got hacked by an unknown group of individuals that moved the funds to a different DAO. Interestingly enough, a group of programmers known as the White Hat Group saw the hack happening and extracted as many funds as possible into a separate decentralized organization known as the White Hat DAO, where they stored people's money to distribute them later.

This event originated a heated debate in the community that caused Ethereum to be divided in two groups, where some believed in the fact that Ethereum must be immutable and shouldn't be modified, while others believed in a hard fork to revert the damage done.

That was the beginning of Ethereum Classic and Ethereum as we know it. Ethereum Classic has a noticeable smaller user base, but it preserves the initial immutability ideals that they consider essential for a blockchain. In March 2017, several companies joined efforts to create the Ethereum Enterprise Alliance (EEA), which is currently a non-profit organization made of more than 500 members whose goal is as follows:

"To create open-source, standards-based blockchain specifications."

-Ethereum Enterprise Alliance

In other words, they created a group of people collaborating on solutions for future blockchains to come, so that they are better, faster, and more capable.

It suffered from several hacks, where millions of dollars were stolen. They had to do a hard fork to save people's funds and have a notorious price volatility, but the future looks bright and it continues, improve as demand increases.

 

The EEA


The EEA (entethalliance.org) is one of the most exciting projects being developed by the core Ethereum team, because they intend to help companies from all over the world to benefit from decentralized technology. By learning about this project, you'll be well positioned when it comes to working as an EEA expert.

In this section, we will cover the following topics:

  • The EEA's vision
  • The EEA membership
  • The EEA architecture

Vitalik funded the organization because he received a huge demand from executives to create software that could be used in big companies to handle demanding dApps. Those companies now want to build a private version of Ethereum to fulfill their research and development needs.

What's interesting about this initiative is that they work with hundreds of companies to research and develop solutions that are shared across them. For instance, if a company member of the EEA creates a new implementation protocol for better and faster dApps, they will share it with the other members so that they can also benefit from this cutting-edge research, while together growing the Ethereum ecosystem.

The EEA's vision

The EEA's four big public goals that they envision they will achieve in the longer term are as follows:

  • Be an open source standard, not a product:

They only work with open source code that can be shared with anybody publicly without restrictions in order to spread development advances that may or may not help others improve their blockchain products. You see, they are a non-profit organization that wants to move blockchain (as we know it) further by combining the efforts of many companies interested in private blockchain solutions.

  • Address enterprise development requirements:

The EEA helps companies incorporate the new innovations that are being discovered by others for free, so that they can enjoy the benefits of the latest requirements.

  • Share improvements between public and private Ethereum:

They want to improve what they are building by taking improvements from the public blockchain so that they can evolve faster while keeping a great product in mind.

  • Leverage existing standards:

When it comes to the blockchain technology, much is left to research and discover. Many problems regarding scalability, security, and transparency are being studied, since this type of decentralized structure is new to modern computing. So, the idea is to learn from existing standards, such as proof-of-stake (PoS), to improve faster than anyone else.

In essence, they are trying to fulfill the demands that many companies are making regarding private enterprise and fast blockchains for their personal applications.

The EEA membership

What's interesting about the EEA is that any company is free to join by just filling a form on their website to become a member of the group for a yearly cost. This openness helps many individuals stay relevant with the new improvements on the Ethereum blockchain.

Here's the breakdown in yearly costs to become a member:

  • Less than 50 employees: $3,000 per year
  • Between 51 and 500 employees: $10,000 per year
  • Between 501 and 5,000 employees: $15,000 per year
  • More than 5,000 employees: $25,000 per year

Non-profit organizations only pay $3,000 dollars per year, regardless of company size. By becoming a member of the Alliance, you can enjoy a series of general benefits, such as being able to participate in discussions, voting, open source code, meetups, and the prestige that you get from having the EEA logo in your website. As a big blockchain company, it makes sense to become a member just for the reputation that you'll get by becoming a member with the EEA logo on your website.

The benefits depend on the type of company you are in, and you can see them in the following section:

  • Class A members are the directors that run the companies associated with the Alliance. They have priorities when reaching decisions and have access to all the benefits.
  • Class B members are those that have a normal company, so they get standard benefits without exclusiveness.
  • Class C members are lawyers and legal firms that are in charge of the legal challenges when it comes to the research done in the EEA.
  • Class D members are non-profit companies and academic institutions. They get basic benefits for the lowest price without voting rights.

The EEA has a powerful pool of about 500 companies, including giants such as Intel, Microsoft, and J.P. Morgan. If you run a decent-sized company, you may be interested in becoming a member of the EEA just to be a part of this revolution when it comes to enterprise blockchains.

The EEA architecture

The enterprise grade applications built with EEA's tools have a very interesting structure that builds on top of the existing Ethereum structure. They developed the Enterprise Ethereum Architecture Stack (EEAS), which is a design that specifies how this new type of Ethereum blockchain should work in a private setting, with features designed for privacy. The team working on the Ethereum Enterprise project details functions of this type of private blockchain without regard to the underlying technology below it, such as software code, APIs, and communication protocols. What the EEA intends to do is focus on creating what's described in their specification so that people can enjoy private blockchains for their companies.

The tooling will benefit from innovative solutions exclusive to the Enterprise Ethereum blockchain, such as the following:

  • Hardware security module (HSM): This is a physical computing device that safely stores digital keys, such as your private cryptocurrency keys, with maximum security features. For instance, Ledger and Trezor are hardware wallets that are also called HSMs, because they provide security in a physical device for your blockchain private keys.
  • Permissioning and authentication: This is useful in order to give users specific roles with limited access to certain areas in a more structured fashion.
  • Enterprise management systems: This is used to help companies control their private blockchain internal workings.
  • Oracles: These are helpful for communicating with external services for custom smart contracts written on top of the enterprise private blockchain. They are essential to exchange key information with the outer world.

Regarding privacy and scaling, we know that many different teams are working on creating unique solutions that could benefit the entire community. However, we know that, initially, the blockchain will use two main systems to scale the capacity of existing dApps:

  • Off-chain transactions with trusted execution: Protocols such as plasma and state channels are being developed to leverage off-chain transactions that can be executed locally by users' computers to reduce the computing load of the main blockchain.
  • Private transactions: Transactions that use zero-knowledge proofs, ring signatures, and many other famous protocols to guarantee the privacy of the data being exchanged with the public blockchain. This is an important aspect that companies demand because they have private data and internal processes that can't be shared publicly. We cannot know which solution they will choose, so it's up to them to decide. They will also implement private code execution that will allow companies to execute certain smart contract transactions in a secure environment, where the users will see an encoded hash.

The EEA is building three additional elements on top of the existing core blockchain:

  • On-chain private state: This is a separate storage compartment where they will store private states of smart contracts. It will provide us, the developers, truly private variables and store functions that we'll be able to use for keeping information secure and unseen by the public. It's very powerful for enterprise-grade dApps.
  • Trusted execution: These are systems that will provide a trusted execution environment where the code will be executed without interfering with public processes.
  • Private consensus: Companies will have the ability to reach agreements using their own private blockchain for their own systems, similar to voting systems that we can see in the Decentralized autonomous organizations section in: Chapter 3, Ethereum Assets.

Lastly, the blockchain network layer will benefit from Enterprise P2P, which will be used to exchange transactions in smaller networks of nodes that are set up by the company, so that they enjoy the benefits of faster processing speeds and confirmation times. Enterprise blockchains will be able to interact with other networks, including the public blockchain to exchange information.

 

Understanding the Ethereum blockchain


The Ethereum blockchain is a complex system made of several important components that work together to achieve an impressive platform that everybody can use to create unstoppable applications. You'll learn the intricacies of the internal workings of the blockchain to gain a greater understanding about how it's made.

The reasoning behind a decentralized blockchain

At the most basic level, the Ethereum blockchain is a set of connected blocks that contain information that many nodes share so that there's an unchangeable data structure to keep information permanently. The goal of any blockchain is to preserve information without the possibility of changing it or deleting it to avoid censorship or manipulation by external entities.

As such, the Ethereum blockchain builds upon that concept by implementing several well-known tools, thanks to Bitcoin and previous research to create programs that run on top of those blocks.

To understand how the Ethereum blockchain works internally, we have to understand each component that makes up a blockchain. First, I'll give you a high-level overview of the blockchain as a set of nodes, and then we'll go through each component from higher to lower levels in the pyramid that makes the blockchain.

The blockchain as a set of nodes

Ethereum is a decentralized platform, which means that two or more nodes work together in a coordinated fashion to achieve a common outcome in a way that the end user sees as a single operation. A node performs various types of functions depending on the role it decides to take. It can propose and validate transactions with mining software to achieve consensus while securing the blockchain using the proof-of-work(PoW) protocol or be a light-weight node that performs payment verification and many other tasks that can be done with limited resources.

The Ethereum blockchain is based on Bitcoin, since the system created by Satoshi Nakamoto is a very robust decentralized solution. In fact, it uses a system to execute decentralized code using opcodes that can process basic instructions on top of a network of hundreds of thousands of computers in a safe manner. They must be simple to preserve security above all.

Although both blockchains are quite similar in their systems, they have noticeable differences, such as the following:

  • Bitcoin and Ethereum use PoW to generate blocks, while Ethereum intends to move to PoS as the block generation system in the future to avoid wasting computational power.
  • Ethereum uses the Ethash algorithm, while Bitcoin uses SHA256 for processing transactions and generating blocks.
  • Ethereum's block time is about 15 seconds, which is about 100 times faster than Bitcoin's. This gives people better confirmation times.

The Ethereum blockchain is decentralized and distributed, which means that the connected nodes have several relationships with each other independently, while running the same software at different locations. This is very important to guarantee the unstoppable aspect of the blockchain. Here what each term means:

  • Decentralized network: This is a network of computers running without a single point of control, no entity controls the entire system, and each node is connected to other nodes directly in a peer-to-peer (P2P) relationship. If the blockchain wasn't decentralized, some government or entity could locate the main controller node and stop the entire system immediately.
  • Distributed network: This is a network where many different computers run on different locations with the same software. If the blockchain wasn't distributed, some entity could go to where all the nodes are located and stop the entire operation because they are all in the same place, so none are safe from such an attack.

You can see in the following diagram how the structure of these types of technologies connect nodes together so that they can communicate with complete security, in their own way, since it's often a confusing point when trying to understand the differences between distributed and decentralized systems:

Those two characteristics give the Ethereum network the capacity to work without having to rely on anybody, because thousands of nodes are able to communicate between each other in a secured and independent fashion. Notice that Ethereum is a completely open blockchain, meaning that anybody is free to join and participate in the decisions that take place, such as block creation and transaction processing. It allows people to join the network of nodes as a participant without any requirements, since the entire structure is secured by cryptographically-safe algorithms.

Nodes can work together or become malicious by executing unexpected code. Those that exhibit arbitrary behavior are known as Byzantine nodes. The main goal is to create a system where nodes cooperate even in the worst situations, with fault-tolerance protections in place to avoid breaking the entire structure. But how do they work together if the nodes making the blockchain can behave randomly because they are Byzantine nodes?

At the end of the day, it's a group of computers working voluntarily toward the same objective. Nothing stops them from doing unexpected actions. That's where one of the most interesting problems that blockchain is facing lies. There are several solutions, but research is still being done to obtain a perfect balance between performance and security in a decentralized system.

The CAP theorem

The CAP theorem, introduced originally by Eric Brewer in 1998, states that any distributed system cannot have all three of these properties simultaneously:

  • Consistency: This is a capability of the network of nodes to keep a consistent copy of the blockchain data in their computers at the same time.
  • Availability: This means that the system of connected nodes is online and available at all times while being accessible by all users to respond to requests without failure when required to do so.
  • Partition tolerance: If a group of nodes of the entire network stops working or loses connection for any reason, the system should not be affected, and it should continue working properly as if nothing happened.

It has been proven that a distributed or decentralized system cannot have all three of these properties at the same time, which is interesting because Ethereum, just like Bitcoin, achieves all of them at what appears to be the same time. The truth is that consistency is not achieved at the same time as partition tolerance and availability, but at a later time. You see, in order to have order in such a diverse variety of computers, we can only hope to achieve the same level of data over time whenever the blockchain grows at an established pace. It lags behind the others. This is called eventual consistency, where the goal is achieved as a result of validating multiple nodes over time. For this reason, the concept of mining was introduced in Bitcoin and Ethereum to agree on a consensus with the PoW protocol.

Eventually, Ethereum plans to move to PoS, which consists of the idea that a node or user maintains a stake, a certain number of Ether or any type of valuable investment in the system, so that the negative consequences of any malicious activity would outweigh the benefits of attacking the network.

For instance, if I want to become a miner to earn some Ether in exchange for my time and resources, I have to lock 100 Ether in a smart contract that runs the PoS protocol. If I decide to validate invalid blocks or transactions, and someone notices my malicious behavior via several security mechanisms, I would lose all those 100 Ether and wouldn't be able to attack again. The reward for processing a block successfully would be a percentage of the resources invested, for example, 0.1 ETH. This forces nodes to cooperate and act responsibly to avoid losing a big stake, even if they agree to attack the system.

Alternatively, delegated proof-of-stake (DPoS) could be used in later versions of Ethereum. It consists of delegating the validation of a transaction to other nodes by voting. It is used in the BitShares blockchain.

Introducing the Ethereum Virtual Machine

The Ethereum Virtual Machine (EVM) is a virtual machine that allows code to be executed with limitations regarding gas costs and price, where each individual interacting with it must pay a fee to protect the network from spamming attacks, so that many decentralized nodes can interact with each other using the same software. It processes bytecode that gets generated with assembly code, which, in turn, uses instruction called operational codes (opcodes). It's a Turing complete computer.

When I say Turing complete, I mean that the smart contract programming languages running on top of Ethereum have the following properties:

  • They have unlimited access to random access memory (RAM)
  • They can make decisions based on the information available in memory
  • They can run forever with the help of while, for, and recursive loops
  • They can use functions

What this means, is that smart contracts are capable of executing any operation that you give them, given enough time and resources. This is important to understand to avoid confusions when someone says that Ethereum is a Turing complete blockchain.

Introducing the state machine

The state machine is a mechanism that keeps track of the state changes that occur on the blockchain. For instance, a normal day has two simple states, either day or night. A state machine would record the situation of each day at every moment so that when the sun goes down, the state of the day changes to night. It is the same thing with the days of the week. Each day can be one out of seven different states, such as Monday or Friday. Whenever it changes at 12 am, the state that keeps track of the day of the week gets updated in the state machine.

The state machine enforces consensus rules to make sure that users are processing valid transactions in a Byzantine resistant system:

  • A P2P network: It connects the participants and propagates the transactions and blocks of verified transactions. This is the network used by the nodes of the blockchain to propagate information between them to achieve consensus.
  • An incentivization scheme: In the case of Ethereum, that scheme is PoW for creating an economically secure state machine. Ethereum developers plan to move to a PoS system where the users will process transactions using a passive system of transaction verification based on the number of ETH that the miner locks at that moment.
  • An open source client: This client is the one used by the nodes to interact with the blockchain. In Ethereum, we have Geth, Parity, and many others that allow you to connect to the blockchain for mining and processing transactions and all sorts of tasks after downloading the blockchain.

Note

You can download a light version of the blockchain by downloading the client Geth and running geth --fast, which only keeps track of the reference numbers of each block to limit the download size of the blockchain, since it can reach several hundreds of gigabytes. The purpose of the light client is to make the Ethereum blockchain available for low-spec computers with limited storage and computing power.

The P2P network

The blockchain runs on top of a P2P network, where nodes are connected to each other to exchange data and state updates. Because of this technology, we are able to interact directly with other computers in order to process orders so that we all agree on the block generation system. It allows miners to be rewarded for completing PoW challenges.

Consensus rules

When we say consensus, we talk about a group of techniques used in systems with many participants to agree on decisions that benefit the whole underlying system. While voting gives the power to decide to a few selected individuals that fulfill a set of requirements, consensus takes in consideration each and every one of the participants to agree on the global way of thinking.

Each algorithm that implements any form of consensus when it comes to blockchain technology must provide the following features:

  • To agree on decisions that benefit the whole system: The idea is to take choices that not only benefit the individual, but the entire network, so that everybody has a better platform.
  • To allow open participation: Every person should be completely free to join and make decisions that they believe will be positive.
  • To be secure enough so that malicious actors can't prejudice the system: All the consensus agreements have to be toward the betterment of the systems, where malicious users can't have enough power to decide for many others.

The problem with reaching consensus started with what's known as the Byzantine Generals Problem, a problem that consists on the fact that many computers can't easily agree on a predetermined order. Some computers will receive the order late, others will ignore it because they don't benefit from fulfilling it, while others will follow the order as best as they can.

In essence, consensus rules are mandatory to achieve a global state that all agree with, while being rewarded for participating in a beneficial manner in the decision-making process.

Proof-of-work

This is a method to guarantee that the result of a task was hard to achieve. Why do we want to make processing tasks difficult? To reward those that are best at completing it. In a blockchain, it costs processing power, which is just hardware, energy, and time, to process transactions made by individuals using the network. It is used to generate blocks in a simple process:

  • The miner proposes a new block that contains a hash number made of the header of the most recent block and the nonce counter.
  • Then, the miner compares the hash to the target value which is determined by the mining difficulty.
  • If the hash is of the target difficulty, the user gets rewarded with the solution by getting ETH. If not, the nonce gets incremented until a hash is generated with the desired solution.

Since the miner will be competing with many others, there must be a system to make sure that the block times are consistent, because we want to keep generating blocks with the same periodicity even when new nodes join the mining network. To guarantee similar block times, the mining difficulty was created.

Proof-of-stake

PoS is a new algorithm to reach consensus between nodes in a decentralized blockchain that focuses on removing the high computing performance requirements from PoW while still keeping the network safe from attacks and malicious behavior. The way it works is based on locking Ether as a stake and validating blocks with the risk of losing your stake if you misbehave. Here's the process:

  • People that want to participate in the PoS process are called validators. They start by locking a specific number of coins as their stake (for instance, 100 Ether) that they can't touch while they are mining. It should be expensive enough to guarantee that groups of people don't agree on attacking the system with the risk of losing their stake if they're unsuccessful.
  • Then, they start receiving transactions from people using the Ethereum blockchain. Validators run programs to validate that the transactions they are receiving are valid so that they can create new blocks by grouping transactions in order. When they have enough transactions to cover the gas limit per block, they place bets on those blocks – for instance, 20 Ether from the initial 100 Ether staked.
  • The block with the most bets is selected as the winner.
  • When the winning block is selected from the pool of generated blocks, the miners that bet on that valid block get a percentage of the total gas used in that block based on their bets. They are not paid in block rewards but in transaction fees. For instance, if the block selected has 100 transactions accumulating a total of 0.5 Ether in transaction costs, that 0.5 Ether will have to be distributed between all the validators that bet on that block. If that block has a sum bet of 1,000 Ether from 10 users and you bet 20 ether, you'd get a 2% of 0.5 Ether, since that's how much you bet for that block. In total, you'd earn 0.01 Ether.

You don't lose any money when betting for blocks, it's just an indicator of how much you trust the validity of that block. It may seem a small reward considering that there aren't block rewards, just fees, but you must consider that these blocks are being generated in a matter of seconds. Maybe even one second per block, which ends up generating a lot of money over the day.

It looks great in theory, but there's a major roadblock that's stopping PoS from being completely viable. It's called the Nothing at Stake problem and is shown in the following scenario, where there is a main chain and a new chain being created with PoS:

When it comes to PoW, you can mine on any fork that you desire without any risk, since you can place bets on every block that looks good to you. What's stopping you from deciding to put all your eggs in a new chain, thus generating a hard fork?

If we were using PoW, you couldn't move to a new chain without having to spend lots of processing power and time generating new blocks for as long as people decide to accept it as a new blockchain. You'd be mining for many months with a very slim chance of creating a new chain that could be accepted as a new coin, worth much less money because of its reduced use.

But with PoS, you can simply diversify your portfolio and bet on all the blocks that look appealing without consequences, since you won't be losing your stake as long as you're validating good transactions. You'd be generating blocks on several different blockchains without risks. This kind of possibility could end up creating hundreds of different blockchains, since people could be mining on all of them simultaneously. That's why it's called the Nothing at Stake problem, because you don't lose anything when participating in the mining process.

This is one of the main reasons why Ethereum has been unable to switch fully to PoS in recent times.

Researchers at Ethereum have been working on solving this problem for a long time. One of the proposals, known as Casper, intends to solve it by punishing users that mine on new chains mindlessly by taking their stake out of them, so that users focus on betting for the longest chain. Casper also punishes nodes that don't actively participate on the network so that they don't start consuming resources without providing value.

At the end of the day, PoW has to improve or change completely to become sustainable, given that many large mining pools are starting to gain too much power. We are at a point where four mining companies can achieve about 60% of the total transaction power, giving them the choice to run a 51% attack and force all users to mine on their own terms with their own corrupted blockchains. PoS is here to stay and bring balance back once again.

 

Workings of smart contracts


Smart contracts are blockchain applications that can execute code and do a diverse variety of tasks. These are programs that the miners execute when mining blocks. They are secure and unstoppable agreements that are automatically executed and enforced. You are probably familiar with them, since this book is aimed at Ethereum developers; however, if you don't know how to use them or if you want to learn more about them, you can rest assured that you'll understand everything because of detailed explanations that you'll be given at the appropriate times.

Unlike traditional paper contracts, smart contracts don't have real-world legal consequences on Ethereum, and they can't be enforced by a legal entity when they break. Instead, they rely on the principle that code is law, which means that the code is the one governing the behaviors of the contract. You can't execute functions that are not defined in the smart contract and you must respect each function's requirements.

What's interesting about smart contracts is that they allow the creation of unstoppable applications that will keep the data and functionalities running on top of the blockchain regardless of whether the underlying web interface is not available or is censured for whatever reasons. Smart contracts open the world to a new type of application that you can deploy and forget, knowing that it will work under any circumstances.

There's an ongoing debate about whether the code is acceptable as a real contract in a court of law. One side thinks that smart contracts have to go further and be enforced legally for a more general view of applications, while the other side thinks that the code as law is enough to guarantee the security and enforcement of the agreements.

Smart contracts are programs that run on top of the blockchain in the software layer. They allow developers to create decentralized trustless programs that have certain functions for managing transactions between individuals. Instead of relying on a centralized server, they are the database and the server in decentralized applications.

Inherently, smart contracts must be limited in their capacity given that we are executing code that will stay as a transaction on the blockchain permanently, meaning that every function you execute gets registered in the blockchain without having the option to undo what's been done. This imposes some natural limitations, since you can't just modify the public database that every node of the Ethereum will have to download without some restrictions. Every change has to be downloaded by all the peers of the network.

The purpose of them is to solve the trust problem that many companies are facing when dealing with voting, banking, and situations where people are expected to blindly trust companies without disclosing what they do with your data and money. They also provide accessibility, since anybody with an internet connection will be able to access them and retrieve the data stored inside.

However, smart contracts are limited in what they can do. They are not a great solution for many cases, such as the following:

  • Applications that require a performing backend that is able to process information at a rapid pace, such as creating users and interacting with an application. They are slow by nature, since they depend on the block times of Ethereum and they cannot work in real-time situations.
  • Applications that store large amounts of data on a database. Smart contracts work like a database, since they allow anybody to store certain information on top of the blockchain, but they are limited and it's costly to do so.

Gas is another concept that is important to understand properly. It was created because smart contracts are Turing complete, which means that they can execute loops such as while or for endlessly until a task is done. It could happen that developers create endless loops that are stuck in the same state forever. To avoid a situation where thousands of nodes are stuck processing one transaction with no limit, each transaction has a gas cost that depends on the processing power required to execute it.

So, they created a system where you have to pay for every action you take using the blockchain. You can store information on the blockchain, but you'll have to pay an important cost, because every single node using it will have to download your changes. The way it calculates the gas cost is simple:

  1. You pay a certain maximum gas that you're willing to spend for your transaction.
  2. Your local Ethereum node calculates how much it will cost to execute your transaction by checking the opcodes used to generate a precise approximation of the computing power needed. You see, every small operation using the blockchain can be measured because we use a sort of assembly language that tells us when this super computer is being used and how.
  3. The right amount of gas is used, and the rest is refunded to you.

You also have to determine a gas price ranging from 1 to usually 100 or more to tell miners which transactions to process first, since they get paid more the more expensive each gas is.

Smart contract deployment process

Smart contracts run on top of the Ethereum blockchain in a similar way to how a server-side web application works. However, the process of deploying a smart contract to it is vastly different. In order to be an expert Ethereum developer, you must understand how the smart contract code is processed and stored in the blockchain blocks for you to be able to use them, because it will give you an understanding of why and how things can go wrong when pushing your newly written smart contract code.

It's not uncommon to receive errors when trying to deploy your code to the blockchain, so to be able to debug it successfully, you need to understand what happens under the hood.

Ethereum transactions

To understand how smart contracts are deployed on the network, it's important to understand first how transactions work, since when you deploy a smart contract, what you're actually doing is generating a transaction with the bytecode of the application that you just built.

The message that makes up a transaction on Ethereum is made up of the following encoded components:

  • Recipient: This is the receiver Ethereum address that will get the transaction.
  • Value: This represents the amount of ether to transfer to the recipient address. This value can be zero, and you can access it in Solidity with the global msg.valuevariable. The value is always in wei, the smallest unit in Ethereum.
  • Data: This is a hexadecimal bytecode string that is mostly used to call a specific function with the required parameters. This is specific information that you need your smart contract to execute. When smart contracts communicate with each other, they need a way to tell when to execute a specific function with a given set of variables. Thanks to this data parameter, we can encode the functions that we want to call in the contract when the transaction is processed. On the other hand, when the smart contract is deployed to the blockchain for the first time, the data parameter contains the smart contract converted to bytecode so that machines can understand it. In general, it contains the smart contract functions to be executed in the next block by the miners.
  • Gas limit: This represents the gas limit, which is how much gas you're willing to spend to process your function transactions. The gas limit is represented in wei, and it's mandatory to give miners as much gas as possible to process your code.
  • Gas price: The gas price determines how much each gas you provide will cost. If your gas cost is one, you'll pay one wei per gas. If it's 20, you'll pay 20 wei per 1 gas. It's used to help miners process the transactions, since they will be rewarded partially with the transaction fees.
  • Nonce: The nonce is a unique counter number that is used to identify transactions. This unique counter is used to identify each block, and it helps miners to identify invalid blocks, since the nonce must always be one number bigger than the previous block.
  • Signature: This is a parameter made of three independent variables known as v, r, and s. These variables are used to sign transactions with your unique Ethereum address data so that people can confirm that you're the one that created it.

When a user makes a transaction to a smart contract, it's called a message instead of a transaction. This difference between transaction and message exists, because messages don't have signature data since they don't have to be signed by the other party. The nonce is required to prevent replay attacks where an external user could take the same transaction data and execute it again for his own benefit.

When you deploy a smart contract, you're actually sending a transaction to the address 0x0 with a special bytecode identifier, so that miners understand that you're creating a new smart contract. The data parameter in this case contains all the smart contract logic, including function names and parameters.

In summary, creating and working with smart contracts is a transparent process, where you tell miners to process your data. They will then understand the bytecode behind it and make the required changes to the blockchain with the needed parameters.

 

Essential smart contract programming


After understanding how smart contracts are created and where they integrate in the blockchain system, you will now get a more practical insight about how to create smart contracts using the two most popular languages for it—Solidity and Vyper.

Solidity

Solidity is the most advanced programming language created for developing smart contracts on the Ethereum network. Its syntax is similar to JavaScript, but with statically typed variables and functions. It provides simple features, such as functions, loops, and several types of variables, as well as complex functions, such as assembly, encryption functions, and signature verification systems.

It's been used in many projects, especially ICOs, with great success, so it's mature enough to be used by any kind of developer interested in developing decentralized applications and secure smart contracts.

The main drawback of it is that it's harder to secure, given that it provides a more complete set of features that could lead to security issues if not audited.

File structure

We'll use the 0.5.0 version of Solidity for all the examples in this book. A smart contract in Solidity always starts with the version that is used in the file to ensure that the contract is not compatible with newer versions that could break the contract because of newly added functionalities.

Let's look at the structure of a contract in Solidity using the following steps:

  1. You define the version at the beginning of the file with the pragma statement:
pragma solidity 0.5.0;
  1. Then you can start writing your contracts. All statements in Solidity must end with a semicolon (;) to be valid. After defining the version used in the file, you have to create the contracts, as shown here:
pragma solidity 0.5.0;
contract Example {}
  1. You can define multiple contracts in one single file:
pragma solidity 0.5.0;
contract Example {}
contract Another {}
contract Token {}
contract ICO {}
  1. Inside the contract, you'll have state variables, functions, modifiers, and a single constructor. I'll explain later how they are used in detail:
pragma solidity 0.5.0;
contract Example {
    uint256 counter;
    modifier onlyOwner {}
    constructor() {}
    function doSomething() {}
}
  1. The variables that are defined directly in the contract, meaning that they are outside functions, are called state variables. These are special variables that store their value even after executing the contract. Think of them as special permanent variables that you can always read and modify:
pragma solidity 0.5.0;
contract Example {
    uint256 myStateVariable;
    string myOtherStateVariable;
    function example(){
        uint256 thisIsNotAStateVariable;
    }
}

As you can see, they are outside functions but inside the contract, and they are defined at the top of the file, right when the contract begins. As I said, they keep their value forever, even after making changes to your contract. So, if your myStateVariable has a value of 5, you'll be able to read the value of that variable days or months after it has been modified, as long as you don't modify it.

They store their value directly on the blockchain storage, not in memory. In-memory variables, as you'll learn later, lose their value and are reset after the contract execution.

Finally, Solidity files use the .sol extension, for instance, example.sol. You will learn how to deploy them with the Remix IDE and Truffle in Chapter 3, Mastering Smart Contracts, and Chapter 9, Decentralized Exchanged Workflow.

Variables

Solidity is a statically typed language, which means that you have to define the type of every variable that you create.

Let's define the types of variables available in this programming language to later understand how to use them, but before that, you need to understand the visibility of variables.

Visibility of variables

Every variable and function in Solidity has a specific visibility. The visibility is a keyword you use after the variable type to define who should have access to it:

  • Public: This means that the variable can be read or written by any contract, including external ones, as long as there's a function to update them.
  • Private: Private variables can't be accessed by a derived smart contract, those that implement your contract with the iskeyword; for example, contract Example is Another {}, where Another is a smart contract with private variables that can't be accessed by Example.
  • External: These variables and functions are not accessible by the contract containing them. Only external contracts and users can use them.
  • Internal: These are variables and functions that can't be read or written by external entities, only by the contract itself or by inherited contracts, as you saw in the example for the private variable.

To keep things simple, I recommend you to always write public for your variables unless it's a special variable, which doesn't happen that often. If you don't define any visibility, the variable will be public by default, although it's better to just write the public keyword in every variable to make sure that you understand the visibility of the variable and it's not a mistake.

Uints

Uints are unsigned integers, which means that they are numbers starting from zero that can't be negative.

You define them as follows:

uint public myNumber;

As you can see, you first define the type of the variable, then the visibility, and then the name of the variable. Remember that if you don't define the visibility of the variable, the variable will be public.

Uints can be of the following types:

  • uint8
  • uint16
  • uint24
  • uint32
  • uint64
  • uint128
  • uint256

The number for each variable means the size of the uint. A uint8 type of variable will be able to store up to 256. So, the maximum variable of a uint8 variable is 256. If you want to store the number 255, the variable will work properly, but, if you want to store the number 256 as follows, then the variable will overflow, and it will reset to zero instead of256, because it exceeds the capacity of that type of variable:

uint8 public myNumber = 256;

When you try to store a value 256, the variable resets because it starts at zero, so the capacity is the calculated number minus one.

What happens when you try to store another number that exceeds the capacity of the variable, such as 300? Then, the value of the variable will be 44. So, input the following:

uint8 public myNumber = 300;

It will become the following:

uint8 public myNumber = 44;

Note that you can't assign a value that is bigger than the variable's capacity, because you'll get a compilation error in some cases when trying to deploy your contract. The overflow problem can happen when you have a function that receives a uint8, but the user inputs a value bigger than 255.

This is the same thing with uint16, which has a maximum value of 65536-1. Likewise, uint24 has a maximum value of 16777216-1. The uint32 variable has a maximum value of 4294967296-1. The uint64 variable has a maximum value of 1844674407370955e19-1. The uint128 variable has a maximum value of 3402823669209385e38-1. The uint256 variable has a maximum value of 1157920892373163e77-1.

As you can see, the maximum number grows pretty quickly. This is great to avoid overflows when you are dealing with big numbers.

On the other hand, you have the problem of underflows. These happen when you try to store a negative number into a uint. For instance, try to do this:

uint8 public myNumber = -5;

You'll get the following:

uint8 public myNumber = 251;

This happens for the same reason as overflows; you are going from zero to the biggest number possible that that variable can hold.

Those problems can result in heavy vulnerabilities. That's why it's important that you check that the values that the user inputs in your functions are within the range of acceptable numbers. You'll later see how to verify inputs from functions with a global function called require().

Addresses

In Solidity 0.4.0, there was only one type of address. Now, we have two types to define whether an Ethereum address should be payable or not.

An address contains the account number of each user in Ethereum. It's a 42-character piece of hexadecimal text, such as this one:

0xeF5781A2c04113e29bE5724ae6E30bC287610007

To create an address variable in your contract, you have to define it as follows:

pragma solidity 0.5.0;
contract Example {
    address public myAddress = 0xeF5781A2c04113e29bE5724ae6E30bC287610007;
}

Addresses don't have quotes because they are not strings of text. In this version of Solidity, you must define the type of address, which could be one of the following:

  • Addresspayable: A payable address is a new type of variable introduced in Solidity 0.5 that allows the address to receive and store Ether inside. Previously, all addresses were payable, now only those explicitly marked as payable will be able to receive or send Ether and use functions that deal with Ether, such as .transfer() or .send().
  • Address: A normal address that can't receive or send Ether to prevent users from doing so.

You define the payable addresses as follows:

address payable public myAddress;

It's useful to have payable addresses when you want to send Ether to that address. For instance, let's say that user A wants to receive 10 ether from the balance stored in the smart contract. They would do something like the following:

pragma solidity 0.5.0;
contract TransferExample {
    address payable public userAAddress;
    function transferFunds() public {
        userAAddress.transfer(10 ether);
    }
}

So, user A would receive 10 ether from the funds stored in this smart contract.

Another important aspect of the addresses is that you sometimes need to access the address of the current smart contract, because, as you know, smart contracts can hold Ether inside.

To get the address of your smart contract, use the following code:

address public myContractAddress = address(this);

Here, this is the special keyword used to reference the active smart contract being used at that moment. But because it is an instance of a smart contract, you need to convert that instance to an address with the type conversion function, which essentially gets the address of this smart contract.

You can also access the balance of this smart contract with the .balance function as follows:

uint256 public myContractBalance = address(this).balance;

That will return the number of wei in the smart contract, useful for making transfers with the transfer() function:

myUserAddress.transfer(address(this).balance);

That will send myUserAddress all the Ether stored inside this contract.

You can convert payable addresses to normal addresses, but not the other way around, based on the fact that payable addresses are an augmented version with additional functions that can't be passed easily.

Strings and bytes

Strings and bytes hold pieces of text in single or double quotes, as follows:

string public myText = “This is a long text”;
bytes public myTextTwo = “This is another text”;

They allow you to store about 1,000 words and they are essentially the same. You can have smaller variations of bytes, such as bytes1, bytes2, and bytes3, up to bytes32.

Now, bytes32 is an interesting type of variable, because it allows you to store about 32 characters of text in a very compact and efficient way. They are used in many cases where short text is required:

bytes32 public shortText = “Short text.”;

They are used in many other advanced uses cases, such as checking if a string or byte's text is empty. For instance, if you have a function that receives text, you may want to make sure that the text is not empty. Here's how you'd do it:

function example(string memory myText) public {
require(bytes(myText)[0] != 0);
}

Don't worry about the technicalities of the function. If you don't know or remember them yet, to check if a string is empty, you must do the following:

require(bytes(yourString)[0] != 0);

This tells the contract to make sure that the first letter of the string is not empty. That's the right way to check for empty strings. We do the same thing with bytes, but without the conversion to bytes.

Use them whenever you need to add special characters to your strings in Ethereum.

Structs

If you are familiar with JavaScript, you can think of structs as objects with properties and values. A struct looks similar to the following:

struct Example {
    propertyOne;
};
Enums

Enums are fixed size lists with unique names that you define. You can use them as custom modifiers for specific objects, or to hold a specific state in your smart contract. This is ideal for controlling the state of ICOs.

You declare them as follows:

enum Trees { RedTree, BlueTree, GreenTree, YellowTree }

Then, you create the enum variable:

Trees public myFavoriteTree = Trees.RedTree;

Note that you don't have to add a semicolon at the end of the enum declaration, but you do have to add it for the variable with the enum type that you just created.

Booleans

A Boolean variable can either be true or false:

bool public isValid = true;
Arrays

Arrays allow you to store large amounts of the same type of variable in one place. They are used as lists that contain a specific type of information for your smart contracts so that you can store your data in an orderly manner. They can be accessed with a simple for loop by getting the length of them.

You can create arrays of uints, strings, structs, addresses, and pretty much any other type:

uint256[] public myNumbers;
string[] public myTexts;

You can also delete elements from an array with the following keyword:

delete myTexts[2];

You can also use .push() and .pop() to add or remove elements from the array in dynamically-sized arrays.

Mappings

Mappings are a special type of variable in the sense that they can hold an endless amount of data. It's like a combination of an array and a struct. You can add elements to it for a set of types:

mapping(string => bool) public validStrings;

Mappings store information as an unlimited array. They work similar to objects in JavaScript, where each key has a value associated and they can be accessed randomly. They don't have a fixed length, nor can you get the length of them, as with arrays, for looping their values. What you must do instead is save the latest updated key of your mapping and go from there.

You can set values for mappings as follows:

validStrings['example'] = true;

In our example, all values of validStrings will be false until you set them to true.

Data location

In Solidity, you have the option to define where your variables will be stored. You can decide to store them in the following places:

  • Storage: This is a permanent place that gets written on the blockchain, therefore it's expensive to use
  • Memory: This is a non-permanent place where variables are held for only as long as the smart contract is running
  • Calldata: This is where the msg object data information is stored, a place dedicated to global variables

An example of this is in the following code:

uint256 memory myNumber;
string storage myText;
Events

Events are a special type of function. Their purpose is to log data on the blockchain and actions that you want to retrieve at a later date. They can be subscribed to to receive an update whenever a new event is generated, almost in real time.

Essentially, you want them to keep a registry of the things that are happening inside your smart contract to later analyze them in order to fix bugs and to understand what happened if you need to read the past in an easy way.

Here's how you declare events inside your smart contract in Solidity:

pragma solidity 0.5.0
contract EventsExample {
    event LogUserAddress(address userAddress);
    function registerUser() public {
        emit LogUserAddress(msg.sender);
    }
}

In this example, you can see how an event is declared and emitted. When you declare your event, you have to decide the parameters that it will be able to receive; all of them are always optional, so you can omit them.

When you emit the event inside a function, you must make sure that they are of the right type. In the declaration, you can add a name for each parameter, or you can leave it with just the type, as follows:

event LogUserAddress(address);

It's good practice to name the parameters inside the event, to help others understand the purpose of each of those parameters.

You can also add an optional keyword called indexed. It's a modifier to the parameter of the event that allows you to search past events for that specific event. Think of indexed parameters as searchable entries in a database:

event LogUserAddress(address indexed userAddress);

Note that you must name the parameters that are indexed. Later you'll see how to retrieve those events and search for specific ones with web3.js.

Modifiers

Modifiers are a special type of function that are used to verify data or execute something before the current function execution as a middleware. They are mostly used to verify that the user executing the function has the required permissions and to verify the parameters:

address public owner;
modifier onlyOwner() {
    require(msg.sender == owner, ‘You must be the owner');
    _;
}

function doSomething() public onlyOwner {}

As you can see, the onlyOwnermodifier is used to check if the doSomethingfunction is being executed by the owner of the contract or by another user. If the caller is the owner, the functions gets executed, and if it's an external address, the contract will revert, and an exception will be thrown.

Note that the require() function is a global assert function to verify that the condition inside it it's true or not. If not, it will throw, and it will stop executing the smart contract.

The underscore statement inside the _modifier is used to indicate where the code of the function will be executed. Sometimes, you want to execute the function before the modifier's checks. The underscore statement is mandatory in modifiers. Also note that the modifier can have parameters optionally. If none are required, you can remove the brackets as follows:

modifier onlyOwner { ... }

Modifiers are very powerful tools that you'll often use whenever you see repetitive code doing the same verifications for several functions.

In the next section, you'll see the types of special modifiers that functions can take for visibility and payments.

Functions

Functions in Solidity are pretty similar in syntax to those in JavaScript, but they have some key differences that you must understand, such as the fact that you must specify return types, the visibility of the function, and the modifiers that apply to each particular function, if any. The syntax is the following:

function example() public returns(uint256) { }

Functions have visibility just as variables do, where public functions can be executed by external users, contracts, and in the contract itself. External functions can only be by external entities, not by the contract itself. Internal functions can only be executed by the containing contract. Private functions can be executed only inside the current contract, or by inherited contracts.

Now, a function can have special modifiers that determine the type of function it is. This includes modifiers such as the following:

  • View: A view function is one that doesn't modify state variables but can read them. Remember that state variables are declared at the beginning of the contract, and they are used to store information directly on the blockchain. So, if your function doesn't modify any state variable, you have to mark it as view.
  • Pure: A pure function is even more restrictive. It applies to those functions that don't even read state variables. Pure functions are normally functions that make some type of calculation inside them without relying on external data. This usually includes mathematical functions or formatting functions.
  • Payable: A payable function is able to receive Ether when it is executed. It will store that Ether inside the contract, so it's very important that you create systems to extract the Ether that gets sent to the smart contract, otherwise the money will be stuck inside there forever. If your function is not marked as payable, when you send Ether alongside the function execution, you'll receive an error and the transaction will revert.

Here's how it looks:

string public myStateString = 'Hi';
function exampleOfView() public view returns(string memory) {
    return myStateString;
}

In that function, we are simply reading and returning the myStateString state variable, so we can mark it as view. Note that we must use the memorykeyword for string types, since they are a type of array internally like an array of each individual character.

Another example is as follows:

function sumTwoNumbers(uint256 numberA, uint256 numberB) public pure returns(uint256) {
    uint256 result = numberA + numberB;
    return result;
}

This pure function is simply adding two numbers and returning the result to the caller. It doesn't modify the state and it doesn't read the state variables.

Here's a payable function:

function receiveDonation() public payable {}

The receiveDonation function is empty because we only need to receive the Ether. We don't have to do anything with it.

The fallback function

This is a special type of function that doesn't have a name. It is executed whenever someone uses the .send() or .transfer() function to this contract address, similar to a default function. It is often used in ICOs to receive Ether and return the specified number of tokens for the Ether received. This allows anybody to buy tokens without having to understand and deploy the contract instance, with just the address of the contract.

Here's how it looks:

function () external payable {}

Fallback functions must be marked external to help people understand that it shouldn't be executed inside this contract by mistake. If you don't add the payable modifier, it will reject all the transactions sending it Ether.

I recommend that you should write and try different functions using the remix.ethereum.org IDE, which will show you errors and notifications about things that must be verified. That way, you'll be able to write your own contract securely.

Vyper

Vyper is a new programming language for smart contracts that has a syntax similar to Python. It was created by Vitalik himself and it's one of the most interesting choices for new decentralized applications, given that it provides a different approach to traditional Solidity smart contracts.

Its goal is to be a simple programming language that has increased security based on simplicity, where the code should be easily understandable, even by non-developers. That's why the syntax is so minimalistic. They also wanted it to be a programming language where it's increasingly hard to write buggy or vulnerable code, so that developers don't spend countless hours analyzing the security of every single application while avoiding unexpected vulnerabilities by default.

That's the main reason Vyper added several interesting features, such as the following:

  • Knowing how much gas each function call will cost every time: Having a precise indication of gas costs is important, because you want users to be able to calculate precisely how much Ether they will invest per transaction. It saves people's money while making the program predictable.
  • Automatic vulnerability checking: Overflows, underflows, reentrancy attacks, and many other well-known vulnerabilities are automatically fixed in Vyper, without having to manually pay attention to every single function of your smart contracts.

On the other hand, they removed important characteristics found in other smart contract programming languages, such as Solidity:

  • No more modifiers: Modifiers are not allowed in Vyper, because they make code confusing to read, given that you have to jump back and forth between the modifier definition and its use. Also, they can be used maliciously by executing code unexpectedly; for instance, creating a modifier called onlyOwner but then executing a transfer() function totally unrelated to what's expected from its name.
  • No more assembly: Assembly code is hard to understand, even to experienced developers, because you're dealing with very low-level functions that can be misleading. This means that you won't be able to create smart contracts that use signatures, state channels, and similar applications relying on assembly.
  • No more recursive functions: To avoid reentrancy attacks while guaranteeing a precise calculation of gas costs, they removed recursive functionality where functions can call themselves an uncertain amount of times.

In general, Vyper is a powerful language that's great for smaller projects and won't require advanced functionality, such as assembly. You can quickly create an easy-to-maintain smart contract that your users will be able to understand within a few minutes for its light syntax and minimalistic code.

Vyper by example

To get up to speed with this new exciting language, we'll go through a simple smart contract so that you can see the full complexity of Vyper. We'll see all the types of variables and functions in one single smart contract.

Go ahead and create a new example.vy file. As you can see, Vyper smart contracts have the .vy termination. Inside it, type down the following code; we'll later explain what every variable means and how they are used. This is just a quick exercise to get your programming hands familiar with how Vyper is written. This code will be your go-to guide to familiarize yourself with Vyper's syntax:

# Events
LogTransfer: event({from: indexed(address), to: indexed(address), amount: uint256})

# Custom units
units: {
    kg: "kilogram"
}

# Numbers
myPositiveInteger: uint256
myDecimalNumber: decimal
myInteger: int256

# Addresses
owner: address

# Strings
myName: bytes32
myLongArticle: bytes[1000]

# Booleans
isThisTrue: bool

# Mappings
todoList: map(uint256, bytes32)

# Structs
struct Client:
    name: bytes32
    age: uint256

myClients: Client[100]

# Timestamps
myBirthday: timestamp
expirationTime: timedelta

# Wei value
etherToSpend: wei_value

# Custom unit types
myKilo: uint256(kg)

# Public functions
@public
def subNumbers(first: int128, second: int128) -> int128:
    return first - second

# Payable functions
@public
@payable
def transferFunds(_from: address, to: address, amount: uint256):
    log.LogTransfer(_from, to, amount)

# Functions that update state
@public
def updateBoolean(result: bool):
    self.isThisTrue = result

# Constructor
@public
def __init__():
    self.owner = msg.sender

# Fallback function
@public
@payable
def __default__():
    self.myBirthday = now

These are some clarifications to help you understand what is going on:

  • Events must be declared at the top of the Vyper file, and they have to come inside curly brackets, like these: ({}).
  • Unsigned integers can only be positive, and their maximum value is 2**256. You can't have uint8 or equivalent; all uints must be uint256.
  • Signed integers, normal integers, can be positive or negative with a maximum value of 2**128 from both sides. They can only be int128, so you can't have smaller sizes.
  • Decimals have a precision of 10 decimal places, meaning that you can have up to 10 characters after the dot, for instance, 1.2394837662.
  • Strings can either be bytes32 or byte arrays with a custom size, such as bytes[2000]. Note that you don't have the string type of variable, so your strings will be stored as hexadecimal texts after you upload them. Also, you can't have variable-size bytes, such as bytes[], because they create uncertainty when calculating gas costs.
  • Mappings must be declared with the map() function and they can be accessed with brackets, for instance, todoList[3] = "Start something".
  • Timestamp is a fixed date for events such as your birthday, or a specific time in the future. This is mostly used as date containers. timedelta is more like a counter without a precise date in the calendar. For instance, timedelta could store 2 months, while timestamp could store January 1 2019, all in numerical format.
  • The wei value is the type used for storing Ether in wei.
  • Custom unit types are personalized types that you define at the top of the file and you can then use for your variables. They must be casted as uints, ints, or decimals.
  • Functions can be public or private. Public functions must have the @public decorator on top of them. The return value of functions is specified with the arrow sign, ->.
  • Payable functions must use the @payable decorator and they can access the Ether sent (if any) with msg.value.
  • To update state variables inside functions, you must use the self. keyword in front of them to update them as state variables. In Vyper, you don't need to add the underscore _ in front of parameter names, because you can easily reference the variable with the same name in state, while in Solidity you can't, so you had to use underscores to differentiate them.
  • The constructor is called __init__(), while the fallback function is called __default__().

That's it! The fastest way you can master Vyper in a few pages. Make sure that you keep this guide in a special place for whenever you write Vyper contracts to save you hours of headaches and uncomfortable moments.

 

Summary


In this chapter, we started by getting a high-level overview of Ethereum's history to understand where it came from and where it's headed. Then, we moved to specific topics, such as the EEA, since it's great to know how the Ethereum technology is being applied in different real-world scenarios. After that, we covered many different topics regarding the specifics of the Ethereum blockchain to understand it more on a technical level that makes sense as a developer, since we'll be dealing with all aspects related to its blockchain. Next, we moved to more technical topics regarding smart contracts, since they are at the core of what an Ethereum developer does, so that you get a clear vision of how they are implemented in the grand scheme of things. Finally, we moved to essential smart contract programming with Solidity and Vyper to kick-start your understanding of how the most popular languages are used in the real world, setting up a solid foundation for future projects to start your journey to become a master Ethereum developer.

If you weren't familiar with Vyper, you should now be able to program simple contracts using the online compiler, which can be found at: https://vyper.online/. Make sure that you practice the functions described in this chapter by yourself and continue reading once you have an intuitive understanding on the concepts explained.

In the next chapter, we're going to explore the Ethereum architecture in depth to understand how each component works at a fundamental level and the main driving forces behind blockchain technology.

About the Author

  • Merunas Grincalaitis

    Merunas Grincalaitis, born in Lithuania and based in Spain since he was 4, has worked with blockchain companies all around the world, helping them create ICOs, dApps, MVPs, technical whitepapers, web apps, and audits so that they improve the Ethereum ecosystem with decentralized solutions that return people's trust in themselves.

    He created one of the first books about Ethereum development, named Ethereum Developer - Learn Solidity From Scratch, which sold a lot of copies worldwide, as a quick guide to provide a bridge for programmers interested in the world of Ethereum and smart contract programming.

    Currently, he's working on providing free learning resources through his Medium blog to all developers looking for expert guidance.

    Browse publications by this author

Recommended For You

Hyperledger Cookbook

Explore the entire Hyperledger blockchain family, including frameworks such as Fabric, Sawtooth, Indy, Burrow, and Iroha; and tools such as Composer, Explorer, and Caliper.

By Xun (Brian) Wu and 2 more
Learn Ethereum

Explore the blockchain-based decentralized platform and understand how Ethereum works with Dapps examples

By Xun (Brian) Wu and 2 more
Python Machine Learning - Third Edition

Applied machine learning with a solid foundation in theory. Revised and expanded for TensorFlow 2, GANs, and reinforcement learning.

By Sebastian Raschka and 1 more
Mastering Blockchain Programming with Solidity

Discover the advanced features of Solidity that will help you write high-quality code and develop secure smart contracts with the latest ERC standards

By Jitendra Chittoda