A comprehensive testing ground for blockchain event indexing, featuring a Solidity smart contract that demonstrates every possible Ethereum event type and structure. This project serves as a reference implementation and testing framework for blockchain event indexers.
This project provides a test environment with a smart contract (SomeContract.sol
) that emits various types of events, ranging from simple value types to complex nested structures. It's specifically designed to help test and validate event indexing systems by covering all possible Ethereum event scenarios.
Basic value types (uint, bool, string, address) Fixed-size types (bytes1, bytes32) Signed integers (int256, int64) Enum types
Fixed-size arrays (uint64[3]) Dynamic arrays (uint64[])
The project includes various struct combinations: Structs with arrays (both fixed and dynamic) Nested structs Structs containing fixed-size struct arrays Structs containing dynamic struct arrays
contracts/
: Contains the Solidity smart contract
test/
: Contains test files for event emission and ABI testing
Post compilation:
typechain/
: TypeChain integration for type-safe contract interactions
artifacts/
: Hardhat artifacts (abi etc)
- Hardhat for Ethereum development environment
- TypeScript for type-safe development
- Ethers.js (v5) for Ethereum interactions
- TypeChain for typed contract interfaces
The following test cases are covered in the codebase:
Event Name / Test Name | JSON Representation | Description |
---|---|---|
SimpleEvent | { "num64Value": 1, "boolValue": true, "stringValue": "3", "addrValue": "0x0000000000000000000000000000000000000123", "bytes1Value": "0x04", "bytes32Value": "0x0000000000000000000000000000000000000000000000000000000000000005", "int256Value": 6, "int64Value": 7, "someEnum": 2 } |
Tests the emission of a simple event with various data types. |
EventWithFixedArray | { "uint64Array": [1, 2, 3] } |
Tests the emission of an event with a fixed-size array of uint64 . |
EventWithDynamicArray | { "dynamicArray": [1, 2, 3, 4, 5, 6] } |
Tests the emission of an event with a dynamic array of uint64 . |
EventWithStructWithArrays | { "theStruct": { "uint64Array": [1, 2, 3], "dynamicArray": [1, 2, 3, 4, 5, 6] } } |
Tests the emission of an event containing a struct with both fixed and dynamic arrays. |
EventWithStructWithNestedStruct | { "theStruct": { "simpleStruct": { "a": 1, "b": 2 } } } |
Tests the emission of an event containing a struct with a nested struct. |
EventWithStructWithFixedStructArray | { "theStruct": { "structArray": [ { "a": 1, "b": 2 }, { "a": 1, "b": 2 } ] } } |
Tests the emission of an event containing a struct with a fixed-size array of structs. |
EventWithStructWithDynamicStructArray | { "theStruct": { "dynamicStructArray": [ { "a": 1, "b": 2 }, { "a": 3, "b": 4 } ] } } |
Tests the emission of an event containing a struct with a dynamic array of structs. |
First, install the project dependencies:
# Install as a dependency
npm install solidity-event-test-suite
# Install globally to use CLI
npm install -g solidity-event-test-suite
To compile the project and generate TypeChain files, run:
npx hardhat compile
Before deploying, make sure to start a local Hardhat node:
npx hardhat node
To deploy the contract to the local network:
npx hardhat run scripts/deploy.ts
This will deploy SomeContract
and output its deployed address.
To run tests (ensure you have node running):
npx hardhat test
To run a single test, you can use the following command:
npx hardhat test test/events.spec.ts --grep "TestName"
Replace "TestName"
with the name of the test you want to run. For example, to run the SimpleEvent
test, use:
npx hardhat test test/events.spec.ts --grep "SimpleEvent"
Make sure you have Hardhat version 2.0.0 or above to use the --grep
option. You can check your Hardhat version with:
npx hardhat --version
If you need to upgrade Hardhat, run:
npm install --save-dev hardhat@latest
The Event CLI is a command-line interface designed to emit events on the blockchain. It provides various commands to handle different types of events, including simple events, events with fixed arrays, dynamic arrays, and structured data.
There is a command matching each test:
SimpleEvent
EventWithFixedArray
EventWithDynamicArray
EventWithStructWithArrays
EventWithStructWithNestedStruct
EventWithStructWithFixedStructArray
EventWithStructWithDynamicStructArray
When installed globally, use:
solidity-event-cli <command> [options]
When developing locally in the repo, use:
npm run emit <command> -- [options]
Global installation:
solidity-event-cli EventWithStructWithArrays --dynamicArray 1,2
Local development:
npm run emit EventWithStructWithArrays -- --dynamicArray 1,2
Command | Description | Possible Inputs | Default Values |
---|---|---|---|
SimpleEvent |
Emit a simple event. | None | None |
EventWithFixedArray |
Emit an event with a fixed array. | None | None |
EventWithDynamicArray |
Emit an event with a dynamic array. | --dynamicArray <value> (comma-separated integers) |
[1, 2, 3, 4, 5, 6] |
EventWithStructWithArrays |
Emit an event with structured arrays. | --dynamicArray <value> (comma-separated integers) |
[1, 2, 3, 4, 5, 6] |
EventWithStructWithNestedStruct |
Emit an event with nested structures. | None | None |
EventWithStructWithFixedStructArray |
Emit an event with a fixed struct array. | None | None |
EventWithStructWithDynamicStructArray |
Emit an event with a dynamic struct array. | --dynamicStructArray <value> (JSON format) |
[{ a: 1, b: 2 }, { a: 3, b: 4 }] |
- Dynamic Array Commands: If no dynamic array is provided, the CLI will use the default values of
[1, 2, 3, 4, 5, 6]
for commands that require a dynamic array. - Dynamic Struct Array Command: If no dynamic struct array is provided, the CLI will use the default values of
[{ a: 1, b: 2 }, { a: 3, b: 4 }]
for theEventWithStructWithDynamicStructArray
command.
- Ensure that the inputs provided for dynamic arrays are integers and formatted correctly.
- For the dynamic struct array, the input must be a valid JSON string representing an array of objects with properties
a
andb
as integers.
This project provides a Docker container that runs a Ganache instance with all contracts pre-deployed which you can use to test your indexer against.
# Pull the image
docker pull yourusername/your-image-name:latest
# Run with default port (8545)
docker run -p 8545:8545 yourusername/your-image-name
# Run on a custom port (e.g., 9545)
docker run -p 9545:8545 yourusername/your-image-name
- The container runs a Ganache instance with pre-deployed contracts
- Default RPC port: 8545
- Fixed mnemonic: "test test test test test test test test test test test junk"
- Gas limit: 100000000
- Default port is 8545 (inside container)
- Map to any port on your host using Docker's port mapping:
-p host_port:8545
# Run on default port
docker run -p 8545:8545 yourusername/your-image-name
# Run on custom port
docker run -p 9545:8545 yourusername/your-image-name
# Run in detached mode
docker run -d -p 8545:8545 yourusername/your-image-name
# Get container logs
docker logs container_id
The RPC endpoint will be available at http://localhost:<port>
where port is either 8545 or your custom port.