Adventures in Classical Ether

Ethereum Classic Phoenix

I was first exposed to Ethereum a few weeks after it went online, fascinated by the concept of smart contracts on a blockchain. The interface used to build a smart contract seemed very interesting to me and I kept imagining the possibilities of a world where we can run decentralized applications that can make our daily life more efficient.

Ethereum Classic came into the picture for me right around the DAO hack and I followed it after the blockchain split, believing more in the values of the immutability of the blockchain. I’ve been a part of the ETC community ever since.

I wanted to build a smart contract for Ethereum Classic to better learn about how it works. For this guide, I will set out to build a simple Trademark Registration smart contract. The purpose of the smart contract is for a user to be able to look up registered trademarks, and if one isn’t registered, be able to register one. A user can also look up who is the author of a registered trademark.

Sounds pretty straightforward, let’s get started!

NOTE: This guide assumes some basic knowledge of the blockchain and smart contracts on the EVM. For a refresher, check out this guide.

For my local set up, I want to use the Truffle suite. It allows for local testing, deployment, and debugging of smart contracts all from your favorite terminal emulator.

We also need a client for connecting to the network. For simplicity’s sake, we will use ganache-cli here.

First, we have to install ganache and run it:

$ npm install -g ganache-cli
$ ganache-cli

When you run ganache-cli, it will run an Ethereum client locally which helps build Ethereum applications much faster.

Keep ganache-cli running in one terminal window for now. Note the port and host it connects to in the terminal window:

Listening on 127.0.0.1:8545
net_version
eth_accounts

Great, we have an Ethereum client running locally!

Now, let’s build our project environment. We start by making a directory and initializing truffle:

$ npm install -g truffle
$ mkdir trademark-contract && cd trademark-contract
$ truffle init

Great, now we have a truffle setup in our project. Let’s make sure our truffle project can listen to the ganache client that we are running. You can use your favorite IDE or text editor to code, I’ll be using vim here.

$ vim truffle.js

Inside the file, replace everything with the following code:

module.exports = {
networks: {
development: {
host: “localhost”,
port: 8545,
network_id: “*”,
}
}
};

The port we specified and the host are what’s given to us in the output of running ganache-cliearlier.

We will test that it is working by running the following:

$ truffle console
truffle(development)>

If it works, you should see truffle(development)> in your terminal. Type .exit to exit the truffle development console.

Now that our environment is all set up, let’s get started with building our smart contract!

For this project, we will be coding our smart contract in Solidity, the lingua franca of smart contracts.

NOTE: For deployment to ETC, we must only compile with Solidity versions below 0.4.2 . When you install Truffle, it installs the latest Solidity version, which we won’t be able to deploy to ETC. For simplicity’s sake, I will demonstrate how to code and test our smart contract in Truffle and then modify the version of Solidity after and deploy it to Ethereum Classic chain.

For our smart contract, we want to build a simple Trademark Registration contract. The contract must be able to look up whether a trademark is registered, be able to register a trademark if one isn’t taken along with the author of the smart contract, as well return back any information about a registered trademark.

The code for this smart contract is found on this GitHub repository.

We start off by writing out the smart contract version for solidity:

pragma solidity ^0.4.19;

NOTE: Here, we add the ^ to specify a Solidity version of 0.4.19 or higher in order for Truffle to compile with its higher version. When compiling for Ethereum Classic later, we will need to remove the ^.

We then add the skeleton code for our smart contract:

contract TradeMarkRegistration {}

Great, we have an empty contract so far. Now let’s think about what we want to build inside it. We will need a struct for our TradeMark that can register the phrase, authorName, timestamp, and proofof the TradeMark.

Inside the contract curly brackets, we build it out:

struct TradeMark {
string phrase;
string authorName;
uint256 timestamp;
bytes32 proof;
}

We then need to build mappings of the proof of the phrase to whether it exists in our mapping. We also need to build a mapping of the proof of the phrase to its TradeMark struct. We also need 2 functions, one for checking if a trademark is registered in our mapping, and another to generate a proof for our phrase. For the proof function, we will simply use a sha256 hash generator.

