The Super Over Smart Contract 2.0 in Solidity

Rishikesh Kale
8 min readApr 29, 2020

--

This article is the second one in a series of articles about constructing a Smart Contract in Solidity. Let’s head towards Super Over Smart Contract Version 2.0.

Recommended : Read previous version -Super Over Smart Contract 1.0

“ Change is the only constant in life. ”

To update our Smart Contract its important to know the drawbacks of Super Over Smart Contract 1.0. Let’s discuss them.

The previous version had two functions maintainscore and winner, which updated the score of individual teams and declared the winner respectively.
However these two functions can be called in any order. There are no rules such as both the teams should have completed their batting quota and winning team can be decided only after both the teams have registered there respective score.
Also there is no restriction over cross updation of team score, which means that the second team’s score can be updated before completion of the innings of the first team and vice versa.

The previous version had two functions maintainscore and winner, which updated the score of individual teams and declared the winner respectively.
However these two functions can be called in any order. There are no rules such as both the teams should have completed their batting quota and winning team can be decided only after both the teams have registered there score.
Also there is no restriction over cross upadtion of team score, which means that the second team’s score can be updated before completion of the innings of the first team and vice versa.

To over come these drawbacks let us add the stages to the version one.
We add the enum for the stages and logic for modifying the stages within the functions. We will compile and run it and make sure it works as expected. Let’s define the stage as enum datatype.

enum Stage { Init , RegTeams , inningsTeamA , inningsTeamB ,   AnnounceResult }

Stage is four distinct stages, Init, RegTeams, inningsTeamA, inningsTeamB and AnnounceResult.

Stage Init           : The stage when program is compiled
and deployed.
Stage regTeams : The stage where both the teams are registered
for the match.
Stage inningsTeamA : The stage at which TeamA is batting.
Stage inningsTeamA : The stage at which TeamB is batting.
Stage Announceresult : The stage when both teams have completed
there batting quota and the winner
is to be declared.

1. The stage is initialized to Init at the time of deployment of the Smart Contract.
2. Then, in the constructor, the Init is changed to RegTeam stage.
3. After both the teams are registered, the stage changes to inningsTeamA.
4. After the batting quota of TeamA ends, the stage is set to inningsTeamB.
5. After the batting quota of TeamB ends, the stage is set to AnnounceResult.

Lets now move towards the programming part

