???? Strategies to Design Solidity Custom Event Topics for Listening on-chain Transactions
?? Guiding the Web3 Engineer to Tune into the Pulse of the Blockchain with Solidity Events and Node Provider's WebSocket Endpoint ??

???? Strategies to Design Solidity Custom Event Topics for Listening on-chain Transactions

Many enlightening articles are available on Solidity Events. Most are on theoretical aspects with intricate detail. These are beneficial for individuals acquainted with microservices architecture or those experienced in Solidity event usage for their extensive studies. However, these can be challenging for the newcomer Web3 developers.

For those striving to grasp the practical implementation of Solidity Events in dApp development, a significant gap arises, as these articles lack concrete simulations or practical demonstrations.

This is why this article is written. Here we will directly discuss some uses of the Solidity event which is used redundantly in most dApp development. I will also discuss the use of some simple techniques through which newcomers can easily design their events, list their topics precisely, and track transactions.


Scenario

Let's pose a scenario based on a typical use of dApp. By which we can understand one of the primary uses of Solidity Event.

Think of a dApp application that has a frontend, backend, and a Web 2.0 database. And the whole application is connected to a Smart Contract which is deployed on a blockchain network.

  1. An application user committed a crypto transaction from the frontend.
  2. The frontend passed the transaction to its integrated Smart Contract's function.
  3. As a response, the frontend will get a Transaction Hash from the Web3 Smart Contract.
  4. For keeping the log the frontend will call the backend API to store the Transaction Hash of blockchain.
  5. The backend will store the Transaction Hash in the Web 2.0 database. But the Transaction Status of Web 3.0 will be unknown to the backend database.

You might be wondering why the Web 3.0 Transaction Status is unknown? The answer lies in the development process for applications on a Proof-of-Stake (PoS) blockchain network. In this scenario, your transactions depend on miners for verification. While you receive a Transaction Hash as a receipt, the success or failure of the transaction is not immediate. (Ethereum/Polygon mainnet may take a couple of minutes to several hours to process a transaction)

As the on-chain transaction speed is dependent on network congestion, gas fees, and other factors, the frontend cannot keep the application's user waiting for an extended period, prioritizing a seamless user experience. Consequently, the application's backend stores the Transaction Hash, allowing it to continue the operation as a background task. This approach enables users to promptly resume using the application without unnecessary delays.

Problem Statement

In the scenario, we explored the flow of a dApp where the Web 2.0 component of the application retains the Web3 Transaction Hash. However, due to the time-consuming nature of the transaction, the application remains unaware of its on-chain status. To address this, a background task can be implemented to update the transaction status in the Web 2.0 database once the transaction is complete on-chain. This ensures that the application stays synced with the progress of the transaction.

Methodology

To sync the Web 2.0 application with on-chain the concept of Solidity Event can be helpful.

If we emit a Event inside Solidity Smart Contract's write function, it allows for the monitoring of transaction status with the help of that event's Topics associated with the same Transaction Hash generated with that write function.

But before going into more detail first we have to understand how Solidity Event Topics works. In a deployed Smart Contract event the first topic is default. Which is the zero-indexed topic. This topic is the hash value of the event name and its parameter names. So if a parameter name gets updated or gets added in an event the zero-indexed topic value of that event will get updated after the smart contract's re-deployment/proxy-deployment.

It's important to note that in Figures 1, 2, and 3 the default zero-indexed topic values differ from one another due to variations in their parameter names.

Event Listening Technique

As we have already described the basics of the Event and its Topics, let's understand the process of event listening technique from the Web 2.0 part of our dApp.

Fig 0: Node Provider Connection Details (Example: Alchemy)

For developing the dApp the Web3 developers first register their application in a Node Provider Services. Such as Alchemy, Infura, etc. There the developers will have three components. Here in Figure 0, it can be seen that in the Alchemy platform the first one is the API key, the second one is the HTTP endpoint, and the last one is an endpoint in WebSocket Protocol (wss).

Generally, the developers majorly use the HTTP endpoint for Smart Contract deployment and other read-write operations. But for monitoring a transaction status this WebSocket endpoint is helpful.

const { Network, Alchemy } = require("alchemy-sdk");

const settings = {
  apiKey: API_KEY, 
  network: Network.MATIC_MUMBAI, 
};
const alchemy = new Alchemy(settings);

