Try โ€‚โ€‰HackMD

Building Azura Chain and Gaming Application

Create an EVM-compatible Azura Chain

To build our Azura Chain and make it EVM-compatible on Cosmos Network, we will develop the custom EVM module in our project, since Cosmos SDK does not provide EVM modules by default. Azura Chain allows users to deploy Ethereum-compatible smart contracts on Azura Chain for smooth execution without modification.

Azura Technical Architecture

This figure shows the technical architecture of Azura. It helps explain how Azura works and functions technically.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More โ†’
Azura Technical Architecture

At the top layer, it shows that Azura will utilizes some Cosmos SDK standard modules, such as Auth, Bank, Distribution, Governance, NFT, Staking, IBC, etc. Moreover, some custom modules will be developed by Azura like EVM and other gaming modules as needed. These modules interface with the ABCI layer, which facilitates communication between the application logic and the consensus engine. At the bottom layer, the Tendermint Consensus (CometBFT) mechanism ensures consensus across the blockchain network.

Here are the summarized steps to build Azura Chain on Cosmos:

  1. Initialize Blockchain: Utilize Cosmos SDK and Ignite CLI to initialize the blockchain, and setup a genesis account to create, sign and validate the transactions.
  2. Extend Functionalities: Append and develop extra modules (i.e., Cosmos SDK standard modules and custom modules for the gaming ecosystem) to extend the functionality for Azura Chain. Please see the next section for more details.
  3. Launch Blockchain: Activate the blockchain to begin operations, allowing the deployment and interaction with Solidity smart contracts on Azura Chain.
  4. Deploy Smart Contracts: Deploy implemented Solidity smart contracts, running familiar Ethereum-based applications and protocols.

The key features and supports of Azura Chain are summarized as follows:

  • EVM Compatibility: Azura Chain enables the execution of Ethereum smart contracts without modification.
  • Client Compatibility: Developers can use the existing Ethereum development tools and libraries like Ethers.js and Web3.js.
  • Cosmos SDK Integration: Azura inherits the modular architecture and scalability benefits of the Cosmos ecosystem.
  • IBC Support: Smart contracts on Azura Chain can interact with other chains through the IBC protocol.

Standard and Custom Modules on Azura Chain

Azura Chain features a set of modules for functionality, leveraging both its own and Cosmos SDK modules. The modules utilized or created by Azura Chain are listed below.

Module Description Key Features
Auth Manages account, transaction authentication / authorization * Secure identity management
* Transaction validation
Bank Handles basic token operations * Transfers between accounts
* Minting, burning, supply
Governance Enables on-chain governance mechanism * Proposal submission
* Voting and decision-making
NFT Supports creation, management, transfer of NFT * Essential for applications requiring unique digital asset representation
Staking Implements Proof-of-Stake consensus mechanism * Allows validators to stake tokens and earn rewards
Distribution Manages the distribution of staking rewards * Fair and transparent reward allocation to validators / delegators
IBC Enables interoperability between different blockchains * Cross-chain token transfers
* Inter-chain communications
EVM Enables Ethereum compatibility on Cosmos Nework * EVM-compatible smart contracts deployment & interaction support

Here are the gaming custom modules provided by Azura. For more details about these modules, please refer to the Azura Custom Gaming Modules section.

Gaming Module Description
Player Profiles Stores player statistics, achievements, and rankings
Matchmaking System for finding and creating multiplayer game matches
Asset Management NFT-like functionality for in-game assets
supporting minting, burning, and transfers
Game State Management Efficient storage and retrieval of game states, including saving and loading game progress
Random Number Generation Integrates a Verifiable Random Function (VRF) and transparent randomness
Governance Integration Enables on-chain governance of game parameters and rules
State Channels Off-chain gameplay with periodic on-chain settlements
Interoperability Uses IBC to support cross-chain asset transfers and game interactions
Gas Optimization Features to optimize gas costs for frequent game actions
AI Integration Provides hooks to integrate AI services for NPC behavior, dynamic difficulty adjustment, etc.

Extend Functionalities - Modules with Azura's Logic

