Issue #2 of the definitive developer’s guide for the journey from web2 to web3 Originally posted as part of JAAK’s developing blog series 🙌 Welcome back to the series of blog posts that aims to get web developers building decentralised applications and smart contracts on Ethereum in the simplest way possible . If you missed the first issue — travel back in time and read it . This second issue will be all about writing Ethereum Smart Contracts, accompanied by an example project. What is a Smart Contract? As covered in the first issue of this series: Smart contracts in the context of Ethereum are scripts that are executed on a global network of public nodes — the EVM (Ethereum Virtual Machine) — and can read/write transactions from/to the blockchain. A is “a voluntary arrangement between two or more parties” ( ). contract Wikipedia A , then, is “a computer protocol intended to facilitate, verify, or enforce the negotiation or performance of a contract” ( ). smart contract Wikipedia Cryptographer way back in the 90s and they have since featured heavily in many cryptocurrency-based projects, most notably Ethereum. Nick Szabo first proposed the idea of smart contracts The primitive ancestor of smart contracts, is the humble vending machine. Within a limited amount of potential loss (the amount in the till should be less than the cost of breaching the mechanism), the machine takes in coins, and via a simple mechanism, dispense change and product according to the displayed price. So, to advance our definition beyond the context of Ethereum: . The implication of this is, of course, the removal of centralised intermediaries. Hence the usefulness in decentralised software. a smart contract can be used to programmatically and enforce agreements autonomously Setup Without further ado, go ahead and grab the example project codebase: git clone cd todoethgit checkout issue#2-smart-contracts https://github.com/lukehedger/todoeth.git We’re going to look at — let’s call it 🤑. In the next two issues, we’ll start to build a todo list app that will pressure the user to complete their todos with the prospect of losing their money! a crypto-economically incentivised todo list Todoeth Wireframe for Todoeth. Icon by . Hea Poh Lin Run the following command to install the project’s dependencies and then we’ll dive in to smart contract development: npm install Let’s look at the stages of smart contract development Design Every robust program starts off with a clear and complete architectural design and this is especially crucial when writing Smart Contracts. Given the immutable nature of contracts deployed to the Ethereum blockchain, it is imperative that all eventualities are considered. In client-server web applications, when a bug is found we can simply (!) deploy a patch to the production server and all future visitors to our site will receive the fixed version. The tradeoff for permanent, verifiable, tamper-proof data records on Ethereum is contracts cannot simply be upgraded in this manner — otherwise, all of those records would be lost! The key to designing an upgradeable contract system is to (we’ll look at this in more detail later on). separate storage contracts from proxy contracts Our decentralised todo application will need three contracts: A primary storage contract to store each user and their todos A secondary storage contract to track deposits made against todos A proxy contract to facilitate interactions from a web application Write A note on : whilst there are a few languages for writing Ethereum Smart Contracts, we will write ours with Solidity as it is currently the most widely used. We’ll use version 0.4.18, which is the latest stable version at the time of writing. There are syntax highlighters for and . Solidity Atom Sublime Let’s start with the ubiquitous ‘Hello, World’ example but, instead of greeting the whole world, we’ll just say hello to the person who called the function: pragma solidity ^0.4.18; // import './SomeContract.sol'; contract HelloYou {event Hello(address you); function sayHello() public {address _person = msg.sender; Hello(\_person); }} The at the top of the contract is simply a that tells the Solidity compiler which version to use. pragma directive This contract doesn’t have any imports but if it did we would define these beneath the pragma using relative file paths. Next comes a . To declare a contract, you use the keyword with the name of the contract — in this example, ‘HelloYou’. contract declaration contract This contract consists of an and a . Events are simply declared with the keyword and a function signature: event name and parenthesised, typed arguments. In the above example, the event is called ‘Hello’ and accepts one argument ‘you’ with the type ‘address’ ( is just a special type in Solidity describing an Ethereum public address). event function event address A note on : Unlike JavaScript (which is dynamically typed), Solidity is a statically typed language so the type of every variable must be specified. If you’ve been using Typescript or Flow to write your JavaScript (or have used other statically typed languages) then you’ll feel at home. Otherwise, you’ll soon get used to it. types The function uses one of Solidity’s . This and other useful values are available to all contract methods. The variable (perhaps, predictably) contains the Ethereum address of the message sender. So, we store this value in the variable (no need for a keyword, just a type, name and ) and pass it to the event, which will trigger the event on the EVM. sayHello global namespace variables msg.sender msg.sender _person var = Hello That’s it! We just said hello to someone via a smart contract. This function can be called and the event listened for in a web application but we’ll save that for the next issue! As the ancient Ethereum proverb says: . “does an event on the EVM make a sound if nobody is listening to it?” Patterns As mentioned earlier, we must build our contracts in a way that enables . This is achieved by separating code that contains permanent state (anytime data is stored in a contract) from proxies that funnel data into these contracts for external sources, such as web applications. The storage contracts can remain extremely light and serve a single purpose that is unlikely to require an upgrade. We’ll look at storage contracts in detail in a few paragraphs time. code upgrades without loss of data Data flow for adding a new todo **Todo.sol** The contract is our ‘proxy’ to the storage contracts and the only contract that will be exposed to our web app. It will not store any data. This way, and any upgrades can be made without loss of data. Todo all operations are routed through this contract It has three methods: Passes the todo ID to the contract along with the as a user ID and passes the (some tokens) to the contract as a deposit amount addTodo(todoId) TodoStorage msg.sender msg.value TodoBank Gets a todo from the contract by the index in the user’s array of todos getTodo(index) TodoStorage Gets the number of todos a user has stored getTodoCount() The reason retrieving a todo from the store is split into two methods is due to a current limitation with Solidity that restricts the return of dynamically sized values, like arrays. So, we first have to get the length of the todos array and then get each todo individually by index 🙈. Fear not, this restriction will be removed in the next minor release . 0.5.0 Storage Smart contracts can be used to store immutable, verifiable data on the Ethereum blockchain. This is a super powerful tool and can be used to enable a range of interesting forms of digital transactions and agreements. In our todo example, we will store a reference to each task for eternity! We are also going to store some Ether (Ethereum’s native token) against each todo. A note on : Storing data on Ethereum is deliberately expensive due to the permanency and computational power involved. There are a number of innovative solutions to this limitation emerging. One common pattern, which we will employ here, is to store metadata in a distributed storage system (like or ) and store references to that metadata on Ethereum. We’ll cover how to do this in the next issue. metadata storage Swarm IPFS **TodoStorage.sol** The 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). TodoStorage These references, which we will use as a , are stored in an array and keyed by (the Ethereum address of the todo owner) in the object. todoId userId TodoStore This gives us a data structure like this: TodoStore: {userId: [todoId]} **TodoBank.sol** The other contract used for storage is . This is where we’ll store the Ether deposits made against each todo — the funds will be secured here until they are legitimately withdrawn. Again, this contract just contains methods for getting and setting deposits. TodoBank The data structure looks like this: TodoVault: {todoId: deposit} It is beyond the scope of this example but you can see how incentive mechanisms could be built into this system. For example, if a todo is completed by a certain time the deposit is returned to the owner’s address but if the deadline is missed the funds are sent to another address that may have bet the owner would not complete it! So, you must either complete a todo or face losing your deposit 💸. We will save this for a future issue! Security Software security is paramount when personal data and funds are involved. Given the inherent economic nature of smart contracts, and the immaturity of the languages used to write them, their security is particularly crucial — safety mechanisms must be built into the design and code of a contract. Whilst experimenting with Solidity, it is enough to keep this concern in mind and be aware of some of the possible attacks contracts are open to. The guide is an excellent resource when you are ready to delve into security. Ethereum Smart Contract Security Best Practices Linting You can lint your contracts with , a tidy tool that follows similar conventions to ESLint. solium To lint the contracts in the example project, run the following command: npm run lint Documentation Solidity contracts can be documented with comments in the (or, NatSpec), which is similar to JSDoc. Ethereum Natural Specification Format /** TodoAdded event* {bytes32} todoId*/event TodoAdded(bytes32 todoId); @notice @param Compile Contracts need to be that can be read by the EVM. compiled with the Solidity compiler into bytecode It is possible to use the Solidity compiler directly via a JavaScript tool called , which is maintained by the Ethereum Foundation developers. [solc-js](https://github.com/ethereum/solc-js) The compiler takes an object of contract names and the stringified content of that contract and and (or, Application Binary Interface). returns the compiled bytecode an interface for interacting with the contract code, called the ABI I’ve found that this workflow can be simplified by abstracting the repetitive tasks (parsing the contract input and writing the output to disk) into a library and controlling the input/output with a configuration file. This tool is called 😂! Sulk Sulk takes a simple configuration file that, in its simplest form, looks like this: module.exports = {contracts: ['Todo',],inputPath: './path/to/contracts',} And writes a file to your project, which includes the bytecode and ABI and can be used when ‘deploying’ your contracts. [contracts.json](https://github.com/lukehedger/todoeth/blob/issue%232-smart-contracts/contracts/contracts.json) To compile the contracts in the example project, run the following command: npm run compile Deploy To expose your contract and its methods, you need to . This is akin to deploying a micro-service to a server and, as with server infrastructure, Ethereum has the concept of production, development and local networks. The production network — of which there is, obviously, only one — is commonly referred to as the ‘mainnet’ and development networks — of which there are a few, each with varying properties and capabilities — are called ‘testnets’. deploy it to the Ethereum blockchain The simplest way to start interacting with your contract is to deploy it to a local Ethereum network. (previously known as ) is a Node.js based “personal blockchain for Ethereum development” that simplifies this process. [**ganache-cli**](https://github.com/trufflesuite/ganache-cli) testrpc From the example project you can run the following command, which simply runs a locally installed binary without any arguments (and ): ganache-cli makes you feel like a deity npm run Once is running, you can use the deployment script included in the example project to deploy the contract to the local Ethereum node: ganache npm run deploy The uses the library to interact with the Ethereum node. Read through the code and comments to see the steps required to deploy a contract. Watch this space for tooling to simplify this process 👀. deployment script Web3.js A note on : The Web3.js library is maintained by the Ethereum Foundation and has become the popular library but there are others such as and , which are worth exploring as you experiment with this stack. Web3.js ethers.js ethjs The deployment script will also store the in a JSON file for later use ( ). Each deployed contract has an Ethereum address (just like an API has an HTTP endpoint) and these are needed when instantiating contracts to interact with them via tests and applications. deployed contract addresses [addresses.json](https://github.com/lukehedger/todoeth/blob/issue%232-smart-contracts/contracts/addresses.json) Gas You may have heard the term ‘gas’ or notice references to it in the deployment script and example code. ; the fuel for the EVM. Ultimately, gas is needed to prevent excessive use of the virtual machine. Gas is simply a transaction fee charged for Ethereum operations Gas: a measurement roughly equivalent to computational steps. Every transaction is required to include a gas limit and a fee that it is willing to pay per gas. If the total number of gas used by the computation spawned by the transaction is less than or equal to the gas limit, then the transaction processes. If the total gas exceeds the gas limit, then all changes are reverted. https://github.com/ethereum/wiki/blob/master/Glossary.md Test It is possible to write Smart Contract unit tests in JavaScript. However, this comes with an overhead that may seem counterintuitive to developers used to writing unit tests for traditional client-server applications: It is necessary to run a local Ethereum node to execute contract methods on from JavaScript tests. Tooling around simulating or stubbing network responses (like for Ethereum) would be great and will surely be developed as demand increases — Go and Python already have such tools. For now, though, we have to break a cardinal rule of unit testing and trigger network activity. Sinon.JS The example project tests can be run with: npm test but for now you can read through the tests to get an idea of how contract methods can be executed using Web3.js. We will explore how to interact with Smart Contracts from web applications in detail in the next issue Debug The process of updating a contract’s code, compiling, deploying and running the unit tests is far too cumbersome to facilitate effective debugging. So, for debugging you can use , a web IDE for writing, compiling, deploying and executing methods. Remix There is also a CLI tool called that can be used to share your local contracts with the Remix IDE. The example project includes a command to enable this — then click the 🔗 button in the Remix toolbar to connect: remixd npm run remix You can also . load the contracts into Remix from this Gist Next time… We’ll cover how to build a decentralised web application that interacts with the todo smart contracts. Some further reading 📖 Official Solidity docs 🏊 Deeper dive into Solidity 🏪 Solidity CRUD ☝️ Writing upgradeable contracts Project Update An awesome by-product of projects run by people passionate about decentralised applications is the vast majority of the code is open source. This makes for a great opportunity to dig around in repos for inspiration and best practice — not to mention contributions! Here at JAAK we are building the and are currently , populating the network with data from our industry partners. Take a and jump into our to chat about anything you find! META Network and protocol piloting both in a private alpha look at our code Slack channel Find on and . us Twitter Facebook Originally published at blog.jaak.io on November 27, 2017.