Skip to main content

Try it Live

Run EventLog examples in the interactive playground

    Topic0 Semantics

    Non-anonymous events: Topic0 is the keccak256 hash of the event signature:
    import { Hash } from 'tevm';
    
    // Transfer(address,address,uint256)
    const transferSig = Hash(
      keccak256(new TextEncoder().encode('Transfer(address,address,uint256)'))
    );
    
    console.log(Hash.toHex(transferSig));
    // 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
    
    Anonymous events: Topic0 is the first indexed parameter (NOT the signature):
    event AnonymousTransfer(
      address indexed from,
      address indexed to,
      uint256 indexed tokenId
    ) anonymous;
    
    import { EventLog } from 'tevm';
    
    const anonymousLog = EventLog({
      address: contractAddress,
      topics: [
        fromHash,    // topic0 = first indexed param (from)
        toHash,      // topic1 = second indexed param (to)
        tokenIdHash, // topic2 = third indexed param (tokenId)
      ],
      data: Bytes(),
    });
    
    const topic0 = anonymousLog.getTopic0();
    // Returns fromHash, NOT event signature
    

    Usage Patterns

    Identifying Event Type

    import { EventLog, Hash } from 'tevm';
    
    const TRANSFER_SIG = Hash('0xddf252ad...');
    const APPROVAL_SIG = Hash('0x8c5be1e5...');
    
    function identifyEvent(log: EventLog): string {
      const sig = log.getTopic0();
      if (!sig) return 'unknown';
    
      if (Hash.equals(sig, TRANSFER_SIG)) return 'Transfer';
      if (Hash.equals(sig, APPROVAL_SIG)) return 'Approval';
      return 'unknown';
    }
    
    const eventType = identifyEvent(log);
    console.log(`Event type: ${eventType}`);
    

    Filtering by Signature

    import { EventLog, Hash } from 'tevm';
    
    const TRANSFER_SIG = Hash('0xddf252ad...');
    
    // Find all Transfer events
    const transferLogs = allLogs.filter(log => {
      const sig = log.getTopic0();
      return sig && Hash.equals(sig, TRANSFER_SIG);
    });
    
    console.log(`Found ${transferLogs.length} Transfer events`);
    

    Validating Event Structure

    import { EventLog, Hash } from 'tevm';
    
    function validateTransferLog(log: EventLog): boolean {
      const sig = log.getTopic0();
      if (!sig) {
        console.error('Log missing signature');
        return false;
      }
    
      if (!Hash.equals(sig, TRANSFER_SIG)) {
        console.error('Not a Transfer event');
        return false;
      }
    
      if (log.getIndexedTopics().length !== 2) {
        console.error('Expected 2 indexed parameters');
        return false;
      }
    
      return true;
    }
    

    Computing Event Signature

    import { Hash } from 'tevm';
    
    function eventSignature(declaration: string): Hash {
      const bytes = new TextEncoder().encode(declaration);
      return Hash(keccak256(bytes));
    }
    
    // ERC-20 events
    const TRANSFER = eventSignature('Transfer(address,address,uint256)');
    const APPROVAL = eventSignature('Approval(address,address,uint256)');
    
    console.log('Transfer:', Hash.toHex(TRANSFER));
    console.log('Approval:', Hash.toHex(APPROVAL));
    

    Empty Topics Array

    If topics array is empty, getTopic0() returns undefined:
    import { EventLog, Address } from 'tevm';
    
    const emptyLog = EventLog({
      address: Address.zero(),
      topics: [],
      data: Bytes(),
    });
    
    const topic0 = emptyLog.getTopic0();
    console.log(topic0); // undefined
    

    See Also