Right. Now we’ve got a Ringmaster and Seats, but nobody’s going to be entertained until we’ve got a full set of performances to entertain them.

Now let’s add some performances to the show. A performance can be given a name, a number of actors in the performance, number of tigers, bears and elephants required for the act, and the amount of time that will be allotted. In addition, it might be useful to make note that clearing the stage is required for the performance to take place. This will let the producers of the show know that some special prep is required in order to handle the performance.

All programming languages attempt to model reality by giving the programmers ways of defining objects through some sort of data structure. In Solidity, the most common way of doing this is by use of the struct — where user defined types can be defined. In the body of the contract, let’s define a Performance structure.

struct Performance {

string name; uint32 actors; uint8 tigers;

uint8 bears;

uint8 elephants; uint16 timeInSeconds; bool clearTheStageFirst;

}

The creator of the contract will now need a way to add a Performance to the show by passing in the required values to a function. Storing this data in the contract has a cost; however, we’re not covering that right now. Right now we’re just demonstrating the need to keep track of it. So that means we’ll have to keep track of an array of Performance objects, denoted Performance[] performances . We’ll append to the array each time the addPerformance function is called.

Performance[] performances;



function addPerformance(

string _name,

uint32 _actors,

uint8 _tigers,

uint8 _bears,

uint8 _elephants,

uint16 _timeInSeconds,

bool _clearTheStageFirst ) public { performances.push(

Performance( { name: _name, actors: _actors,

tigers: _tigers, bears: _bears,

elephants: _elephants,

timeInSeconds: _timeInSeconds,

clearTheStageFirst: _clearTheStageFirst }

)

);

}

We’re about to get ahead of ourselves for a second, but hopefully this will help clear things up. After the contract is deployed to the network, the owner of the contract might obtain the instance of the deployed contract using code in truffle console that looks similar to this.

// Add a performance of Knife Throwing requiring 2 people.

// The performance will last 3 minutes and require zero animals.

GreatestShow.deployed().then( function(show) {

show.addPerformance( "Knife Thrower", 2, 0, 0, 0, 180, false );

} );

// Add a performance of 4 Flame Breathers lasting 30 seconds

GreatestShow.deployed().then( function(show) {

show.addPerformance( "Flame Breather", 4, 0, 0, 0, 30, false );

} );

Arrays in Solidity, as in most languages, are zero-indexed. To get the first performance inside the contract code, you could reference performances[0] .

But what if you wanted to access all the data for a particular performance as the caller of the contract? Imagine that a user of your contract will want to list information on some web app. We’ll add a handy method to get at all the data for a particular Performance instance at the _index passed in.

Note again that the data is not changing, but also note that we cannot directly return the Performance object. Solidity limitations require that the data must be returned as multiple values as indicated in the returns statement. We wrap all of the return values by ( parenthesis ) .

function getPerformance( uint _index ) view public

returns (string, uint32, uint8, uint8, uint8, uint16, bool) { Performance storage perf = performances[_index]; return (perf.name, perf.actors, perf.tigers, perf.bears,

perf.elephants, perf.timeInSeconds,

perf.clearTheStageFirst);

}

Imagine the third entry is Zendaya’s performance as Anne Wheeler the flying trapeze artist. She’s a one woman show, but needs a set of 8 other supporting actors to help catch and throw her around as she performs various acrobatic feats. and the stage needs to be clear for the equipment. An example of how to get some info from that performance:

GreatestShow.deployed().then( function(show) {

let performance = show.getPerformance( 2 ); // 0-indexed console.log( "Name:" + performance.name ); // Flying Trapeze

console.log( "Actors:" + performance.actors ); // 9 = 1 + 8

console.log( "Clear:" + performance.clearTheStageFirst); // true

});

Zendaya as Anne Wheeler the Flying Trapeze Artist and 8 supporting Actors

We’re almost done but we need a way to collect money for the people buying tickets! Luckily in Ethereum there is a way to create a function that accepts Ether, the native cryptocurrency representing digital money. Ether has a fluctuating exchange rate versus normal fiat currencies like the US Dollar or British Pound, but we’re not going to worry about that for the sake of argument. No, instead we are only going to worry about accepting Ether in exchange for a certain number of seats.

We haven’t discussed the mapping data type yet, but essentially it allows us to map one value to another value. Here we will demonstrate keeping track of ethereum addresses and their count of tickets in an unsigned integer.

mapping(address => uint256) internal tickets;

An easy way to accept Ether is to mark a fallback function as payable and do the logic inside that function to assign the function caller’s Ethereum address a number of tickets per unit cost. A simple method might look like this:

uint256 internal ethusd = 700; // peg to 700 dollars

uint256 internal rateInCents = 2000; // 2000 cents = $20.00 function () payable public { uint256 _wei = msg.value; // 1 Ether = 1000000000000000000 wei

uint256 tickets4ETH = _wei.mul(ethusd).mul(100).div(rateInCents);

tickets[msg.sender] = tickets[msg.sender].add( tickets4ETH ); }

Ignore for a moment that the ETHUSD rate is constantly changing in reality. We’re representing a pegged value of $700 per ether, and a ticket price of $20.00. There are some limitations in Solidity that do not allow for floating point numbers to be stored. Knowing that we have to deal with this limitation, we want to make sure that we have more places available to perform arithmetic so that we don’t lose as much precision as possible when multiplying or dividing so we first multiply by 100 before dividing the result by the rateInCents for each ticket. We are also relying on the SafeMath library for mul , div , and add as well as sub . We’re not getting into the reasons for that right now, but be aware that any arithmetic operation in a smart contract can have undesirable effects, and sometimes catastrophic data integrity issues — so we always check for overflow when performing math operations.

Back at the console, install zeppelin-solidity:

npm install zeppelin-solidity

And at the top of your file after pragma line & before contract GreatestShow :

import 'zeppelin-solidity/contracts/math/SafeMath.sol';

Then, inside the actual contract the first line should read:

using SafeMath for uint256; // adds helper functions to uint256

Ok. We’re ready to proceed! You have created your GreatestShow contract, you have a way of specifying the name of your ringMaster , we’re keeping track of the performances data structures represented by the Performance struct, and holding onto the number of availableSeats . To make sure that we can fill those seats, we make sure the payable fallback function is available so that when a customer sends us Ether from their account, we assign a value of tickets based on the amount they sent us, to their msg.sender address.

Let’s head back to the console and get ready for the magic to happen: