# Updating and Testing a Raffle Contract

Over on the Bitfalls website there’s a couple of great tutorials(1) for learning Solidity and Ethereum. The tutorials guide readers through the making of a Raffle. Now, the code is not meant to be bullet proof, but as a software tester by day the ‘gaps’ piqued my interest.

In this post I’m going to do two things; firstly provide a few updates to the code readers pointed out or that have become the more current way of doing things since Solidity version updates and secondly, to execute the code in the online tool, Remix, so we can see how it actually runs.

Naturally, the below makes more sense if you’ve either worked through the tutorials, will do or have just grabbed the code. Let’s crack on.

## Code Updates Firstly, let’s look at what needs a refresh since Bruno wrote the original articles. Open up the `Blocksplit.sol` file you’ve been working on. You can always get the completed script from their GitHub repository.

Review the code for the `randomGen()` function from the last tuorial:

``````    function randomGen() constant internal returns (uint256 randomNumber) {
uint256 seed = uint256(block.blockhash(block.number - 200));
return(uint256(keccak256(block.blockhash(block.number-1), seed )) % players.length);
}
``````

In here we can see the `… block.blockhash(block.number …` construct, this needs to be changed to read `… blockhash(block.number …`.

Additionally, the last line of the `randomGen()` function should be changed to use ``abi.encodePacked` and the trailing space after seed removed. It will look like this:

``````return(uint256(keccak256(abi.encodePacked(blockhash(block.number-1), seed))) % players.length);
``````

This will give a final code block for the `randomGen()` function of:

``````    function randomGen() internal view returns (uint256 randomNumber) {
uint256 seed = uint256(blockhash(block.number - 200));
return(uint256(keccak256(abi.encodePacked(blockhash(block.number-1), seed))) % players.length);
}
``````

One final change just so we don’t lose any test Ether is to change the `address public charity` to be one of your test accounts, make it the one you deploy the contract under. Account set-up is discussed next.

`address public charity = put-the-full-address-here-for-your-test-acccount;`

One last thing is to change the ‘Unix epoch’ time in the `draw()` function to something in the near past if it’s very current.

### Set-up the Testing Environment

There’s a few things we need to have in place to test this contract effectively: - MetaMask - Three Ethereum Accounts - Remix open in a browser window - The updated contract code ready to deploy

Make sure the MetaMask browser extension is running in either of Brave(2) or Chrome.

We’ll need to have three Ethereum accounts available to us via MetaMask – one to act as the contract owner and two additional ones to act as the players. If you’ve not done so, read the Bitfalls MetaMask article that explains how to set up MetaMask and add accounts. You’ll need to get some free Ether from one of the faucet sites in order to play the raffle.

Remix is a free browser-based IDE for writing smart contracts in Solidity, then compiling and deploying them. It’s available at https://remix.ethereum.org/.

### Compile and Execute the Contract Code

The Remix UI was updated mid 2019 so may have a different look compared to other tutorials you’ve worked through - be sure to select ‘Solidity’ under the Environments section of the Home page before you start.

To the top-left, change the Compiler version to read `0.4.26+commit.4563` as from version 0.5.0 there were breaking changes to the Solidity codebase. This is also above the 0.4.20 compiler version we stated in the contract code, so the code will compile just fine.

In Remix, click on the ‘File explorers’ icon, create a new file and call it `Blocksplit.sol`, then paste the updated contract code into the file and save it.

Now click on the ‘Solidity compiler’ icon and hit ‘Compile Blocksplit.sol’

Finally, click the ‘Deploy & Run Transactions’ icon, we’ll use this tab to deploy and test our contract. We’ll deploy to the Ropsten test network and to do so we need to change a few things before we hit Deploy.

• In the ‘Environment’ field select `Injected Web3` from the dropdown
• In MetaMask, switch to the ‘Ropsten Test Network’
• Also in MetaMask, select the account you have chosen as the contract owner account

Now hit the orange ‘deploy’ button to deploy the contract to Ropsten, accepting the MetaMask transaction window when it pops-up. This is charging the cost of writing to the blockchain.

### Check the Deployed Contract and Interface

Now we’ve deployed the contract we’ll have a set of buttons that provide an interface to the contract elements, shown under ‘Deployed Contracts’. Click the arrow next to the contract name to show the set of buttons that give us an interface to the contract.

Next to the contract name is also the contract address that can be copied and searched for on Etherscan against the Ropsten network. Copy the address shown and look up the Etherscan record. Between Etherscan and MetaMask we can readily see how the transaction details match up.

We can see that the ‘From’ address, Contract Creator address and the address we used in MetaMask all match. This shows us how organisations can deploy a contract, then use the `msg.sender = owner` code pattern to assign the ability to perform certain actions only to a given address; in this case the one that deployed the contract.

As a reminder, blue buttons read data and so are free of Gas, whereas orange buttons write data to the blockchain and so will cost us Gas.

Click on the blue ‘charity’ button and you’ll see a) no MetaMask window as we don’t need to pay anything and b) the address we assigned to the `address public charity` variable.

Note the contract value is showing as ‘0 Ether’ as no raffle monies have been transacted yet.

### Play the Raffle

Ordinarily, the public raffle elements we can get to would be wrapped in a Web3.js enabled webpage, using the ABI file, to give us a smart interface. However, for testing, the Remix interface is good enough.

#### Player One Plays

To play we need to switch to an alternate account in MetaMask, so we’re acting like the raffle’s Player One and not the owner. Open MetaMask and switch accounts now, that same account will be shown in Remix in the ‘Account’ field.

• in the ‘Value’ field enter 0.1 and make sure ‘ether’ is selected
• in the field next to the ‘play’ button, paste the address you’re using as Player One
• hit the ‘play’ button and accept the MetaMask prompt to pay the fee plus gas

After a few seconds MetaMask will bring up a prompt stating the transaction went through. If we check the contract again on Etherscan, we’ll see it now has a second transaction worth 0.1 ETH from the address we’re using for Player One.

If you now enter `0` in the field next to ‘players’ it will return the address of Player One. This is because we declared `address[] public players;` at the start of our contract then `players.push(_participant);` in the `play()` function - which takes an address (as we tested above), then pushes it onto the `players` array.

#### A Quick Sanity Test

Something we can test now is clicking on the ‘draw’ button. The code here is that we can only run a draw if the number of winners is less than 2: `require (winners.length < 2, "");`. This is interesting as when we click ‘draw’ now it should work and indeed it does. If we enter `0` in the field next to the ‘winners’ button it will return the address of Player One.

It may be that we should change this code in two ways: - Change `draw()` to Require the `msg.sender` to be the owner of the contract so not just anyone can call the function - Set a Require of `players.length == 2` to ensure two players are needed for a draw to happen

#### Player Two Plays

To play a second player is just like playing the first. Switch accounts, set the value to 0.1 ETH, add your Player 2 address into the ‘play’ field and hit ‘play’ as before.

Now in Etherscan we can see: - two transactions of 0.1 ETH which are the raffle ‘plays’ - one transaction between these that are the possibly unwanted pressing of ‘draw’ by a player

Both of the above can be proven using Etherscan’s logs: - Click on the ‘Txn hash’ for the draw (0 ETH transaction) - At the bottom of the page that opens, click on ‘Click to see More’ - Under ‘Input Data’ check to see it says ‘Function: draw() ***’

Repeat the steps above to check one of the Plays made by either player.

However, we may have another potential issue. In the `draw()` function we have the line of `players.length--;` which with the line of code above it is a way to remove the winner from the list of players (so they don’t become winner number 2 as well as winner number 1, fair enough). We can test this too by entering a `0` or a `1` in the field next to ‘players’ and seeing what’s returned. We expect two player’s addresses but for index `1` we should get ‘0x0000000000000…’ which tells us Player One got removed from the `players[]` array (because when I tested, Player One won. It may be Player Two for you). OK, the code works, but the change suggested above might prevent this if we feel it’s an issue.

As we have clause in `draw()` that won’t allow us to send any ETH balance off to the charity address until `winners.length == 2` we need another player to win. As it happens, we can just hit `draw()` again and watch our remaining player win.

### Re-draw and Contract Payout

Go ahead and hit `draw()` for a second time, then refresh the Etherscan page for your contract. You’ll eventually see a new 0 ETH transaction for the second draw and the contract value is now 0 ETH.

That proves the `charity.transfer(address(this).balance);` line in `draw()` must have worked – but where’s the transaction?

You’ll notice there’s a new tab in Etherscan called ‘Internal Txns’, our `transfer` of 0.2 ETH is recorded in there as it occurs as part of the code in the function, not a call from outside. The balance is sent to the address that was defined under the `charity` variable.

### Conclusion

We’ve seen that at every step of the way we can control how the contract is deployed, deploy it to a non-live blockchain such as the Ropsten Testnet, then carefully test out the contract functionality. Remix and Etherscan combined provide us with a host of features and information to allow us to test our code and check the results.

There are more tests we could add, but the core features have been checked here. We’ve also discovered there are some (expected) weaknesses in the code that could be fixed up. Overall, a good couple of tutorials and a great way to learn more about Solidity and Smart Contract development.

Until next time!

Mark

References

1) Tutorials: https://bitfalls.com/2018/03/31/solidity-development-crash-course-building-blockchain-raffle/ and https://bitfalls.com/2018/04/05/solidity-development-crash-course-finishing-raffle-project/

2) Brave Browser: https://brave.com/CYR315 (referral link)

• Kauri original title: Updating and Testing a Raffle Contract