When one decides to start developing smart contracts, one of the things at the top of the list is to setup a proper development environment, where code can be written, tested and deployed. As in any other computer language, there are several moving parts that have to be attuned and installed correctly, but the Blockchain imposes its own specificities. In this post, I walk you through all the steps needed to have a productive work environment. There is necessarily overlap with other posts out there. I found this tutorial to be useful and extensive
It helps to make a checklist of everything we need:
- a text editor with syntax highlighting for a language that can be compiled to EVM bytecode. I use Solidity
- a compiler for our contracts that can produce executable code
- an execution environment that allows our contracts to be deployed and its methods to be called
- a debugger
- a testing framework, that allows us to write tests for our contracts
- a way to deploy our code to the blockchain
- optionally, a block explorer to check the transactions made by your tests
The next sections detail each of these steps.
Remix
Remix is an online IDE that does most of the above. It provides a basic text editor with minimal highlighting, but offers several other valuable things, including static code analysis, a debugging suite that allows setting breakpoints and the usual options to skip instructions, step out, into, etc. It is also possible to call any contract function with any input value, specify a gas limit and value, use one of 5 different accounts to submit the transaction (each with 100 Ether to begin with) and examine the transaction logs.
It’s a pretty solid beginning environment, and one can learn a lot about the way Ethereum coding works from it. For serious development, I prefer to use a more flexible environment, as Remix does not allow me to easily save and organise my contracts and libraries in different files and or directories.
Code Editor
The ideal environment for developing software is an IDE, where we can type our code, run code analysis, compile, debug, run and even profile executions. Ethereum and Solidity are still very young, and there are few options available, and these probably fall short of everything you’d expect from an IDE.
I use Atom for my daily development. It is a pleasant editor, with several packages for customization, including dedicated ones for Solidity, that give auto-completion, syntax highlighting and some measure of code analysis. There is no integrated debugging, nor useful commands like “Go to definition” or “Go to previous position” (at least in Solidity), but on the other hand it is integrated with GitHub and makes it very easy to resolve merging conflicts.
Another alternative is Visual Studio Code, which also has packages to support Solidity and pretty much the same features mentioned above. It’s a matter of personal taste.
Compiler
The Solidity language has its own compiler, known as solc
. Installation instructions for the currently latest version of Solidity can be found here. For my home setup, I just installed Visual Studio Code and then downloaded the binaries for the latest windows release. I extracted the files and added them to the path.
Then I created a very small contract in file hello.sol
, with some deliberate typos, and invoked solc hello.sol
, until there were no errors or warnings.
My example contract is this:
pragma solidity ^0.4.24;
contract Hello {
event LogMessage(string message);
function sayHi() public {
emit LogMessage("Hello");
}
}
Solc is a very complete tool. Besides compiling the Solidity code, it can produce Natspec documentation, the ABI, binary code, assembly and bytecode, for example. All of this is written to the console and can easily be redirected to a text file.
Execution Environment
Every time we write a program, we intend to run it somehow. We compile it to transform our high level code into some arrangement of bytes that can be understood by the target environment that is responsible for executing our code. In the old days, we’d compile into machine code that would be directly run by the microprocessor; then If we write Java, that will be the Java Virtual Machine; if we write a Windows executable, that will be the Operating System; if we write javascript, that will likely be a Javascript engine inside a browser.
The corresponding environment in Ethereum is the Ethereum Virtual Machine, but because of the nature of blockchain everything is more complicated. The Ethereum blockchain is hosted in many individual nodes around the world. Anyone can run a node and host the full blockchain there, although this becomes more difficult as the size of the chain increases and nodes have to constantly keep up to date. Some of these nodes are special, they are miners which add new blocks to the blockchain and thereby create new Ether.
In a blockchain, blocks keep track of transactions sent between two accounts, which can be seen as the primary citizens of the blockchain. But in Ethereum, these accounts can be of two types:
- Externally Owned Accounts: an account that is controlled by a private key. It has no code and is, in this sense, passive. It can send and receive Ether to and from other accounts.
- Contract Accounts: an account that is controlled by a smart contract, which is a unit of code that can be executed in certain circumstances.
A smart contract has two different execution phases: when the contract is created, its constructor is executed, and will never be executed again. After the contract is created, other accounts can freely call non-constructor methods of the smart contract, and the corresponding code will be executed.
Every full node has inside it an instance of the EVM, that executes the smart contracts. Its native language is a type of bytecode, (which can be produced by running the solc
compiler). But any execution only ever happens as part of a transaction inside a mined block.To send a transaction to the blockchain, we need to use an Ethereum client, that ultimately links our computer to the full nodes out there.
Because transactions ultimately cost money, as developers we want to avoid to write to the real blockchain as we write, debug and test our code. We could use a test blockchain for that, but interacting with a blockchain can take several seconds or even minutes, which is too slow for normal development. For this reason, we have to use a particular kind of Ethereum client, that simulates a blockchain instead of connecting to a real one (either the main net or a test network). Such a simulator still does all the block validations as the real blockchain would do, but does not take as long nor cost any tokens.
The most used simulator nowadays is Ganache (previously called TestRPC) which is now part of the Truffle framework. Truffle is a whole framework for development which covers many of the other functions outlined above, as I’ll show below. For this reason, it is better to install Ganache as part of Truffle.
Truffle
Truffle is a development framework for Ethereum. It provides many services for the developer, of which I highlight the following:
- It provides a javascript-based testing framework to test smart contracts. This framework is based on Mocha and Chai
- it provides a command line Solidity debugger
- it provides a scriptable framework to deploy and migrate smart contracts
- it provides an easy way to configure connections to different blockchain-hosting networks
- it provides a console to directly interact with a smart contract
Plus, as I said above, it includes Ganache, which is a must for development.Therefore, I recommend installing Truffle as part of your development setup.
Truffle is a node.js package. The best way to install is to first install node.js and npm, and then run
npm install-g truffle
Once this is done, create a new directory for your development and once inside it type:
truffle init
This creates a basic truffle structure, with three standard directories:
contracts
: this is where you should place your contracts. By default, this includes a single contract,Migrations.sol
, which is responsible for detecting the current version of each contract. Whenever you run truffle to deploy your contracts, this one will help truffle decide which ones have not been changed and do not need to be redeployed.migrations
: this stores the scripts needed to deploy your contracts. You don’t have to specify every contract you create here, but if there are dependencies between them, these scripts will define the order in which they must be deployed.test
: this is where you should place your truffle (javascript) tests for your contracts.
Besides these directories, truffle creates still two configuration files, with the same content: truffle.js
and truffle-config.js
. This is where you can specify the different networks you want to access, including an identifier, a name for the network, connection details, gas limit and gas price, among others.
The default name is truffle.js
, but in Windows this causes a conflict with the executable truffle
command. This is because the operating system will search for an executable file that can match that name (without extension) and give preference to files found in the current directory. Because JS files are considered executables, Windows will try to execute truffle.js
instead of the truffle batch file that is globally installed. If you don’t have to support more than the Windows platform, then I recommend you just delete truffle.js
and use truffle-config.js
instead. Otherwise, you should call your commands with truffle.cmd
instead.
Among the many things Truffle gives, an important one is the debugger. The debugger is rather basic, giving you a command line interface with the ability to step into, over and out of a function. But one feature I sorely miss (or could not find) is to set a breakpoint before I reach it in the code. You can toggle breakpoint once you are there, but it is far more useful to set the breakpoints ahead of time and automatically execute until we reach that point. Truffle debug
does not yet let you do this. In situations where you have libraries, for example, this is highly inconvenient, as it forces you to trudge through the linking code instead of simply jumping to the entry point in the library. There are other problems with the debugger, though. Sometimes it will not recognise a transaction, and simply fail to debug it. I’ve had a situation where the debugger seemed not to apply the short-circuiting rules of logical operators. It can evaluate Javascript expressions, but it would also be useful to evaluate Solidity code directly. In short, there is still some way to go for it to be a fully-useful debugger.
Ethereum Client
An application that interacts with a smart contract is essentially a distributed application. The smart contract is stored in the blockchain, somewhat akin to being “in the cloud”, which acts as a provider of services (smart contracts) for the applications. In some sense, the blockchain is a hugely distributed server, and accordingly the app needs to connect to it through some specialised “blockchain client”.
There are a number of clients to choose from. Ganache, of which I talked about above, is a quasi-client, in the sense that it gives access to a blockchain-simulation, but it is no good to link to “the” blockchain. In the Ethereum world, there is, of course, only one “true” blockchain, the one that hosts the smart contracts available for public consumption and the real Ether tokens. But testing with the real blockchain would be unreasonably expensive and dangerous (remember that smart contracts, once deployed, cannot be altered). Therefore, there exist also test blockchains, which have their own version of Ether that, obviously, does not have currency outside of these networks. Examples of test networks are Rinkeby, Kovan and Ropsten. The main blockchain itself is known as MainNet
Ethereum clients offer an API to interact with these networks, by sending transactions, making function calls, reading logs, etc. They can also act as full nodes in the network and act as miners. There are also a few of these around. Truffle recommends the following:
Here are some tips on how to use Geth.
Ethereum Block Explorer
Finally, once our code is deployed in a live network and our apps can connect to it, it is useful to use an explorer of the block chain, to confirm our transactions are really sent and accepted by the network. The best way to do this with Ethereum is Etherscan.
Should you need the same kind of service for your local development in Ganache, you can try EthExplorer.
Conclusion
This is it for today. I hope it can help you to set up your development environment, and start the journey as a blockchain coder.