Recipe ID: hsts-r44
We offer blockchain introduction, Hyperledger for system admin, Ethereum, Solidity, Corda R3, Hyperledger for developers, blockchain cybersecurity and more classes in self-paced video format starting at $60. Click here to learn more and register. For complete self-paced blockchain training, visit our Complete Blockchain Development Training page.
The latest version of this tutorial along with all updated source codes is available via the below link:
  https://myhsts.org/blog/ethereum-dapp-with-evm-remix-golang-truffle-and-solidity-part2.html
 Ethereum is a general-purpose blockchain that is  more suited to describing business logic, through advanced scripts, also known  as smart contracts. Ethereum was designed with a broader vision, as a  decentralized or world computer that attempts to marry the power of the  blockchain, as a trust machine, with a Turing-complete contract engine.  Although Ethereum borrows many ideas that were initially introduced by bitcoin,  there are many divergences between the two.
    The Ethereum virtual machine and smart contracts  are key elements of Ethereum, and constitute its main attraction. In Ethereum,  smart contracts represent a piece of code written in a high-level language  (Solidity, LLL, Viper) and stored as bytecode in the blockchain, in order to  run reliably in a stack-based virtual machine (Ethereum Virtual Machine), in  each node, once invoked. The interactions with smart contract functions happen  through transactions on the blockchain network, with their payloads being  executed in the Ethereum virtual machine, and the shared blockchain state being  updated accordingly.
    
    For those who are not familiar with blockchain technology reading History  and Evolution of Blockchain Technology from Bitcoin article is strongly recommended. Also,  if you wish to learn and practice Hyperledger blockchain development, visit Comprehensive  Hyperledger Training Tutorials page to get the outline of our  Hyperledger tutorial articles. 
    We  have written two sets of tutorials to explore Ethereum and Solidity programming  in depth. First set covered the following nine recipes:
In  short, you learned about how to set up and configure Ethereum and develop  blockchain applications using Solidity programming language. We explored its  key components, including smart contracts and Web3.JS API via an Auction  Decentralized Application (DApp) step-by-step. 
    In  second set, we discuss more advance topics in Ethereum blockchain development  and solidity while building a Tontine DApp game step-by-step. Specifically, we  cover Truffle and Drizzle. For instance, we show you how a tool such as Truffle  can be an assistant in building, testing, debugging, and deploying DApps. In  summary, we are going to cover four main topics: 
The 2nd set consists of 8 recipes as follows:
IMPORTANT: Understanding and completing the first set of recipes are  required prior to working on second set of recipes.  
    In our first round of recipes, we learned a lot  about the Ethereum ecosystem, but we are yet to realize the full potential of  its different components. More precisely, we explored how Ethereum works, what  a decentralized application (DApp) is and how to build one, and also covered  the key concepts of Solidity  and web3.js. We then introduced some of the most  common smart contract design patterns (withdrawal from a contract, restricting  access, state machines), before ending  with a discussion of a contract’s cost optimization.
    To brush up your knowledge and skills, on second  round of recipes, we are going to build a Tontine DApp game. We will exploit  this example to explore new tools that are going to change the way you build DApps, and introduce  new Solidity features. 
In this walkthrough, we will discover how a tool such as Truffle can aid in building, testing, debugging, and deploying our DApp.
In Ethereum, contracts communicate between each other using message calls. Practically, a smart contract is able to communicate with another one that it deploys or with an instance of an existing contract. In Solidity, for both cases, we can declare a Cplayer instance as follows: Cplayer Tplayer. Let's discuss how contracts interact between Ethereum and Solidity.
To instantiate an existing contract, we need to  know its address. For example, in our contract, we will instantiate the Cplayer  contract in the Ctontine constructor as follows:
    constructor(address  _CplayerAddress) public { Tplayer = Cplayer(_CplayerAddress);
    } 
The Cplayer(_CplayerAddress);  expression will perform an explicit  conversion of the Cplayer type,  stating that "we know that the contract at the given address of _CplayerAddress is of the Cplayer type." It's worth  noting that instantiating a contract using  its address doesn’t imply the execution  of its constructor.
    The interaction with a deployed contract is a very  powerful feature as it allows code reusability, since deployed contracts can be  used like libraries. Furthermore, if we implement a pattern that enables us to  change the used contract, instantiation can help us avoid reusing faulty contracts by changing the contract address.
The second option is to deploy a new instance of a  given contract. To achieve that, Solidity provides the new  keyword, which can be used as  follows:
    contract  ContractA { uint256 x;
function  ContractA (uint256 y) payable { x = y;
    } 
    } 