mapping (bytes32 => bool) private trademarkLookup;
mapping (bytes32 => TradeMark) public trademarkRegistry;
function checkTradeMark(string phrase) constant returns (bool) {
bytes32 proof = phraseProof(phrase);
return trademarkLookup[proof];
}
function phraseProof(string phrase) constant returns (bytes32) {
return sha256(phrase);
}

The functions here are straightforward. checkTradeMarkfirst generates a proof of a phrase passed to it then looks to see if it’s stored in the trademarkLookupmapping and returns a boolean. phraseProof hashes the phrase with thesha256 hash function.

Also, notice the constant near returns for those functions. This means that the function shouldn’t change the state of the blockchain or contract (and not use gas at all) but just do simple tasks that are static like generate a hash or do a simple lookup.

Now, let’s build the trademark registration function:

function registerTradeMark(string document, string author) 
returns (bool) {
if (checkTradeMark(document) == false) {
bytes32 proofHash = phraseProof(document);
TradeMark memory trademark = TradeMark({
phrase: document,
authorName: author,
timestamp: now,
proof: proofHash
});
trademarkLookup[proofHash] = true;
trademarkRegistry[proofHash] = trademark;
return true;
}
return false;
}

This function simply gets back the data of a registered trademark and returns it from the struct constructed.

Great, we have our smart contract built! Now, let’s compile it and deploy it.

In terminal, we run from inside the directory:

$ truffle compile
Compiling TradeMarkRegistration.sol...
Compiling Migrations.sol...
Writing artifacts to ./build/contracts

If you see a bunch of warnings pop up when compiling, they’re safe to ignore for now.

Now, let’s migrate our contract:

$ truffle migrate
Using network 'development'.
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x67927682a4f832b72fbce053fc90f55249f41c4ae50af65ef537e134ca4fc43c
Migrations: 0xc85fa4542d77675b4e05253456cbd3d579f5e4de
Deploying TrademarkRegistration...
... 0x26ac51700167a9ed91ced3f21f54c6ec4d5250cce8e9f647229903a9f15aea52
TrademarkRegistration: 0x2552fd4d9736ab3e147deb7e87b82758c87a3aa6
Saving successful migration to network...
... 0x1430e29094b1281ee0468b6132fa2b14e88c017239831aa10cd56e3233444e6b
Saving artifacts...
Running migration: 2_deploy_contracts.js
Replacing TrademarkRegistration...
... 0x671942c306680d3d788852f8797a5521c8558057e19d9a948d0d9c1b711e1ddd
TrademarkRegistration: 0x50c74ff65ccd8a12c8e4757a3268671ec67918cf
Saving successful migration to network...
... 0xaecd9a087edf24b70c1a1963e00ffded813b4244bae5383203422e9f1e46fd45
Saving artifacts...

Great, we have deployed our smart contract to our local client. Now, let’s interact with it and see if it works as intended.

$ truffle console
truffle(development)>

We will call our smart contract by creating a var that references to its address:

truffle(development)> var trademark = TrademarkRegistration.at(TrademarkRegistration.address)
undefined
truffle(development)> trademark.address
'0x50c74ff65ccd8a12c8e4757a3268671ec67918cf'

Sweet, we have the address of our smart contract. Now, we will call the functions and test out a trademark phrase. My trademark phrase for this example is: “ETC Take My Energy” and the author is “ETC Community”.

We first call the checkTradeMark function:

truffle(development)> trademark.checkTradeMark("ETC Take My Energy")
false

It returns a false boolean as expected since we haven’t registered the trademark yet. Let’s proceed with doing that:

