Translator: Ocean biscuit

The original link


Moving from web2 to web3 is the second installment of a trusted tutorial for developers

🙌

Welcome back to this series of blogs designed to help Web developers build distributed applications and smart contracts based on Ethereum in the easiest way possible.

The first blog post in this series is -Transition to Web3-01 Distributed development introductionThe second part (this one) discusses how to write Ethereum smart contracts, along with a sample project.


What is a smart contract?

As the first blog post mentioned:

Smart contracts in the Ethereum context are scripts that execute on a global network of public nodes — EVM(Ethereum VIRTUAL Machine) — and can read/write transactions from the blockchain.

** Contract ** is a “voluntary agreement between two or more parties” ([Wikipedia][10]).

** Smart contract ** is “a computer protocol that facilitates, verifies, or enforces negotiation of a contract “([Wikipedia][11]).

As a cryptographer in the 1990s, [Nick Szabo first proposed the concept of smart contracts][12], and the concept has been featured in many cryptocurrency-based projects, the most notable of which is Ethereum.

The first form of smart contracts was vending machines. The potential losses from vending machines are limited (the ultimate loss should be less than the cost of breaking the mechanism), where the machine swallows coins and, through a simple mechanism, makes change and orders based on the displayed price.

It is now possible to give a definition based on the Ethereum background: Smart contracts can be used to programmatically and automatically execute contracts. Smart contracts can work in distributed software because they eliminate centralized mediation.

Set up

Download the sample project directly:

git clone https://github.com/lukehedger/todoeth.git

cd todoeth

git checkout issue#2-smart-contracts
Copy the code

We’ll see ** a cryptographically motivated Todo List** — it’s called Todoeth. In the next two blogs, we will start building a Todo List app that will push people to complete their Todo List by deducting money from users!

Todoeth is circled in the wire frame. ICONS are provided by [Hea Poh Lin][13].

To install the project dependencies, run the following command:

npm install
Copy the code

Let’s take a look at the smart contract development process.

design

Each robust program starts with a clear and complete architectural design, which is especially critical for writing smart contracts. Given that contracts deployed to the Ethereum blockchain are unchangeable, all possible scenarios must be considered.

In a client-server web application, if there is a bug, we can simply patch the production server so that all future visitors to our site can access the patched version. Given the permanence, verifiability, and tamper-proof nature of data in Ethereum, it’s clear that contracts cannot simply be upgraded in this way — otherwise, all records will be lost!

The key to designing a updatable contract system is to ** separate the storage contract from the agent contract **(more on that next).

Our distributed Todo app requires three contracts:

  • A primary contract that stores each user and the user’s Todo
  • A secondary contract that tracks Todo deposits
  • A proxy contract that facilitates web application interactions

write

Solidty: Several languages can be used to write Ethereum smart contracts. Solidty was chosen because it is the most widely used. We will use version 0.4.18, which is the most recent stable release when the contract was written. [Atom][14] and [Sublime][15] both provide syntax highlighting.

Let’s start with the classic “Hello,World”, of course, where the implementation says Hello only to the function caller:)

Pragma solidity ^ 0.4.18;Copy the code
// import './SomeContract.sol';
Copy the code
contract HelloYou { event Hello(address you); function sayHello() public { address _person = msg.sender; Hello(_person); }}Copy the code

The **pragma** at the top of the contract is a [directive][16] that tells the Solidty compiler which version we are using.

This contract does not have any input, if it does, we will define the input under pragma with the relevant file path.

Next comes the ** contract declaration **. To declare a contract, use the contract keyword for the contract name – in this case, ‘Hello You’.

The contract includes a **event and a function**. Events are simply declared with the event keyword and a function signature (the event name and type parameters enclosed in parentheses). In the above example, the event name is’ Hello ‘and the event takes a parameter’ you ‘of type ‘address’ (address is a special type used in Solidty to describe a Ethereum public address).

Type: Unlike JS(dynamic typing), Solidty is a statically typed language in which the type of each variable must be defined. If you’ve been writing JS in TypeScript or Flow (or any of the other statically typed languages you already use), you can get up to speed. Even if you haven’t used it, you can get used to it quickly.