To follow the specific structure of Cosmos SDK modules, Azura should create new modules within the x directory in the repository. In Cosmos SDK-based projects, including Azura, the x directory is a convention for organizing and naming directories that contain custom modules. It helps distinguish between the SDK's core modules and those added by Azura for specific functionalities.

Inside the x directory, each custom module typically has its own directory named after the module. These custom modules can introduce new features, manage application-specific states, handle custom messages, and define unique application logic (i.e., game logic) beyond the standard Cosmos SDK modules. In a new module's directory, there are several default subdirectories, such as client, keeper, module, types, and more.

azura/
โ””โ”€โ”€ x/
    โ””โ”€โ”€ azura_custom_module/
        โ”œโ”€โ”€ client/
        โ”œโ”€โ”€ keeper/
        โ”œโ”€โ”€ module/
        โ”œโ”€โ”€ simulation/
        โ”œโ”€โ”€ types/
        โ”œโ”€โ”€ docs/
        โ””โ”€โ”€ ...

Azura will implement various components for a custom module:

  • client: Manages user interactions with the Azura Chain node through multiple interfaces: CLI, REST API, and gRPC.
  • keeper: Defines methods for accessing and modifying the module's state, serving as an interface between state and game logic.
  • module: Integrates the custom module into the Cosmos SDK application, defining routes, handlers, and overall module structure.
  • simulation: Simulates tests to evaluate module behavior under various conditions.
  • types: Contains definitions for data structures used throughout the module, including messages, queries, states, and parameters.
  • docs: Contains documents describing the module's design, functionality, and usage.
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More โ†’
Custom Module Interaction Flow for Azura

This diagram outlines a simplified interaction flow of a custom module in the Cosmos SDK for Azura, demonstrating how a game message is processed from different interfaces to handling the response.

  • Send Game Message: The process begins with a game message being sent from the user interfaces (CLI, REST, or gRPC) to the Client component.
  • Handle Game Message: The Client then forwards the message to the Module for routing and handling, based on the defined messge type.
  • Process Game Logic: The Module interacts with the Keeper, which carries out the necessary game logic and state transition rules using the received message.
  • Response Result: The processed result is then returned from the Keeper back through the Module and Client to the original user interfaces.

To explain this more practically, a simplified implementation example is presented in the next section: Gaming Logic Implementation on Azure Chain.

After creating and defining a new custom module, additional steps are required after the implementation, such as:

azura_chain/
โ”œโ”€โ”€ x/
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ app.go
โ”‚   โ”œโ”€โ”€ ibc.go
โ”‚   โ””โ”€โ”€ ...
โ”œโ”€โ”€ cmd/
โ”‚   โ”œโ”€โ”€ azurad/
โ”‚   โ””โ”€โ”€ ...
โ”œโ”€โ”€ proto/
โ””โ”€โ”€ ...
  • Register Module: Register the new module within the application constructor in app/app.go, which is the main entry point for defining and configuring the Cosmos SDK application.
  • Add Module CLI Commands: Extend the CLI commands in cmd/azurad/cmd/commands.go for interacting with the module (azurad is the abbreviation for Azura Daemon, which is a customized Azura CLI).
  • Update Protobuf Files: Update the files in proto if the new module defines new message types, queries, or state structures.

Note that the app/ibc.go file handles the setup and configuration of IBC module within the application.

Example - Game Logic Implemention on Azura Chain

At the implementation level, there are two approaches to executing game logic on Azura Chain. One approach is to define the logic directly on the chain, while the other is to deploy EVM-compatible smart contracts as the logic on the chain. To easily understand the implementation of game logic on Azura Chain, consider the example of a simple custom module for gaming called Game State (module named gamestate) presented in the following subsections.

Approach 1: Define Game Logic on Azura Chain

Define the Messages and Parameters

As mentioned earlier, the directory x/gamestate/types defines the messages, queries, states, and parameters used by the module. In messages.go, we define the messages and parameters needed for the game.

// src: x/gamestate/types/messages.go package gamestate const ( ModuleName = "gamestate" StoreKey = ModuleName ) // Represents the game state type GameState struct { PlayerID string Score int } // Defines the SaveGame message type MsgSaveGame struct { PlayerID string Score int }

