Creating a local test environment for Ethereum Smart Contracts

hardie™
5 min readDec 20, 2017

--

In this tutorial I will describe the setup for my local environment when developing smart contracts, enabling offline testing.

I have compiled this information from various existing tutorials on the Truffle website.

Step 1 - Set up MetaMask browser extension.

MetaMask is a Chrome and Firefox add on that allows you to interact with dapps using the browser. You can connect to the main Ethereum network without having to run a full node on your machine. Alternatively, you can connect to a testnet (for example Ropsten), or a local blockchain. During development we can use MetaMask to interact with our dapp’s functions in the same way users will eventually interact with it on the Ethereum mainnet (via transactions).

To install MetaMask for Chrome, go to the Chrome Web Store and click the “Add to Chrome” button.

To install MetaMask for Firefox, go to the Firefox Add-ons page and click the “Add to Firefox” button.

Step 2 - Install Ganache personal Ethereum blockchain.

Ganache is a GUI developer tool allowing fast & easy deployment of a personal Ethereum blockchain. We can run tests, execute commands and inspect state while controlling how the chain operates, making this an excellent tool for our dapp development.

Ganache auto-mines all transactions immediately, making it a great accessory to continuous integration build tools.

To install Ganache download from the Truffle framework’s website and follow the installation directions.

Step 3 - Set up MetaMask with your Ganache chain

Note: If you already use MetaMask, ensure your current Wallet Seed is properly backed up as we will install a new wallet for our test.

When opening Ganache, you will be greeted with a seed phrase. This is how we will import our wallet into MetaMask. Copy the phrase and go to MetaMask. Click import existing den if you are creating your first MetaMask. If you already have a wallet set up, you should lock your usual MetaMask and then click “restore via seed phrase”. When prompted, enter your Ganache seed phrase (or usual wallet’s, when you are finished with the local environment).

Now we need to connect MetaMask to the blockchain created by Ganache. Click the menu that shows “Main Network” and select Custom RPC. Enter the following url into the “New RPC URL” box : http://localhost:7545 and click Save. The network at the top will now say “Private Network”.

Each account created by Ganache is given 100 ether. The first account should have less than the others because that account supplies the gas for smart contract deployment.

Step 4 - Set up a Truffle project to deploy to the development blockchain

Truffle is the most popular development framework for Ethereum. It simplifies the process of dapp development by providing a compiling, testing, deployment and debugging toolset. To install Truffle you will need to have NodeJs 5.0+. Follow the instructions on their website.

First, lets create a simple dapp.

$ mkdir hello-world
$ cd hello-world
$ truffle init

The command truffle init uses the following repo as default blueprint https://github.com/trufflesuite/truffle-init-default, it includes an example contract and tests.

To create a new contract, run the command truffle create. It requires the type of item we want to create and the name.

$ truffle create contract HelloWorld

The name must be CamelCased. After running the command, the file will be under contracts/HelloWorld.sol with the following content:

pragma solidity ^0.4.4;

contract HelloWorld {
function HelloWorld() {
// constructor
}
}

We need to configure this app to enable deploying to our local blockchain. We can do this in the dapp’s truffle.js configuration file. Navigate to the root of the hello-world project, and edit the truffle.js file to the below:

module.exports = {
// See <http://truffleframework.com/docs/advanced/configuration>
networks: {
development: {
host: "localhost",
port: 7545,
network_id: "*" // Match any network id
}
}
};

Now if we create a migration, we should deploy directly to our Ganache chain. Lets try that :

$ truffle create migration deploy_hello_world
$ truffle migrate --network development

If everything worked, Truffle will log some successful migration info, as below:

Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x8799ca767bb7c11ddb17b9453755b05bc60f69cedeb43ea4e1763c11b11918f7
Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0
Saving successful migration to network...
... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956
Saving artifacts...
Running migration: 1513768483_deploy_hello_world.js
Saving successful migration to network...
... 0xe6181e7cc0395712a06bd7f909e65473f197e383a9494971e8f11ce23854a2b6
Saving artifacts...

We can see from the log that the migration of the hello world contract was completed on transaction id 0xe6181e7cc0395712a06bd7f909e65473f197e383a9494971e8f11ce23854a2b6. Moving to the Ganache GUI, we can see in the Logs section that our transaction was a contract creation, and was successful.

Our local network is setup correctly!

In the next section, I will be explaining how we can deploy a smart contract that actually does things, and how to interact with it using MetaMask.

Deploying And Interacting With A Real Smart Contract

We will now deploy a contract where we can set a variable using a transaction, and then query what the variable is set to using the Truffle console.

One of the most basic types of smart contract is a simple storage contract. This example was lifted from the Solidity Documentation.

pragma solidity ^0.4.17;  contract SimpleStorage {
uint myVariable;

function set(uint x) public {
myVariable = x;
}
function get() constant public returns (uint) {
return myVariable;
}
}

Any Java developer will notice the basic getter/setter functions of a bean class in this contract (for others we could say struct or json entity!). So, lets get this bean into our local blockchain so it is callable from our wallet.

Create a new project

$ mkdir simple-storage 
$ cd simple-storage
$ truffle init

Inside the contracts/ directory, create a file called Store.sol with the Simple Storage contract sample from earlier.

Inside the migrations/ directory, create a file called 2_deploy_contracts.js and populate it with the following content:

var SimpleStorage = artifacts.require("SimpleStorage"); module.exports = function(deployer) {        
deployer.deploy(SimpleStorage);
};

As before, edit the truffle.js file at the root of the project to add our local network to its deployable environments:

module.exports = {
// See <http://truffleframework.com/docs/advanced/configuration>
networks: {
development: {
host: "localhost",
port: 7545,
network_id: "*" // Match any network id
}
}
};

Now we are ready to compile and deploy.

$ truffle compile
$ truffle migrate --network development

If all goes well, we should see our contract deployed in the Ganache log.

We will now use the Truffle console to see what our variable is set to, by making a remote call to the get() method.

$ truffle console
truffle(development)>

We can see the console has connected to our configured environment (development). Enter the following command:

SimpleStorage.deployed().then(function(instance){return instance.get.call();}).then(function(value){return value.toNumber()});

This command looks at the SimpleStorage contract and calls the get() function, and displays the response converted to a number:

0

The variable myVariable is set to 0. This is because variables with integer types are automatically populated with the value of 0 in Solidity. (Similar to a Java primitive int.)

We can now set the variable using a transaction. First lets try that on the console:

SimpleStorage.deployed().then(function(instance){return instance.set(4);});

This sets the variable to 4. The output in the console will show the tx ID and receipt and some logs (which will be empty). Run the get() function again to ensure the variable is now updated. In my case the tx Id is 0x2cc0d39fc0bec51835df91343e64577b34ae335f7d998143349d5ab8b3d63181. We can check when the transaction happened on the blockchain in the Ganache logs.

[15:38:00] eth_sendTransaction
[15:38:00] Transaction: 0x2cc0d39fc0bec51835df91343e64577b34ae335f7d998143349d5ab8b3d63181
[15:38:00] Gas usage: 41642
[15:38:00] Block Number: 11
[15:38:00] Block Time: Wed Dec 20 2017 15:38:00 GMT+0000 (GMT)

As this isn’t a contract where we can send Ether, we cannot directly interact using the MetaMask browser extension. However, you may notice that the first account has been charged Ether (gas) for running the transactions.

You are now ready to start developing more complicated apps locally.

--

--