The sayHello function uses a [global namespace variable][17]msg.sender from Solidty. This value and other useful values can be accessed by any contract method. So, we store this value in the _person variable (no var keyword, just a type, variable name, and =) and pass the variable to the Hello event, which fires the event on EVM.

So we say hello to someone through a smart contract. This function can be called, and the event can be listened for in a Web application, which will be covered in the next article! As the earlier Ethereum proverb says: “” Can events on EVM make a sound if no one is listening?” “

model

As mentioned earlier, we had to structure our contract in such a way that ** allows code to be updated without losing ** data. This is done by separating the code that contains permanent state (data is stored in contracts at any time) from the proxy, and the data flowing into these contracts is external, such as web applications. This storage contract can keep the state very light and service an operation that does not need to be updated. We’ll cover storage contracts in more detail later.

Add a new Todo generated data stream

**Todo.sol**

The ToDo contract is our ‘proxy’ for the storage contract, and it is the only contract associated with our Web app. It doesn’t save any data. This way ** all operations are associated with the contract ** and no data loss is caused by any updates.

Here are three ways to do it:

  • addTodo(todold)The todo ID andmsg.senderPassed as the user ID toToDoStorageContract, and putmsg.value(some token value) as a deposit account toToDoBank
  • addToDo(index)TodoStorageThe contract obtains a Todo from the user Todo array
  • getTodoCount()Gets the number of toDos stored by a user

The reason retrieving a Todo from storage is a two-step process is that Solidty restricts the return of dynamically sized values, such as arrays. So we first get the length of the Todo array, and then get the ToDos one by one using the index. But don’t worry, this restriction will be removed in the next release, 0.5.0.

storage

Smart contracts based on Ethereum blockchain can be used to store unchangeable, verifiable data. This is a great tool that can be used in many interesting areas such as digital transactions and protocols.

In the Todo example, we store a permanent reference for each task! We also store some Ether(Ethereum’s native token) for each Todo.

Metadata storage: Storing data on Ethereum is expensive considering permanence and computing power. Of course, there are many innovative ways to remove this limitation. A common pattern we will use is to store metadata in a distributed storage system (such as [Swarm][18] or [IPFS][19]) and store references to the metadata in Ethereum. The implementation will be presented in the next article.

**TodoStorage.sol**

The TodoStorage contract simply contains methods for getting and setting todos. Metadata about the todo will be stored on Swarm and, so, the only data we actually store in the contract will be the Swarm reference to this metadata (an address of where to Find the data in the Swarm network. The TodoStorage contract simply includes methods to get and set Todo. Swarm will store the Todo metadata in Swarm, so the actual data stored in the contract will be a Swarm reference to the corresponding metadata (i.e. the address of the data in Swarm).

These references are stored in an array as Todoids and locked with userId (the Ethereum address of the Todo owner) on the TodoStore object.

Its data structure is as follows:

TodoStore: {

  userId: [

    todoId

  ]

}
Copy the code

**TodoBank.sol**

Another contract used for storage is TodoBank. This is where we store Ether deposits for each Todo – these deposits are encrypted until they are cancelled normally. Of course, this contract value contains the method of obtaining and setting the deposit.

The data structure is as follows:

TodoVault: {

  todoId: deposit

}
Copy the code

This is out of the scope of the example, but you can see how incentives fit into the system. For example, if a backlog is completed by a certain time, the money is returned to the owner’s address, and if the deadline is missed, the money is sent to another address for the user’s unfinished backlog.

Therefore, you must complete Todo or lose your money. This will continue in the next article.

security

Security is of Paramount importance when software involves personal data and money. Given the inherent economic nature of smart contracts and the nascent language in which contracts are written, their security is extremely important — security mechanisms must be in place when designing and writing a contract.

When testing Solidty, it is necessary to be aware of some possible attacks against contracts. The Ethereum Smart Contract Security Best Practices [20] tutorial is a great choice when you need to research security.

check

You can check your contract using [solium][21], a gadget similar to ESLint.

To check the contract in the sample project, run the following command:

npm run lint
Copy the code

The document

Solidty contracts can use comments as documentation in [the format specified by default for Ethereum]22, similar to JSDoc.

/*

 * @notice TodoAdded event

 * @param {bytes32} todoId

 */

event TodoAdded(bytes32 todoId);
Copy the code

compile

The contract needs to be compiled by the Solidty compiler into bytecode that can be read by EVM.

The Solidty compiler can be used directly through a JavaScript tool called [solc-js][25], which is already used by Ethereum Foundation developers.

The compiler gets the contract name object along with the char content of the contract, [returns compiled bytecode][26], and [an interface to the contract code called ABI]27.

I’ve found that this process can be simplified by abstracting repetitive tasks (parsing contract inputs, writing output to hard disk) and integrating them into a library that uses configuration files to control input and output. The tool is called [Sulk][28] 😂!

The Sulk configuration file is concise. Here is the simplest form of the configuration file:

module.exports = {

  contracts: [

    'Todo',

  ],

  inputPath: './path/to/contracts',

}
Copy the code

You also need to write a [schemes.json][29] file in your project that contains the bytecode and ABI, which will come in handy when your contract ‘should be deployed’.

To compile the contract in the project example, run the following command:

npm run compile
Copy the code

application

To expose your contract and its method, you need to deploy the contract to the Ethereum blockchain. Similar to deploying a microservice to a server, Ethereum also has the concept of production, development, and local networks. The production network – of course, there is only one production network – is often considered the ‘master network’; Development networks – each with a different nature and capability – are called ‘test networks’.

The easiest way to start interacting with your contract is to deploy it to a local Ethereum network. [** Ganache -cli**][30](previously shared with TestrPC) is a Node.js based “personal blockchain developed for Ethereum” that simplifies the deployment process.

In the example project you can run the following command, which will run a local binary installation of Ganache-cli with no arguments (it doesn’t get any better than that, does it?)

npm run 
Copy the code

Once Ganache is running, you can deploy the contract to a local Ethereum node using the deployment script included in the project example:

npm run deploy
Copy the code

The [deployment script][31] uses the [web3.js][32] library to interact with Ethereum nodes. Read through the code and comments so you understand the steps required to deploy a contract. Focus on how tools simplify the deployment process.

The wb3.js: web3.js library has been adopted by the Ethereum Foundation as a popular library, along with others like [ethers.js][33] and [ethjs][34] that are worth trying out in the project example.

The deployment script also stores the address of the deployment contract in a JSON file for later use ([addresses.json][35]). Each deployed contract has a Ethereum address (just like an API has an HTTP endpoint), and these addresses are required when instantiated contracts interact through testing and applications.

Gas

You may have seen the word ‘gas’ or references to it in deployment scripts and sample code. Gas is just a transaction fee charged for Ethereum operations; It’s the source of funds for EVM. Ultimately, GAS needs to avoid overuse of virtual machines.

Gas: is a measure similar to an operational step. Each transaction requires a gas quota and payment for each unit of gas. If the resulting operation uses less than or equal to the quota of gas, the transaction passes. If the limit is exceeded, all changes are restored.

[github.com/ethereum/wi…].

test

It is possible to write unit tests for smart contracts in JavaScript. What’s not easy to swallow, however, is that it’s a bit counterintuitive to programmers used to writing unit tests for traditional client-server applications: you have to run a native Ethereum node to compute the contract methods in JavaScript tests.

Tools for simulating or storing network responses (such as [sinon.js][37] for Ethereum) are great and must be a priority – Go and Python already have similar tools. Now, we must break the fundamental constraints of unit testing and trigger network activity.

Example project tests can be run like this:

npm test
Copy the code

The next article will cover interactions between applications using smart contracts in more detail, but now you can read these tests to learn how to calculate contract methods using Web3.js.

debugging

The process of updating contract code, compiling, deploying, and running unit tests is bloated, and debugging is inefficient. You can debug using Remix, which is an IDE for writing, compiling, deploying, and executing methods.

There is a CLI tool also called Remixd that can share your local contract with the Remix IDE. The project example has the command to perform the share operation – then click the 🔗 button in the Remix toolbar to connect:

npm run remix
Copy the code

You can also [load contracts from Gist into Remix][38].


The next article

We’ll show you how to build a distributed Web application that interacts with a Todo List smart contract.


Develop reading

  • 📖 [Official Solidity docs] [39]
  • 🏊 [deep dive into Solidity][40]
  • 🏪 [Solidity CRUD] [41]
  • ☝ ️ [Writing upgradeable contracts] [42]

Project update

The centralised app enthusiasts have run a great side project, most of which is open source. You can dig deeper and practice problems in the REPO — I’m not saying you have to contribute your code:)