pragma solidity ^0.5.9;
contract SuperOver{

address public umpire;
address public TeamA ;
address public TeamB ;

struct Team{
string name;
uint score;
uint balls ;
}

mapping(address => Team) teamdata;

Similar to previous version we have a struct Team, which stores the variables for storing team data. Along with the address variable umpire we have two additional variables of type address which stores the address of the teams.

Next we have a mapping that holds the data of the team for given address.

enum Stage { Init , RegTeams , inningsTeamA , inningsTeamB , AnnounceResult }Stage public stage = Stage.Init;

As stated above, to remove the mentioned drawbacks we add the enum for the stages and logic for modifying the stages within the functions. The variable stage is defined to be of this enum stage type, and it has been initialized to the Init stage. Actually Init is 0, RegTeams is 1, inningsTeamA is coded as 2, inningsTeamB is coded as 3 and AnnounceResult is coded as 4. Remember that when we are looking at the outputs in the web interface.

constructor() public
{
umpire = msg.sender;
stage = Stage.RegTeams;
}

Here in the constructor we have variable which stores the address value is initialized to msg.sender and stage is set to RegTeams.

function registerTeams(address addTeamA,string memory nameTeamA ,address addTeamB,string memory nameTeamB ) public
{
if (stage != Stage.RegTeams) return;
if(msg.sender != umpire) return;
TeamA = addTeamA;
teamdata[TeamA].name = nameTeamA;
TeamB = addTeamB;
teamdata[TeamB].name = nameTeamB;
stage = Stage.inningsTeamA;
}

In this version we are adding a new function registerTeams which registers the teams for the match. The first line of the function checks whether is it the regTeams stage or not. If stage is not regTeams then it prevents registration of any additional team thus preventing a new registration in between an ongoing match. After both the teams are registered the stage is set to inningsTeamA , which states that the first team can come out to bat.

Next we have the following two functions which maintains the scores of individual teams. The first line of both the functions checks if we are in the appropriate stage to update the date and the last line of the functions directs the code towards next stage if the batting quota of respective team is finished.

function maintainScoreTeamA(uint runs) public
{
if (stage != Stage.inningsTeamA) return;
if(msg.sender != umpire || teamdata[TeamA].balls > 6)
return;
teamdata[TeamA].score += runs;
teamdata[TeamA].balls++;
if(teamdata[TeamA].balls == 6 )
{ stage = Stage.inningsTeamB; }
}

function maintainScoreTeamB(uint runs) public
{
if (stage != Stage.inningsTeamB) return;
if(msg.sender != umpire || teamdata[TeamB].balls > 6)
return;
teamdata[TeamB].score += runs;
teamdata[TeamB].balls++;
if(teamdata[TeamB].balls == 6 )
{ stage = Stage.AnnounceResult; }
}

Lastly we have winner function which declares the winner of the match. The function first checks whether the match is completed or not by checking the current stage thus preventing any absurd result.

function winner() public view returns(string memory)
{
if (stage != Stage.AnnounceResult)
return "Match is yet to be finished";
if(teamdata[TeamA].score > teamdata[TeamB].score)
return teamdata[TeamA].name;
if(teamdata[TeamA].score == teamdata[TeamB].score)
return "Trophy is Shared";
else return teamdata[TeamB].name;
}

Its recommended to carefully analyze the function and understand its working line-by-line.

By the time you reach here your code must look like this :

pragma solidity ^0.5.9;
contract SuperOver{

address public umpire;
address public TeamA ;
address public TeamB ;

struct Team{
string name;
uint score;
uint balls ;
}

mapping(address => Team) teamdata;

enum Stage { Init , RegTeams , inningsTeamA , inningsTeamB , AnnounceResult }
Stage public stage = Stage.Init;

constructor() public
{
umpire = msg.sender;
stage = Stage.RegTeams;
}


function registerTeams(address addTeamA,string memory nameTeamA ,address addTeamB,string memory nameTeamB ) public
{
if (stage != Stage.RegTeams) return;
if(msg.sender != umpire) return;
TeamA = addTeamA;
teamdata[TeamA].name = nameTeamA;
TeamB = addTeamB;
teamdata[TeamB].name = nameTeamB;
stage = Stage.inningsTeamA;
}

function maintainScoreTeamA(uint runs) public
{
if (stage != Stage.inningsTeamA) return;
if(msg.sender != umpire || teamdata[TeamA].balls > 6)
return;
teamdata[TeamA].score += runs;
teamdata[TeamA].balls++;
if(teamdata[TeamA].balls == 6 )
{ stage = Stage.inningsTeamB; }
}

function maintainScoreTeamB(uint runs) public
{
if (stage != Stage.inningsTeamB) return;
if(msg.sender != umpire || teamdata[TeamB].balls > 6)
return;
teamdata[TeamB].score += runs;
teamdata[TeamB].balls++;
if(teamdata[TeamB].balls == 6 )
{ stage = Stage.AnnounceResult; }
}

function winner() public view returns(string memory)
{
if (stage != Stage.AnnounceResult)
return "Match is yet to be finished";
if(teamdata[TeamA].score > teamdata[TeamB].score)
return teamdata[TeamA].name;
if(teamdata[TeamA].score == teamdata[TeamB].score)
return "Trophy is Shared";
else return teamdata[TeamB].name;
}

}

Compiling the Solidity Smart Contract using Remix IDE

Copy paste the code into Remix IDE in the newly created file.

So let’s execute it and see it running.

After you compile and deploy the code you will be able to see the buttons of the functions we created along with the public variables we had declared in our Smart Contract.

Let’s analyze them one by one. On clicking the umpire button we should get the address of the account in which the Smart Contract was deployed.

Only umpire has the right to update the scores thus always make sure that the selected account belongs to umpire.

Let’s try checking if the contract shows any random result when we check the winner to verify if the contract have overcame the drawbacks or not.

Perfect!! We got the desired result. Now we can move towards team registration but before that we need to check in which stage we are.

We are progressing correctly. So its Stage 1, that means we can register the teams. Let’s do that.

Stage 1 : Team Registration

Select new address for the teams from here.

Enter the account address for both the teams by copy pasting one of the address from the available address and the enter the name of the teams as done below.

Before transacting make sure you get back to umpire’s address account.

Since the teams are now registered, the stage should be upgraded to next stage. You can check it by clicking the stage button.

Great!! We are on right path.

Stage 2 : Its time for Team A to set the target for Team B

As we did in previous version we will enter the runs ball-by-ball as per the score timeline given below.

Score Card of Team A

Note : After entering runs after each ball you need to transact it to add the runs to teams total score.

You can check the stage before proceeding towards next step.

Stage 3 : Can Team B chase the target set by Team A ?

Enter the runs for Team B as per the scoreboard below.

Score Card of Team B

Stage 4 : Its time to announce the winner

Before proceeding make sure you have entered the final stage.

And the winner is …..

Congratulations!! 🎉
You successfully designed and deployed the Super Over Smart Contract 2.0 which resolved the drawbacks of Super Over Smart Contract 1.0 to obtain the accurate result.

That wraps up the step-by-step article for now.

Other articles in this series:

Please check me out on LinkedIn as well, I would love to hear from you!

--

--