The Sim IDX framework has been updated with a new core import and a standardized function for accessing the block number in listener contracts.What’s new:
- Core Import: All listeners should now include
import "sim-idx-sol/Simidx.sol";
. This file provides essential framework helpers required for core functionality. blockNumber()
Function: This function is now available to get the current block number. Use this instead ofblock.number
for standardized access across all supported blockchains.
blockNumber()
function, listeners must include the sim-idx-sol/Simidx.sol
import. Attempting to call the function without the import will result in a compilation error. Going forward, all listener contracts should adopt this pattern to access core framework features.Example Listener
New Feature: Custom Block Range SupportYou can now specify custom block ranges for your triggers, allowing you to target specific blocks or time periods for each trigger.What’s new:This creates a trigger that listens to events starting from block 10,000,000 onwards with no end block. The This creates a trigger that listens to events only within blocks 10,000,000 to 10,000,001 (both inclusive). The This demonstrates creating a
- Chain helper functions now support
.withStartBlock()
,.withEndBlock()
, and.withBlockRange()
methods - Block range support for contract, ABI, and global targets
withStartBlock()
method creates a BlockRange
struct with BlockRangeKind.RangeFrom
, meaning it captures all blocks from the specified start block to the latest available block.Inclusive Block RangewithEndBlock()
method modifies the BlockRange
to use BlockRangeKind.RangeInclusive
, creating a bounded range that stops processing after the end block.Using BlockRange Struct DirectlyBlockRange
struct directly using the BlockRangeLib
library functions before applying it to the chain. The BlockRange
struct is available through the sim-idx-sol
import. This approach gives you more flexibility to reuse ranges across multiple triggers or build complex range logic.CallFrame Properties Are Now FunctionsEvery field on
ctx.txn.call
’s CallFrame
structure has been updated to use function calls instead of direct property access.What changed:Old (≤ v0.0.82) | New (v0.0.83+) |
---|---|
ctx.txn.call.callee | ctx.txn.call.callee() |
ctx.txn.call.caller | ctx.txn.call.caller() |
ctx.txn.call.callData | ctx.txn.call.callData() |
ctx.txn.call.callDepth | ctx.txn.call.callDepth() |
ctx.txn.call.value | ctx.txn.call.value() |
ctx.txn.call.callType | ctx.txn.call.callType() |
(new) | ctx.txn.call.delegator() |
(new) | ctx.txn.call.delegatee() |
ctx.txn.call.verificationSource
is unchanged (still a property).Impact:If you were directly reading these fields, your code will no longer compile. Add ()
everywhere you touch ctx.txn.call.*
.Example (UniswapV3Factory Listener)
New Feature: Database Indexing SupportYou can now define database indexes directly within your listener contracts. This gives you more control over your app’s query performance.What’s new:
- Define indexes directly above your
event
declarations using a/// @custom:index
comment in your Solidity code. - Support for multiple index types, including
BTREE
,HASH
,BRIN
, andGIN
. - The
sim build
command now validates your index definitions to catch errors early.
- Improved Query Performance: Significantly speed up data retrieval by indexing columns that are frequently used in your API queries.
- Declarative and Convenient: Manage database performance directly from your Solidity code without writing separate migration scripts.
- Fine-Grained Control: Apply the right index types to the right columns for optimal performance.
Breaking Change: Generated Struct Names Now Include Contract NamesWith CLI version v0.0.79 and upwards, there will be a breaking change that impacts users who import and use generated structs from the ABI.Why this change was needed:
The same struct name can be used across different contracts (example:
GPv2Trade.Data
and GPv2Interaction.Data
within the same ABI) with different definitions. Using just the struct name for generated structs prevented proper triggering on protocols like CoW Swap.What changed:
We now include the contract name as part of the struct name in the generated Solidity file associated with the ABI. Instead of using $AbiName$StructName
for the names, we now use $AbiName$ContractName$StructName
.Impact:
If you have imported a generated struct, you’ll need to update the name to include the contract name the next time you run codegen. This doesn’t impact the default inputs/outputs/context structs, so most users won’t encounter this issue.Who is affected:
You’ll only run into this issue if you:- Update to use CLI v0.0.79 or higher
- Add a new ABI or manually run a new codegen
- AND you’ve been using generated structs that aren’t the ones provided in the trigger inputs/outputs object (i.e., you’re using a nested struct from the inputs/outputs for some variable or part of the event)
New Feature: Multiple Listener Contracts SupportThe Sim CLI now supports defining multiple listener contracts within a single IDX application, enabling better code organization and structure.What’s new:
- You can now define listeners in separate files instead of having everything in
Main.sol
- Listeners can be organized across multiple contracts for better code maintainability
- The
Main.sol
file still needs to contain theTriggers
contract, but individual listeners can be defined anywhere - Enhanced
sim listeners evaluate
command to target specific listeners for focused testing
- Better Code Organization: Split large applications with many listeners into manageable, separate files
- Improved Maintainability: Organize related listeners together (e.g., all DEX-specific listeners in one file)
- Focused Testing: Evaluate specific listeners without noise from other listeners in your application
- Existing single-file applications continue to work without changes
Main.sol
must still exist and contain yourTriggers
contract- Listener contracts can be moved to separate files as needed
New Feature: Pre-Execution TriggersThe Sim CLI now supports pre-execution triggers, allowing you to execute code before a function runs instead of the default behavior of executing after.What’s new:
- Pre-triggers use corresponding
Pre-
abstract contracts (e.g.,preCreatePoolFunction
) - Handlers receive a
PreFunctionContext
with access to function inputs only (outputs haven’t been generated yet) - Enables reactive logic that needs to run before the target function executes
- Emit events or perform actions based on upcoming function calls
- Pre-process or validate function inputs before execution
- Set up state or conditions that the main function execution will depend on