contract ContractB {
    ContractA CAinstance = new ContractA(10);
    } 
As you can see, we can pass arguments when we create a contract, since the created contract has a constructor that accepts arguments. The new ContractA(arg) line will execute the created contract's constructor and return its address. Note that an instance of each smart contract is implicitly convertible to its address, and in Solidity we are not dealing with real objects as in OOP to represent contracts as we do for classes.
Moreover, you can send ether from your source  contract to the newly created contract using the .value() option, as follows:
    ContractA  CAinstance = (new ContractA).value(amount)(arg);
Once the instance is created, the caller contract can pass messages to call remote methods or to read or edit remote states. Let’s see how to perform such calls.
In our project, we have a Ctontine contract that  instantiates a Cplayer object.  As we presented in the game design, the player should sign up using the Cplayer  contract, and then join the  game using the Ctontine contract.  This implies that the Cplayer contract  manages the player details and that Ctontine needs to access them.
    In Ethereum, each contract has its own storage  space, which can’t be accessed directly or overridden by another  contract. Given the ContractA and ContractB  contracts, the former can only access  the storage of the latter by invoking a method (getter) that returns data from  the storage of ContractB.
You might be wondering, "What if we declare  states variables as public? Wouldn’t they be  accessible?" It's not important whether the variable is public  or not, as the public  specifier provides a free getter  function within the contract scope, and not external access. 
    Back in our contract code, if we try to  read the admin variable in the Ctontine contract from the Cplayer contract directly – Address Cplayer_admin = Tplayer.admin; – we’ll get the following message  error, even if admin is declared as public: 
    
  
So how do we solve this?
In the target contract, we should have a getter that reads for us and returns the intended value.
As was the case for reading contract storage, you cannot modify states of another contract without defining a setter function.
Let’s have a look at the following example:
    contract  ContractA { uint256 public state;
    function  setstate(uint _value) { state = _value;
    } 
    } 
contract ContractB{
    ContractA public OneInstance  = new ContractA(); function getstateA() public  {
    OneInstance.state = 12;  OneInstance.setstate(12);
    } 
    } 