listenSecondaryTrx(){
    const secondaryTopic = "0x53635ad006ccc6d......";
    const secondaryEndTopic = "0x000000000bc6....fa";
    const nftContractAddress = "0x.............";

    // Create the log options object.
    const SecondaryEvents = {
        address: nftContractAddress,
        topics: [secondaryTopic, secondaryEndTopic],
    };

    // Open the websocket and listen for events!
    alchemy.ws.on(SecondaryEvents, (txn) => {
        const eventObj = txn;
        // Logic of updating/syncing the Web 2.0 DB transaction status
    });
}        

In the provided code snippet, I've shared a source code that serves as a background task. Take this as an example where two different topics are declared as the starting and ending range, along with a smart contract address to listen to specific contract events emitted from the EVM. This example uses Alchemy's WebSocket endpoint, and the source code serves as an integration sample for the Alchemy SDK. (If you want to try our in your preferred Test Network find out the network name from Here.)

Event Topics

Fig1: Sample Solidity Events with Topic Range Issue

Here at Figure 1 there is an event named SecondaryRevenueDistribution with two topics. The first one is default and the second one is developer-defined. But this event has an issue. The developer-defined topic is a Token-Id which is not a constant value. It can be changed when the event is emitted. For this reason, this topic can not be considered for Real-Time listening. The reason will be described in Figure 2.

In Figure 1 there is another event named LogFeeTransfer which is an inherited event from an ERC standard contract. In Smart Contract development this is a common case where developers will find different events are emitted from different ERC contracts. So if the developers don't set the specific start and end topic for Real-Time listening to their transaction events, the call can be triggered from a different write function.

This is particularly relevant because these ERC events are utilized in various internal and public functions (Example: LogFeeTransfer). For instance, the SecondaryRevenueDistribution event only specifies a starting topic, without defining the range for the ending. Consequently, the LogFeeTransfer's topic will also be also listened if any other function emits it.

Fig2: Sample Solidity Event with Inappropriate Topic Range

To overcome that issue another topic was also added at index-2 in Figure 2. As the topic value is the Smart Contract address, we can consider this as constant. But this will cause another issue. Between the two topics (index 0 and 2) there is another topic at index-1 which is Token Id. Its value can be dynamic. As a result, the given background task's code snippet source code will fail to listen to the Smart Contract transactions for this specific event.

Fig3: Sample Solidity Event with Appropriate Topic Range

A good example of appropriately designing the event topic is illustrated in Figure 3. Here, both the starting and ending topics are sequentially placed, with the starting topic at index-0 and the ending topic at index-1. Utilizing these two indexes as topic listening ranges ensures the Web 2.0 background task functions seamlessly.

So these are the common pitfalls developers often face during event listening. From this case a question can be raised: how can a custom topic be created for events?

event SecondaryRevenueDistributed(
    address indexed platformAddress,
    uint256 indexed tokenId,
    uint256 platformFee,
    uint256 hotelFee,
    uint256 sellerFee,
    uint256 totalPaid
);        

In the provided code snippet, the raw source code of the event from Figure 3 is visible. Notably, the `indexed` keyword is utilized as an attribute before platformAddress. With this indexed attribute, platformAddress is treated as a topic with an index of 1 in the Ethereum Virtual Machine (EVM), where index 0 is reserved for the event name and its parameter hash (Figure 3).

The event-indexing technique holds significance not only for event listening but also for querying within a Subgraph. When a Smart Contract is integrated into The Graph service and configured as its own Subgraph, Web3 developers have the flexibility to design their schema. Leveraging the topic indexing technique becomes valuable for querying diverse data based on various indexed references. In essence, Subgraphs serve as instructions for indexers, enabling efficient data retrieval for decentralized applications.

When you are using the custom Topics for listening through the WebSocket, make sure the value is in Hex format.

Conclusion

In summary, Solidity events are vital for real-time transaction monitoring in dApps. Common mistakes, such as overlooking proper event topic indexing, can hinder developers. A well-designed event topic, with careful indexing, is crucial. It not only ensures effective real-time transaction listening but also facilitates seamless integration with SubGraphs. This approach empowers developers to build dApps with efficient transaction monitoring and advanced SubGraph querying capabilities, enhancing the overall decentralized ecosystem.



要查看或添加评论,请登录

Md. Ariful Islam的更多文章

社区洞察

其他会员也浏览了