Search code examples
blockchainsolidityweb3js

how likely is it to miss a solidity event?


Hi i am making a finance application that depends on Events from blockchain, Basically i update my database based on Events i receive using web3js, and when user asks i sign with private key for the contract to be able to give user Money.

My only concern is can i depend on events? like can there be a case where i miss events?

here is my code for doing so :

    const contract = new web3.eth.Contract(abi, contract_address)
    const stale_keccak256 = "0x507ac39eb33610191cd8fd54286e91c5cc464c262861643be3978f5a9f18ab02";
    const unStake_keccak256 = "0x4ac743692c9ced0a3f0052fb9917c0856b6b12671016afe41b649643a89b1ad5";
    const getReward_keccak256 = "0x25c30c62c42b51e4f667b70ef60f1f683c376f6ace28312ed45a40665e01af37";

    let userRepository: Repository<UserData> = connection.getRepository(UserData);
    let globalRepository: Repository<GlobalStakingInfo> = connection.getRepository(GlobalStakingInfo);
    let userStakingRepository: Repository<UserStakingInfo> = connection.getRepository(UserStakingInfo);
    let transactionRepository: Repository<Transaction> = connection.getRepository(Transaction);

    const topics = []

    web3.eth.subscribe('logs', {
            address: contract_address, topics: topics
        },
        function (error: Error, result: Log) {
            if (error) console.log(error)
        }).on("data", async function (log: Log) {


            let response: Boolean = false;
            try {
                response = await SaveTransaction(rpc_url, log.address, log.transactionHash, transactionRepository)
            } catch (e) {
            }


            if (response) {
                try {
                    let global_instance: GlobalStakingInfo | null = await globalRepository.findOne({where: {id: 1}})
                    if (!global_instance) {
                        global_instance = new GlobalStakingInfo()
                        global_instance.id = 1;
                        global_instance = await globalRepository.save(global_instance);
                    }
                    if (log.topics[0] === stale_keccak256) {
                        await onStake(web3, log, contract, userRepository, globalRepository, userStakingRepository, global_instance);
                    } else if (log.topics[0] === unStake_keccak256) {
                        await onUnStake(web3, log, contract, userStakingRepository, userRepository, globalRepository, global_instance)
                    } else if (log.topics[0] === getReward_keccak256) {
                        await onGetReward(web3, log, userRepository)
                    }
                } catch (e) {
                    console.log("I MADE A BOBO", e)
                }

            }
        }
    )

The Code works and everything, i am just concerned if i could maybe miss a event? cause finance is related and people will lose money if missing event is a thing. Please advise


Solution

  • You can increase redundancy by adding more instances of the listener connected to other nodes.

    And also by polling past logs - again recommended to use a separate node.

    Having multiple instances doing practically the same thing will result in multiplication of incoming data, so don't forget to store only unique logs. This might be a bit tricky, because theoretically one transaction ID can produce the same log twice (e.g. through a multicall), so the unique key could be a combination of a transaction ID as well as the log index (unique per block).