where ModuleName and StoreKey are constants used to identify the module and its storage key in the Cosmos SDK. GameState struct represents the core data of a game state, containing a PlayerID (string) and a Score (integer). MsgSaveGame struct defines the message structure for saving a game state. It mirrors the GameState structure and is used as the input for transactions to save game states.

Define the Keeper

As mentioned earlier, the directory x/gamestate/keeper handles game logic and state transition rules. It manages the game state, including the ID and score of the player, as defined in keeper.go.

// src: x/gamestate/keeper/keeper.go package gamestate import ( "x/gamestate/types" // import `types` as mentioned sdk "github.com/cosmos/cosmos-sdk/types" "encoding/json" ) type Keeper struct { storeKey sdk.StoreKey } func NewKeeper(storeKey sdk.StoreKey) Keeper { return Keeper{storeKey: storeKey} } // Function to store a game state func (k Keeper) SetGameState(ctx sdk.Context, state GameState) error { store := ctx.KVStore(k.storeKey) value, err := json.Marshal(state) if err != nil { return err } store.Set([]byte(state.PlayerID), value) return nil } // Function to retrieve a game state func (k Keeper) GetGameState(ctx sdk.Context, playerID string) (GameState, bool) { store := ctx.KVStore(k.storeKey) value := store.Get([]byte(playerID)) if value == nil { return GameState{}, false } var state GameState err := json.Unmarshal(value, &state) if err != nil { return GameState{}, false } return state, true }

where Keeper struct manages the module's state storage, holding a storeKey for accessing the module's storage. NewKeeper is a constructor for creating a new Keeper instance. SetGameState stores a GameState in the module's storage. It serializes the state to JSON format and uses the PlayerID as the key. GetGameState retrieves a GameState from storage using the PlayerID. It deserializes the JSON data and returns the state indicating whether the state was found.

Define Message Handler

After we have defined the messages, parameters and keeper, the next step involves setting up a message handler. This handler will be responsible for processing the message MsgSaveGame in module.go.

// src: x/gamestate/module/module.go package gamestate import ( "x/gamestate/keeper" // import `keeper` as mentioned "x/gamestate/types" // import `types` as mentioned sdk "github.com/cosmos/cosmos-sdk/types" ) // Function to create a new handler for gamestate module messages func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { case MsgSaveGame: return handleMsgSaveGame(ctx, k, msg) default: return sdk.ErrUnknownRequest("Unknown message type").Result() } } } // Function to handle MsgSaveGame messages func handleMsgSaveGame(ctx sdk.Context, k Keeper, msg MsgSaveGame) sdk.Result { state := GameState{ PlayerID: msg.PlayerID, Score: msg.Score, } err := k.SetGameState(ctx, state) if err != nil { return sdk.ErrInternal("failed to save game state").Result() } return sdk.Result{Events: ctx.EventManager().Events()} }

where NewHandler creates a new handler function for processing module messages. It uses a switch statement to route different message types to their respective handlers. handleMsgSaveGame is the specific handler for MsgSaveGame messages. It creates a GameState from the message and uses the Keeper to save it, which the function SetGameState executes the logic of Game State in keeper.go.

Approach 2: Deploy Contracts with Game Logic to Azura Chain

This approach is quite different from the Cosmos SDK module-based implementation when using smart contracts. The game logic included in the contract defines, stores, and retrieves the game state. Here is a simplified smart contract example of GameState module.

// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract GameStateModule { // Defines the game state structure struct GameState { uint256 score; bool exists; } // Represents the game states (PlayerID => GameState) mapping(uint256 => GameState) private gameStates; // Function to store a game state function saveGameState( uint256 _playerId, uint256 _score ) external { gameStates[_playerId] = GameState(_score, true); } // Function to retrieve a game state function getGameState( uint256 _playerId ) external view returns (uint256, bool) { GameState memory state = gameStates[_playerId]; return (state.score, state.exists); } }

After implementing and compiling this Solidity smart contract, we can proceed by deploying them to the Azura Chain. The deployment and interaction process will follow the same steps and methods on Ethereum.