The OneInstance.state = 12; line in the getstateA method will raise an error. We need instead to call the setstate() setter to update the state value.
The need for getters (read) and setters (update) in intra-contract interactions demonstrates the importance of the CRUD pattern.
Let’s get back to our game code. So far, in our Ctontine contract, we have declared the required states and our constructor is already defined. All we are missing is implementing the Ctontine contract methods.
In order to start the game, a player has to call the join() method while sending more than one ether to the Tontine contract. Therefore, in the Ctontine contract, we need to implement this function as follows:
function  join() public payable returns(bool) { require(Tplayer.exist(msg.sender),  "player doesn't exist"); require(msg.value >= 1 ether &&  Tpension[msg.sender] == 0, "send higher
    pension");
    Tpension[msg.sender] =  msg.value; Tplayer.EditPlayer(msg.sender, active_players.length);  active_players.push(Tplayer.getplayer(msg.sender)); Lindex +=  (active_players.length - 1); ping_time[msg.sender] = now;
    emit NewActivePlayerEv(msg.sender,  now); return true;
    } 
Let’s go over this implementation, line by line.
    First  of all, the join()  function is marked as payable  to allow the contract  to accept ether via  standard transactions. It is also defined as external, specifying that the method  has to be called from other  contracts or via transactions. We made this choice following the game design  and because an external function is cheaper than a normal public function.
The join() method implements the game rules. Thus, a player should be able to join the game if the following requirements are met:
If they fulfill the conditions, we save the supplied ether in the Tpension array.
    The Tplayer.EditPlayer(msg.sender, active_player.length); line edits the value of the id attribute  for the given player. We use this element to keep track of the index of each  player in the active player array. That will help us to know which case to  delete if we want to remove this player.
Then the active_player.push() function is used to add a new player into the 
    active_player array. 
We use a Lindex global state,  which sums up the index  values of the active players. Why? Because it will help us to know  the last surviving player’s index in the active  players array.
    The ping_time[msg.sender] = now; line initially stores the time  when the players  join the game as their first ping time. 
At the end of the function, we emit an ewActivePlayerEv(msg.sender,now) event to announce the signing of a new player.
So far, within this function, we have introduced a lot of new things related to intra-contract interaction. Let's again take a pause in writing the Ctontine contract and learn some new concepts. You can skip the next two sections if you want to concentrate on building the game.
In Solidity, you can call functions either internally or externally. Only the functions of the same contract can be called internally, whereas external functions are called by other contracts.
If you were to call a function from another contract, the EVM uses the CALL instruction, which switches the context, making its state variables inaccessible. In the following sections, we will discover two ways to call a function from another contract.
As we did in the Ctontine contract, the regular way to interact with other  contracts is to call (invoke) a function on a contract object (we borrow here  the OOP terminology). For example, we can call a remote function from a remote  contract, ContractA ,  as follows: ContractA.Remotefunction(arguments).
    But to be able to make the invocation this way, we  need to define (in the same Solidity file) an abstract form of ContractA. For instance, if we have a contract, ContractA, then  the code is as follows:
contract ContractA {
    function f(uint256 a, string s) payable returns  (bool) {
    //your code here return true;
    } 
    } 
    If this contract is deployed in the blockchain, let’s say under the 0x123456 address,  and we want to call the f() function within a caller contract, ContractB, then we have to include the abstract form of ContractA in  the ContractB file, then instantiate ContractA and  execute f(). Here is how  the ContractB contract file will look:
    contract ContractA {
    function f(uint256 a, string  s) payable returns (bool); function h() payable returns (uint);
    } 
contract ContractB{
    address ContractAaddress = 0x123456;
    ContractA ContractAInstance =  ContractA(ContractAaddress);
function g() returns (bool){
    return ContractAInstance.f(10,  "hello");
    } 
    } 
    If we invoke a payable function, we can specify the number of wei, as well as limit the amount of gas available  to the invocation using the .gas() and .value() special options, respectively: ContractAInstance.h.value(10).gas(800)();. 
    The parentheses at the end serve to receive the arguments needed  to perform the  call. If the function doesn’t accept any arguments, we keep them empty.
When the called  contract doesn't adhere to the ABI, we can't just use ContractAInstance.f();  or ContractA ContractAInstance = ContractA(0x123456) to define a new instance. 
    In this case,  we have to use the special low-level  call function, using  the following call structure:
contract_address.call(bytes4(sha3("function_name(arguments types)")), parameters_values)
In the previous  example, we could call f() with two arguments using ContractAaddress.call(bytes4(keccak256("f(uint256,string)")),  10, ”hello”);. 
    This is a sort  of tedious manual construction of the ABI function signature. However, things  are getting better with newer Solidity. Since release 0.4.22, the abi.encode(), abi.encodePacked(), abi.encodeWithSelector(), and abi.encodeWithSignature()  global functions have been defined to  encode structured data, therefore helping us to build a valid call, as follows: 
OneInstance.call(abi.encodeWithSignature("function_name(arguments types)")),parameters_values)
call  can be used along  with the .gas() and value()  methods to adjust the supplied gas and value in the call. 
  call returns true if the called function executes without exception.  Also, it will fire an exception if the call contract does not exist, or if it  throws an exception or runs out of gas. If we apply call to a contract without specifying a function name,  its fallback will be  executed (maybe that's why the fallback function doesn’t have a name).
For security reasons, there is a capped stipend of  2,300 gas that applies to internal sends (using the transfer() or send() methods) from one smart contract to another. Therefore, the triggered fallback has a  limited amount of gas to operate. However, the call function doesn’t have a similar limitation, which represents a  risk for your contract. In order to define the same security measure, you have  to set gas to 0 in your calls: contract_address.call.gas(0).value(xyz).
    Mind you, the call method or other low-level functions should be used  with care as they may cause some security issues if we deal with a malicious  contract.
After this long introduction about contract remote calls, let’s get back to our Ctontine contract.
After implementing the join() function, it’s time to define the ping() function, which will allow the player to update their activity, as follows:
function  ping() external returns(bool) { ping_time[msg.sender] = now;
    return  true;
    } 
There's nothing complex about this code. Each time ping() is called, we will store the current time returned by now as the new ping time. Players will not literally ping the contract as we do in a network, they will only send a transaction invoking the ping method to prove their activity.
The game logic enables a player to eliminate another unlucky opponent by  triggering the
  eliminate() method, which  we define as follows: 
  function  eliminate(address PlayerAddress)  external        returns(bool)  { require(now > ping_time[PlayerAddress] + 1 days);
  delete  Tpension[PlayerAddress];
  delete  active_players[Tplayer.getplayer(PlayerAddress).id]; Lindex -=  Tplayer.getplayer(PlayerAddress).id; eliminated_players.push(Tplayer.getplayer(PlayerAddress));  Tplayer.EditPlayer(msg.sender, 0); share_pension(PlayerAddress);
  emit  eliminatedPlayerEv(PlayerAddress); return true;
  } 
Take a close look, and I’m sure you’ll make sense of this code.
  The require(now > ping_time[PlayerAddress] + 1 days);  line  ensures that we can eliminate only players who didn’t ping the  contract within the last 24 hours. 
  This function will remove the eliminated player  from the active player list (active_players) and move it to the eliminated player list (eliminated_players.push). Then we set the player's ID to zero as it has been  removed from the active player list. Afterward, we call share_pension(), which will share the balance of the eliminated  player between the remaining active players. We end by firing an event, declaring the elimination of the player.
As you saw, in the previous function  we called share_pension() to share  the eliminated player’s deposit. Here’s its implementation:
  function  share_pension(address user) internal returns (bool) { uint256 remainingPlayers = remaining_players(); for(uint256 i  = 0; i < active_players.length; i++){
if  (active_players[i].Paddress != 0x00)
  Tpension[active_players[i].Paddress]  = Tpension[user] / remaining_players;
  } 
  return true;
} 
function  remaining_players() public view returns (uint256) { return  (active_players.length-eliminated_players.length);
  } 
  } 
