A 'Hello world' Ethereum smart contract using Ganache
In this step-by-step blog post I will go through the simplest possible smart contract using the Ganache Ethereum emulator.
A coating of Ganache
Ganache is an in-memory full Ethereum node, loaded with utilities to facilitate local testing and debugging.
It can have a number of different test blockchains (called workspaces), each with its own pre-loaded testing accounts.
Most importantly, the built-in Ethereum miner lazily mines blocks only when there are new transactions, rather than every
few seconds. This greatly helps keep “log noise” to a minimum.
Installing on a Mac is a simple download or a simpler Homebrew brew install --cask ganache
.
Let’s create a quickstart workspace.
This starts a node listening on port 7545, mining a local blockchain. The blockchain is “seeded” with 10 accounts, each
pre-loaded with 100 Ethereum.
We will also need to have the latest Node.js installed (e.g. by brew install node
).
The contract
Clone locally the hello_ethereum project from Github.
Run npm install
to get the 2 dependencies:
- the Solidity compiler (
solc
). This also determines the supported version of the Solidity language. - the Web3 library (
web3
). We will use this to deploy and communicate with our smart contract.
Let’s quickly examine the contents of our Hello smart contract.
- It defines an internal variable to store the message…
- which is initialized atomically in the constructor (i.e. globally once, upon deployment).
- There is a reader method
getMessage
, which returns the current value of the message.
It is worth noting that this is marked asview
, which makes it “free” to call. Remember that most smart contract actions in Ethereum require the caller to spend gas. - Finally, there is a writer method
setMessage
, which changes the “state” of the contract (i.e. the message).
Compiling and deploying
The rough outline of the steps to deploy a smart contract are as follows:
- Compile the Solidity code into the ABI interface and EVM bytecode.
Thesolc
compiler takes a JSON object defining all the compilation parameters, including the source code itself. - Create a Contract object based on the compiler output.
This output contains the ABI and EVM as separate JSON fields. - Create a “deploy contract” transaction and send it to the target node (in our case, the local Ganache node).
The transaction needs to be sent (and hence paid for) by one of the accounts already created by Ganache.
These steps are captured in the script deploy.js
.
After updating the account from which to deploy the contract (i.e. pay the gas fee), you can execute it with
node deploy.js
.
The output will look something like this.
We can verify the deployment transaction in Ganache.
We can also see the reduced balance of the deployment account, after paying for the deployment cost.
Interacting with the contract
Now that the contract is deployed we can call its 2 methods.
The getter is “free” to call, whereas the setter requires the caller to pay some gas.
To call an Ethereum contract we need a Contract instance.
The instance is defined by the Contract’s interface (i.e. the methods it exposes, in ABI) and the address where it is
deployed in the blockchain.
We can get the ABI by compiling the Solidity code, whereas we have the deployed address from the deployment message and the
Ganache transaction log.
Some sample commands to interact with the contract are in the script interact.js
.
After updating the contract and caller account addresses, you can execute it as many times as you want with node interact.js
.
We can verify the message update transactions in Ganache.
We can also see the updated balance of the account making the API calls.
Parting thought
This post is by no means an Ethereum deep-dive, nor does it aspire to be one.
The intention is to provide a one-stop starting point, if you want to get started with Ethereum smart contracts.
Happy coding!