This is my personal laboratory where I conduct experiments with Smart Contracts (SC) in the Ethereum blockchain.
I have been using the Truffle suite of Ethereum development tools, so you’ll need installed:
- Truffle for the development environment
- Ganache Ethereum blockchain sandbox (optional)
- ganache-cli command-line version of Ganache (optional)
Some of the SC have smalls decentralized-applications (dApps) to test how’s the Web3 integration with them. I’m using ClojureScript to write these, and you’ll find them in the dapps/ folder.
They’re just an extension of the SC; thus, none of them are mandatory. But, if you want to play with them using a blockchain sandbox, you’ll need to compile using the Clojure CLI.
I like short feedback loops for the exploration phase of a problem, so I’m
using truffle’s develop
command to run a REPL. It comes with built-in
utility functions to migrate, test, and compile the SC without quitting the
underlying process.
truffle develop
The above method is often enough, but I sometimes feel like having more visual feedback on the created transactions resulted from SC interactions from the REPL. For that, I like to pair truffle with Ganache GUI.
# Before running the commands below, you need to start the Ganache GUI locally.
truffle compile
truffle migrate --network development
truffle console --network development
NOTE: The networks are defined at truffle-config.js.
To call contract methods from different accounts, you need to pass the address as an extra argument.
contract.doSomeMagic('foo', { from: '0x708ed710A6eeD6A877fA906f15CD427a46320685' })
# Runs all tests.
truffle test
# Runs a single test in any supported extension (.js, .ts, .sol).
truffle test <FILEPATH>
By default, Truffle doesn’t reset the state in between tests and this might have some undesired behaviors. However, we can workaround the issue by deploying the contract again in the test scope.
Calling .new
in the contract class will force a new deploy with a new
address. Thus the state will be fresh only within the test where it was
invoked.
it('foo', async () => {
console.log((await TodoList.deployed()).address) // address 1
console.log((await TodoList.new()).address) // address 2
console.log((await TodoList.deployed()).address) // address 1
})
it('bar', async () => {
console.log((await TodoList.deployed()).address) // address 1
})
It seems intuitive to me to always deploy a new contract for every test to avoid state leaking. However, the Truffle team must have a good reason to share the deployed address within tests in the same file, and I don’t know the consequences of repeatably deploy the same contract yet.
See In-test debugging documentation.
See TodoList.sol and todo_list.js.
TodoList.deployed().then(todo => todo.add('do some foo'))
TodoList.deployed().then(todo => todo.get(0))
TodoList.deployed().then(todo => todo.toggle(0))