We declare this function internal as it’s intended to be used only within the contract scope. As we can see, share_pension() shares the eliminated players’ balances between the remaining active players. This function has to allocate the Tpension[user]/remaining_players quotient to each active player. However, we are facing a problem here! Have you spotted it?
Handling the division in the previous scenario is  just the same as working with integer divisions, as Ethereum doesn’t adopt floating  point numbers. The division would result in a floor of the calculation with the  remainder discarded. For example, the division 17/3 equals 5, with the  remainder of 2 discarded. To fix this, we create a new method that does the  following:
  function calcul(uint a, uint b, uint precision)  public pure returns (uint)
  { 
  require(b != 0);
  return a * (10 ** (precision)) / b;
  } 
Note that the double asterisk, **, is a Solidity operator representing the exponentiation operation. In  our example, 10 is the base whereas precision is the exponent.
  If we divide 17 by 3 using the calcul() function, and we call the function with a precision of 5 (the number of digits after  the decimal point), it will output 566,666, which can be displayed to the  player as 5.66666. In this way, we can produce a float using integer division,  though it still requires that in the frontend you divide the result by the equivalent  value of (10 ** (precision)) to display  the floating-point number.
Therefore, in the share_pension() function, we substitute the quotient by performing the following:
Tpension[active_players[i].Paddress] = calcul(Tpension[user], remainingPlayers, 18);
At the final stage of the game, the last active player can claim their  reward by calling
  claimReward(), which we define as the following: 
  function  claimReward() external returns (bool) { require(remaining_players() == 1); active_players[Lindex].Paddress.transfer(address(this).balance); return  true;
  } 
I’m sure the this keyword has caught your attention more than the rest of the code. So what is it?
The this keyword in Solidity is pretty similar to this  in OOP,  and represents a pointer to the current contract, which is explicitly  convertible to an address. Moreover, all contracts inherit the members of address, thus it is possible to query the balance of the current contract using address(this).balance (you'll  find this.balance in  old code).
  As this returns the address of the current  contract, we can use it as follows:  address ContractAddress = this;. 
  this is also used to access internally a method declared  as external,  otherwise the compiler won’t recognize it. In that case, the function will be  called through a call message instead of being called directly via jumps.
Great, at this level, we’re nearly done with the game contracts. However, the code should be tested before we start working on the user interface side in our next recipe. I hope you didn’t forget how to use Truffle.
To conclude this recipe, we like to recommend our Learn Hands-on Blockchain Ethereum Development & Get Certified in 30 Hrs, and Become Blockchain Certified Security Architect in 30 hours courses to those interested in pursuing a blockchain development career. This recipe is written by Brian Wu who is our senior Blockchain instructor in Washington DC. His Blockchain By Example book is highly recommended for learning more about blockchain development.
  Hands-on Node.JS, MongoDB and Express.js Training
  Advance JavaScript, jQuery Using JSON and Ajax
 Learn  Hands-on Blockchain Ethereum Development & Get Certified in 30 Hrs
 Learn  Blockchain Hyperledger Development & Get Certified in 30 Hrs
  Become  Blockchain Certified Security Architect in 30 hours
 
 Blockchain Certified Solution Architect in 30 hours
 
  Introduction to Python Programming
    Object Oriented Programming with UML 
  
We offer private coding classes for beginners online and offline (at our Virginia site) with custom curriculum for most of our classes for $59 per hour online or $95 per hour in virginia. Give us a call or submit our Private Coding Classes for Beginners form to discuss your needs.