How to Get Event Information from Hedera Smart Contracts | Hedera Hedera Network Services Token Service Mint and configure tokens and accounts. Consensus Service Verifiable timestamps and ordering of events. Smart Contracts Run Solidity smart contracts. HBAR The Hedera network's native cryptocurrency. Insights How It Works Learn about Hedera from end to end. Explorers View live and historical data on Hedera. Dashboards Analyze network activity and metrics. Network Nodes Understand networks and node types. Devs Start Building Get Started Learn core concepts and build the future. Documentation Review the API and build using your favorite language. Developer Resources Integrations Plugins and microservices for Hedera. Fee Estimator Understand and estimate transaction costs. Open Source Hedera is committed to open, transparent code. Learning Center Learn about web3 and blockchain technologies. Grants Grants & accelerators for your project. Bounties Find bugs. Submit a report. Earn rewards. Ecosystem ECOSYSTEM Hedera Ecosystem Applications, developer tools, network explorers, and more. NFT Ecosystem Metrics Analyze on-chain and market NFT ecosystem metrics. CATEGORIES Web3 Applications Connect into the innovative startups decentralizing the web on Hedera. Enterprise Applications Learn about the Fortune 500 companies decentralizing the web on Hedera. Wallets & Custodians Create a Hedera account to manage HBAR, fungible tokens, and NFTs. Network Explorers Hedera mainnet and testnet graphical network explorers. Developer Tooling Third-party APIs, integrations, and plugins to build apps on Hedera. Grants & Accelerators Boost your project with support from the Hedera ecosystem. Partner Program Explore our partners to bring your vision into reality. Hedera Council Over 30 highly diversified organizations govern Hedera. Use Cases Hedera Solutions Asset Tokenization Studio Open source toolkit for tokenizing assets securely. Stablecoin Studio All-in-one toolkit for stablecoin solutions. Hedera Guardian Auditable carbon markets and traceability. Functional Use Cases Data Integrity & AI Reliable, secure, and ethically governed insights. Sustainability Enabling fair carbon markets with trust. Real-World Asset Tokenization Seamless tokenization of real-world assets and digital at scale. Consumer Engagement & Loyalty Mint, distribute, and redeem loyalty rewards. Decentralized Identity Maintain the lifecycle of credentials. Decentralized Logs Scalable, real-time timestamped events. DeFi Dapps built for the next-generation of finance. NFTs Low, fixed fees. Immutable royalties. Payments Scalable, real-time, and affordable crypto-payments. HBAR Overview Learn about Hedera's token, HBAR. Treasury Management Hedera’s report of the HBAR supply. Governance Decentralized Governance Hedera Council See the world's leading organizations that own Hedera. About Meet Hedera's Board of Directors and team. Journey Watch Hedera's journey to build an empowered digital future for all. Transparent Governance Public Policy Hedera's mission is to inform policy and regulation that impact the industry. Meeting Minutes Immutably recorded on Hedera. Roadmap Follow Hedera's roadmap in its journey to build the future. Resources Company What's New Partners Papers Careers Media Blog Technical Press Podcast Community Events Meetups Store Brand Navigation QUICKSTART How to Get Event Information from Hedera Smart Contracts technical Feb 09, 2022 by Ed Marquez Head of Developer Relations by Greg Scullard Lead Developer Advocate Events in Solidity provide a way to log things and actions that take place in your smart contracts. In this article, you will learn how to get human-readable event information from contract logs using transaction records and mirror nodes. You will use the Hedera JavaScript SDK and mirror node REST API with libraries like web3.js and ethers.js. Try It Yourself Get a Hedera testnet account This Codesandbox is already setup for you to try this example Remember to provide your testnet account credentials in the .env file And open a new terminal to execute index.js Get the code from GitHub Includes index.js, stateful.sol, abi.json, bytecode.json, and more. This repository implements this same example with other languages and libraries How Are Events Used? Here’s how you declare and emit events in Solidity: //Declare an Event event Deposit(address indexed _from, bytes32 indexed _id, uint _value); //Emit an event emit Deposit(msg.sender, _id, msg.value); Copy When an event is emitted, it stores the arguments in a special on-chain data structure called the transaction log. Logs are associated with the address of a contract; however, logs and their event data are not accessible from within contracts. Logs are composed of topics and data. When you use the attribute indexed for event arguments, they are added to the topics part of the log, not the data. Doing this can be useful because topics allow you to search for events. On the other hand, all arguments that don’t use the indexed attribute are added to the data part of the log. Access Event Information from a Hedera Contract The contract to deploy is called StatefulContract, and it is simply a getter-setter contract that changes and reads the state variable message, which is of type string. In addition, the contract has the event SetMessage that captures changes to the state variable. The contract looks like this: pragma solidity ^0.6.12; contract StatefulContract { // sample event event SetMessage(address indexed from, string message); // the message we're storing string message; constructor(string memory message_) public { emit SetMessage(msg.sender, message_); message = message_; } function set_message(string memory message_) public { emit SetMessage(msg.sender, message_); message = message_; } // return a string function get_message() public view returns (string memory messageOut) { messageOut = message; } } Copy Now, this entire example in JavaScript runs through the seven steps below, but we’ll focus only on steps six and seven: Deploy the contract on Hedera with a “Hello Hedera” message (this emits a SetMessage event) Query the contract for the current message value Set the contract message to “Hello again” (this emits a SetMessage event) Use a query to fetch the contract's current message value (get_message) Use a transaction to fetch the contract's current message value (get_message) Call set_message with the current date time as a parameter (this emits a SetMessage event) AND fetch the emitted event using a record Fetch all the events for the contract using a mirror node query Here is the console output when you run the entire example: Here is the main function that implements those seven steps: async function main() { // deploy the contract to Hedera from bytecode const contractId = await deployContract(); // query the contract's get_message function await queryGetMessage(contractId); // call the contract's set_message function await callSetMessage(contractId, "Hello again"); // query the contract's get_message function await queryGetMessage(contractId); // call the contract's get_message function await callGetMessage(contractId); // get call events from a transaction record await getEventsFromRecord(contractId); // get contract events from a mirror node await getEventsFromMirror(contractId); } Copy Get Event Information Using Transaction Records Let’s take a closer look at the function getEventsFromRecord (see below). This function sets the state variable, message, to the current date and time by calling the set_message function of the contract with the ContractExecuteTransaction() module. From the Solidity code, doing this emits a SetMessage event. A record of the transaction is then obtained because it contains the output of the function as well as events. The changes to the contract state variable are checked by calling the queryGetMessage function. Finally, the events contained in the record are decoded (parsed) using web3.js to get human-readable information. Note that both the data and topics from the event logging exists in record.contractFunctionResults.logs. async function getEventsFromRecord(contractId) { console.log(`\nGetting event(s) from record`); // calling "set_message" with the current date/time to generate a new event const newMessage = new Date().toLocaleString(); // generate function call with function name and parameters const functionCallAsUint8Array = encodeFunctionCall("set_message", [newMessage]); console.log(`Calling set_message to trigger new event`); // execute the transaction calling the set_message contract function const transaction = await new ContractExecuteTransaction() .setContractId(contractId) .setFunctionParameters(functionCallAsUint8Array) .setGas(100000) .execute(client); // a record contains the output of the function // as well as events, let's get events for this transaction const record = await transaction.getRecord(client); // query the contract's get_message function to witness update await queryGetMessage(contractId); // the events from the function call are in record.contractFunctionResult.logs.data // let's parse the logs using web3.js // there may be several log entries record.contractFunctionResult.logs.forEach((log) => { // convert the log.data (uint8Array) to a string let logStringHex = "0x".concat(Buffer.from(log.data).toString("hex")); // get topics from log let logTopics = []; log.topics.forEach((topic) => { logTopics.push("0x".concat(Buffer.from(topic).toString("hex"))); }); // decode the event data const event = decodeEvent("SetMessage", logStringHex, logTopics.slice(1)); // output the from address stored in the event console.log( `Record event: from '${AccountId.fromSolidityAddress(event.from).toString()}' update to '${event.message}'` ); }); } Copy Auxiliary Functions Below are the functions (and dependencies) used by the getEventsFromRecord function. Note that the usage of web3.js is shown in the last three functions to encode and decode function results, parameters, and events. async function queryGetMessage(contractId) { console.log(`\nget_message Query`); // generate function call with function name and parameters const functionCallAsUint8Array = encodeFunctionCall("get_message", []); // query the contract const contractCall = await new ContractCallQuery() .setContractId(contractId) .setFunctionParameters(functionCallAsUint8Array) .setQueryPayment(new Hbar(2)) .setGas(100000) .execute(client); let results = decodeFunctionResult("get_message", contractCall.bytes); console.log(results); } Copy function decodeFunctionResult(functionName, resultAsBytes) { const functionAbi = abi.find((func) => func.name === functionName); const functionParameters = functionAbi.outputs; const resultHex = "0x".concat(Buffer.from(resultAsBytes).toString("hex")); const result = web3.eth.abi.decodeParameters(functionParameters, resultHex); return result; } Copy function encodeFunctionCall(functionName, parameters) { const functionAbi = abi.find((func) => func.name === functionName && func.type === "function"); const encodedParametersHex = web3.eth.abi.encodeFunctionCall(functionAbi, parameters).slice(2); return Buffer.from(encodedParametersHex, "hex"); } Copy function decodeEvent(eventName, log, topics) { const eventAbi = abi.find((event) => event.name === eventName && event.type === "event"); const decodedLog = web3.eth.abi.decodeLog(eventAbi.inputs, log, topics); return decodedLog; } Copy Get Event Information Using Mirror Nodes Now let’s take a closer look at the function getEventsFromMirror (see below). This function introduces a delay of 10 seconds to allow transaction propagation to the mirror nodes. After the 10 seconds, a URL is created with the mirror node REST API (learn more about the mirror node API here) and the axios client is used to obtain the logs from the mirror query. Iterating through the logs is necessary in case there are multiple log entries, which is true in this case. Finally, decoding the events with the decodeEvent function is the last step before outputting a human-readable message to the console with information from each event. async function getEventsFromMirror(contractId) { const delay = (ms) => new Promise((res) => setTimeout(res, ms)); console.log(`\nGetting event(s) from mirror`); console.log(`Waiting 10s to allow transaction propagation to mirror`); await delay(10000); const url = `https://testnet.mirrornode.hedera.com/api/v1/contracts/${contractId.toString()}/results/logs?order=asc`; axios .get(url) .then(function (response) { const jsonResponse = response.data; jsonResponse.logs.forEach((log) => { // decode the event data const event = decodeEvent("SetMessage", log.data, log.topics.slice(1)); // output the from address and message stored in the event console.log( `Mirror event(s): from '${AccountId.fromSolidityAddress(event.from).toString()}' update to '${event.message}'` ); }); }) .catch(function (err) { console.error(err); }); } Copy To see the output of this function, check step seven in the console output image above. In addition, the Auxiliary Functions section shows the decodeEvents function and how it uses web3.js to decode the contract log. Now you know how to get event information from hedera smart contracts using transaction records and mirror nodes! For feedback on this article or future articles you would like to see, let us know via the Hedera Discord server. Check Out the Code and Try It Check out the code in GitHub Try the code in Codesandbox (remember to provide your account credentials in the .env file) Continue Learning about Smart Contracts How to Deploy Smart Contracts on Hedera – Part 2: A Contract with Hedera Token Service Integration Smart Contracts (Core Concepts - Hedera Documentation) What Are Smart Contracts? (Hedera Learning Center) Share This Back to blog What is gRPC, gRPC-Web, and Proxies? Ed Marquez Pragmatic Blockchain Design Patterns – Integrating Blockchain into Business Processes Michiel Mulders Zero Cost EthereumTransaction on Success: Hedera's New Fee Model for Relay Operators Oliver Thorn Hedera Adopts Chainlink Standard for Cross-Chain Interoperability To Accelerate Ecosystem Adoption Hedera Team Hedera Developer Highlights March 2025 Michiel Mulders Hedera Release Cycle Overview Ed Marquez View All Posts Sign up for the newsletter CONNECT WITH US Transparency Open Source Audits & Standards Sustainability Commitment Carbon Offsets Governance Hedera Council Public Policy Treasury Management Meeting Minutes LLC Agreement Node Requirements Community Events Meetups HBAR Telegram Developer Discord Twitter Community Support FAQ Network Status Developer Discord StackOverflow Brand Brand Guidelines Built on Hedera Logo Hedera Store About Team Partners Journey Roadmap Careers Contact General Inquiry Public Relations © 2018-2025 Hedera Hashgraph, LLC. All trademarks and company names are the property of their respective owners. All rights in the Deutsche Telekom mark are protected by Deutsche Telekom AG. All rights reserved. Hedera uses the third party marks with permission. Terms of Use  |  Privacy Policy