A new game Capture the Ether has been released with the express purpose of teaching people Ethereum programming and to make the basics of smart contracts and blockchain more approachable. The game comes at a perfect time as it's a brilliant followup to our total introduction into Solidity programming.
The game explains what's needed to beat each step and in the process assigns points for successful completions of tasks, listing the best players on a leaderboard.
The first steps are there as a warmup, but can still be too complex for people who have never done any Solidity programming or programming in general, so we absolutely recommend reading our gentle introduction first.
The game first takes the players through the process of changing the Ethereum network they're connected to with MetaMask from Mainnet to the Ropsten testnet, and then explains how to get Ropsten Ether for playing the game.
Let's go through challenge 2 and 3 (we'll skip the first – do it yourself as it's a simple button click) as a demonstration and explain what exactly we're doing.
Call Me
To solve this challenge we need to call the callme
function in the smart contract that's been deployed on the address shown on the screen. In my case that's 0x80d70155c1defd5c38D8ae0421e9f668b8ac024c
. Luckily, we published a tutorial about that specific thing – how to call functions on the Ethereum blockchain.
The challenge code looks like this:
pragma solidity ^0.4.21;
contract CallMeChallenge {
bool public isComplete = false;
function callme() public {
isComplete = true;
}
}
As we explained in our introduction, the pragma
line denotes which version of Solidity we're using to write the code.
Next, the CallMeChallenge
contract is defined which declares a single boolean variable (boolean means it can only be true
or false
, no other value) called isComplete
, which defaults to false
. It also declares the callme
function which is public
– this means it can be called both from within the contract and from outside it. This function, when called, changes the value of isComplete
to true
.
Thus, it is enough to open Remix, paste the code shown on the screen into an empty file (1), open the Run tab (2), enter the address of the contract into the At Address
field (3), check that Injected Web3
is selected as the environment (4) and click the blue At Address
button (5).

If you get the following error when pasting the code into an empty Remix file…
browser/Untitled.sol:1:1: SyntaxError: Source file requires different compiler version (current compiler is 0.4.19+commit.c4cbbb05.Emscripten.clang - note that nightly builds are considered to be strictly less than the released version
… go to the Settings screen, change the version into the newest one and try again.
After clicking At Address
the buttons callme
and isComplete
will become available in Remix.

Notice that clicking the isComplete
button returns the value false
which means the challenge hasn't been completed yet.
Clicking the red callme
button will execute the function and change the variables value once you confirm the transaction with MetaMask. Remember, red buttons are write functions and always require a transaction. Blue buttons are read buttons and can always read blockchain data for free.
We can make sure we completed the mission successfully by clicking the isComplete
button again and getting back true
or by clicking “Check the solution” in the game itself.

Choose a Nickname
This mission wants us to define a nickname for the current player. The code is as follows:
pragma solidity ^0.4.21;
// Relevant part of the CaptureTheEther contract.
contract CaptureTheEther {
mapping (address => bytes32) public nicknameOf;
function setNickname(bytes32 nickname) public {
nicknameOf[msg.sender] = nickname;
}
}
// Challenge contract. You don't need to do anything with this; it just verifies
// that you set a nickname for yourself.
contract NicknameChallenge {
CaptureTheEther cte = CaptureTheEther(msg.sender);
address player;
// Your address gets passed in as a constructor parameter.
function NicknameChallenge(address _player) public {
player = _player;
}
// Check that the first character is not null.
function isComplete() public view returns (bool) {
return cte.nicknameOf(player)[0] != 0;
}
}
It's important to note that the code displayed on the screen is actually a combination of two different contracts, and just the relevant parts of them. The function setNickname
is the main function of the CaptureTheEther
contract of the whole game, but is for simplicity shown here without the rest of the logic which powers the game. This does not mean that the whole contract is only that one function!
contract CaptureTheEther {
mapping (address => bytes32) public nicknameOf;
function setNickname(bytes32 nickname) public {
nicknameOf[msg.sender] = nickname;
}
}
This contract first defines a mapping which connects Ethereum addresses and text. The function setNickname
which is public
accepts one argument, and that's the nickname of the player. This nickname is saved into the appropriate address of the nicknameOf
mapping.
The second contract is the NicknameChallenge
and is there just as a validator for the first. In programming, we call such a program a “test” because its only purpose is making sure another program works.
contract NicknameChallenge {
CaptureTheEther cte = CaptureTheEther(msg.sender);
address player;
// Your address gets passed in as a constructor parameter.
function NicknameChallenge(address _player) public {
player = _player;
}
// Check that the first character is not null.
function isComplete() public view returns (bool) {
return cte.nicknameOf(player)[0] != 0;
}
}
This contract first references the previously deployed CaptureTheEther
contract for the current user, saves it into the cte
variable and declares the player
variable which saves the current player's address (currently empty). This is also visible in the NicknameChallenge
function which is purposely named the same as the contract. Such functions are called constructors and are immediately executed when the contract is created. After accepting a player's address, the function stores it into the previously declared player
variable.
Finally, the isComplete
function checks if the mission was completed successfully. cte.nicknameOf
will call on the nicknameOf
variable from the CaptureTheEther
contract and will grab its zeroth (first, because counting starts at 0) element and compare it to 0. In other words, it checks that the nickname of that address isn't empty.
The challenge requires the following:
To complete this challenge, set your nickname to a non-empty string. The smart contract is running on the Ropsten test network at the address 0x71c46Ed333C35e4E6c62D32dc7C8F00D125b4fee.
This means we need to call the setNickname
function on the provided address and give it a nickname by which the game can call us. Following the procedure from the previous task, we get to this screen:

Notice that we've provided “bitfalls.com” with the quotes – this is very important when dealing with text in Remix, and the quotes will be excluded from the final sent value. After clicking the red button and confirming the transaction, the nickname will be set. To check if it worked, we need to click the “Check the solution” button in the game. Apart from a victory screen telling us that we've successfully completed the challenge…

… we'll also now be named in the upper right corner of the game.

Conclusion
We went through two challenges in the CaptureTheEther game, the purpose of which is educating people on Solidity code and common pitfalls in security.
While some decisions are sub-optimal (e.g. functions that are only meant to be called from the outside of the EVM should be declared external
, not public
), the game is an excellent source of experience in the Ethereum ecosystem and we recommend that you try playing through some more challenges if you're an aspiring Ethereum developer. Good luck!