truffle(development)> trademark.registerTradeMark("ETC Take My Energy", "ETC Community")
{ tx: '0x58ced570617bea3b210a7a914f749777e1f95c4c212551ca54a2cb0617f88895',
receipt:
{ transactionHash: '0x58ced570617bea3b210a7a914f749777e1f95c4c212551ca54a2cb0617f88895',
transactionIndex: 0,
blockHash: '0x26cadc9a227dd7edea0b1ed72dfdcfa3b99e9c409cbc4c14d5a3fd451084b972',
blockNumber: 6,
gasUsed: 129690,
cumulativeGasUsed: 129690,
contractAddress: null,
logs: [],
status: '0x1',
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' },
logs: [] }

Because our registerTradeMarkuses gas for registering a trademark, it results in a transaction output on our console just like if you were using gas on a production blockchain.

Now, let’s test to see if our trademark is registered:

truffle(development)> trademark.checkTradeMark("ETC Take My Energy")
true

It shows now as registered. What if we want to get back data on the registration of our trademark? We will use the getTradeMarkData function:

truffle(development)> trademark.getTradeMarkData("ETC Take My Energy")
[ 'ETC Take My Energy',
'ETC Community',
{ [String: '1536767522'] s: 1, e: 9, c: [ 1536767522 ] },
'0xf162b3f6c83d920f6ec6ee44bbede159c4c384c3efe1ad58ca209ad3441dbb26' ]

This shows the struct returned back to us with the phrase, author, timestamp, and proof of the phrase. Great, it works!

Now, let’s recompile this smart contract for ETC.

Remember before when I mentioned that ETC can run Solidity contracts lower than 0.4.2? We change the code at the beginning of the smart contract file to be this:

pragma solidity 0.4.19;

This tells solidity that we only want to compile with this version, not a higher version (by omitting the ^)

Ok, now we will need to head over to this web IDE for an easy compilation tool for Solidity.

Inside the browser here, we will paste our solidity code here:

On the right-hand side, we click on Settings and select 0.4.19+commit.c4cbbb05 from the Solidity version dropdown as shown here:

This tells the site which compiler to use to compile our smart contract. We then click on compile to start compiling here:

After compilation, click on the button Details. A popup will appear with relevant information that we need. We need 2 things, the bytecode generated and the ABI JSON code.

For the bytecode, we need to copy-paste what’s inside the “object” key. We then go on over to MyCrypto to deploy.

NOTE: Since we are going to be deploying to our ETC Blockchain, I will assume you already have an Ethereum Classic wallet with ETC currency on it and you have used MyCrypto before.

Inside the Contracts tab in MyCrypto, select the Deploy tab in order to deploy. Copy paste the bytecode into the text area element as shown here:

Then, select Deploy Contract button in order to deploy. It’ll ask you to sign the transaction, which you can do via a hardware wallet or your private key. Note that deployment also costs gas, so make sure you got ETC in your wallet for deployment.

Once you deploy, you’ll be shown the transaction and contract address as shown here:

Make sure you copy paste the address since you’ll need it to interact with your smart contract.

For now, give yourself a mini-pat on the back as you’ve deployed a contract to Ethereum Classic chain!

Let’s start registering a trademark on our immutable blockchain.

Go back to MyCrypto->Contracts. Select the Interact tab.

Inside that tab, there are a few options that you need to fill out. First is the Contract Address, which you’ll need to paste in the contract address you saved earlier after you deployed your smart contract.

Then, you need to copy paste the ABI JSON we discussed earlier into the text area. ABI JSON provides an easy interface one can use to interact with their smart contract. It was generated back in our solidity-browser step when we compiled our contract. You can copy it by selecting the copy button here:

Go ahead and paste it inside the text area like this:

Now, when you click on Access, it will generate an interface for you to interact with your smart contract as shown below:

If we select checkTradeMark from our dropdown, we will be presented with an input for phrase string where we can check on our trademark. Let’s type “ETC Take My Energy“ into it and see what it returns:

It returns a false since we haven’t registered that trademark on our Ethereum Classic chain.

Let’s register it then. Select registerTradeMark from the dropdown, and fill the phrase as “ETC Take My Energy” and author as “ETC Community” as shown below:

Now, we write the command, being prompted to sign our transaction. After doing so (with your private key or hardware wallet), you’ll be able to send the transaction. Once the transaction is sent, you can see it on gas tracker and know when it’s being confirmed. Once it is confirmed, we can go back to MyCrypto and check to see if our trademark is registered.

Using the function checkTradeMark, we see if it’s registered:

It returns true! Congratulations, you just registered your first trademark on Ethereum Classic chain!

Now, let’s get data back about our trademark using getTradeMarkData:

Great, we see the authorName, timestamp, and proof.

That’s awesome. We can expand this smart contract further in the future by building a friendly UI on a web app for it. For now, hope you enjoyed this guide.