Skip to content
On this page

BUILDING OUR GAMESTAT SMART CONTRACT PART 2

We're now ready to develop the Gamestats.ts file located in the assembly directory which contains the core smart contract logic of our dApp. Let's quickly recap the logical behavior:

  1. Gamestats.ts contains the core business logic and uses an on-chain database to manage information about the winners. It also sends a mint command to the reward token contract based on the current game's winner.

  2. On chain storage, such as player information, game statistics, and leaderboard information are stored on chain based on the logic coded into the GameStatsStorage.ts, LeaderboardStorage.ts, MetadataStorage.ts and PlayerStorage.ts files.

In summary, we have one file to manage the logic (Gamestats.ts), and several files (GameStatsStorage.ts, LeaderboardStorage.ts, MetadataStorage.ts, and PlayerStorage.ts) to manage on-chain state. This is a common framework among smart contracts no matter what language is used.

BUILD OUR GAMESTAT CONTRACT (PART 1: EXPORT CLASS)

Now that we generally understand the organization of our code, we'll deep dive into the logic behind our dApp's Gamestats.ts code. The full code can be found here: https://github.com/koinos/1-week-challenge/blob/master/contracts/game-stats/assembly/Gamestats.ts

Our Gamestat.ts file contains an exportable class that contains

_contractID

In most cases, the developer will not know which wallet address their contract will be uploaded to. Since the wallet address is necessary in many situations, we create a variable called _contractID of Uint8Array type and call the System class from the @koinos/sdk-as module. The System class allows us to communicate with the blockchain itself (such as identifying the address) so it is an important class to understand. Read more about the System class here: https://koinos.github.io/koinos-sdk-as/modules/System.html

_metadataStorage, _playersStorage, _gameStatsStorage & _leaderboardStorage

Since we're storing information on-chain, we'll need to instantiate the memory state first. Recall in Module 7: Managing Storage Space on Chain how to do this. We simply instantiate the memory within our export statement.

initialize(args: gamestats.initialize_arguments): gamestats.empty_message {}

The initialize entry point is useful in many contracts to inject data necessary for the contract to function. Our use case is to inject the address of the reward token. To do this we use System.requireAuthority to ensure that no one but the contractId (itself) can define the reward token.

We also use System.require to check if this initialization has already been completed because we only want it to be done once.

submit_game_stats(args: gamestats.submit_game_stats_arguments): gamestats.empty_message {}

The majority of the Gamestat logic is located at this entry point. Here we call the database to create or grab objects and then store various game statistics such as the gameid, the leaderboard, and the winner's address.

**PRO TIP!**Assembly Script can overflow and underflow when performing mathematical operations using certain types of number systems such as u64. When you are not certain of the maximum value that your function will reach, it is advisable to use SafeMath which is provided to us in the @koinos/sdk-as module. Beware that SafeMath requires more Mana than built-in mathematical operations provided by Assembly Script, so use it only when you are handling sensitive information, such as incrementing the gameId which is involved in the minting of the reward token.

With all of the databases updated, we submit the data to game_stats.

Lastly, we mint our token for the winner. To do this, we use the Token helper which we imported from @koinos/sdk-as, see more information here: https://koinos.github.io/koinos-sdk-as/classes/Token.html.

Note: The token contract is based on a standard so we know which entry points are available.

The minting uses System.require to ensure that the game_stats contains the winner and the number of tokens to be rewarded, otherwise, it returns a fail message.

get_player_info(args: gamestats.get_player_info_arguments): gamestats.player_object {}

Used by the front end to display certain types of information.

get_leaderboard(args: gamestats.get_leaderboard_arguments): gamestats.get_leaderboard_result {}

Used by the front end to display certain types of information.

get_games_stats( args: gamestats.get_games_stats_arguments): gamestats.get_games_stats_result {}

Used by the front end to display certain types of information.

CONCLUSION

Our Gamestats.ts file is now ready for compilation! Next, we'll review our reward token contract.