At Jakk we are building [meta-networks and protocols][43], and recently in [a private alpha][44] we are populating the network with data from our partners. Take a look at our code [link][45] and chat with us on [Slack Channel][46] about anything you post!

Search for [us] on [Twitter][48] and [Facebook][49] [47]

Thanks to [JAAK][50] and [FR ξ Tibbles][51].

  • [Ethereum][52]
  • [Web3][53]
  • [Development][54]
  • [Dapp][55]
  • [Blockchain][56]

Please give us a “like” to determine which post is more popular.

[3]: twitter.com/jaak_io “”Visit “JAAK” on Twitter”” [4]: blog.jaak.io//facebook.c… Visit “JAAK” on Facebook” [5]: medium.com/m/signin?re… [6] : medium.com/m/signin?re… [7]: blog.jaak.io/@level_out? … [8]: blog.jaak.io/@level_out? … [9] : blog. Jaak. IO/crossing – ov… [10] : en.wikipedia.org/wiki/Contra… [11] : en.wikipedia.org/wiki/Smart_… [12] : www.fon.hum.uva.nl/rob/Courses… [13] : thenounproject.com/charlenehea… “” View Profile” “[14] : atom. IO/packages/la… [15] : packagecontrol. IO/packages/Et… [16] : en.wikipedia.org/wiki/Direct… [17] : solidity. Readthedocs. IO/en/develop /… [18] : swarm-gateways.net/bzz:/theswa… [19] : ipfs. IO / [20] : consensys. Making. IO/smart – contr… [21] : github.com/duaraghav8/… [22] : github.com/ethereum/wi… [23]: twitter.com/notice “”Twitter profile for @notice”” [24]: twitter.com/param “”Twitter profile for @param”” [25]: Github.com/ethereum/so… [26] : solidity. Readthedocs. IO/en/develop /… [27] : solidity. Readthedocs. IO/en/develop /… [28] : github.com/lukehedger/… [29] : github.com/lukehedger/… [30] : github.com/trufflesuit… [31] : github.com/lukehedger/… [32] : github.com/ethereum/we… [33] : github.com/L4ventures/… [34] : github.com/ethjs/ethjs [35] : github.com/lukehedger/… [36] : github.com/ethereum/wi… [37] : sinonjs.org/ [38] : gist.github.com/lukehedger/… [39] : solidity. Readthedocs. IO/en/develop /… [40] : github.com/androlo/sol… [41] : medium.com/@robhitchen… [42] : blog. Colony. IO/writing – upg… [43] : github.com/meta-networ… [44] : cointelegraph.com/news/jaak-a… [45] : github.com/meta-networ… [46]: community.meta-network.io/ [47]: jaak.io [48]: twitter.com/jaak_io [49]: www.facebook.com/JAAK.io/ [50]: medium.com/@jaak_io?so… [51] : medium.com/@Tibbles?so… [52] : blog. Jaak. IO/tagged/ethe… [53] : blog. Jaak. IO/tagged/web3… [54] : blog. Jaak. IO/tagged/deve… [55] : blog. Jaak. IO/tagged/dapp… [56] : blog. Jaak. IO/tagged/bloc… [57]: blog.jaak.io/@level_out? … “”Go to the profile of Luke Hedger”” [58]: blog.jaak.io/@level_out “”Go to the profile of Luke Hedger”” [59]: blog.jaak.io? source=footer_card “”Go to JAAK”” [60]: blog.jaak.io? Source =footer_card [61]: blog.jaak. IO “”Go to jaak “” [62]: medium.com/@Medium/per…