Frontier EVM support
Method documentation is also available inline and can be accessed via suggestions in most IDEs.
Check out the Caveats section of this page to avoid common issues.
This section describes additional options available for Substrate chains with the Frontier EVM pallet like Astar. On ArrowSquid, use the frontier-evm template as the starting point.
The overall approach is to use the SubstrateBatchProcessor
methods addEvmLog()
and addEthereumTransaction()
to request the required EVM data. The data can then be converted into a standard EVM format using the utils from the frontier package and decoded with utility classes generated by squid-evm-typegen
.
Contract state can also be accessed via wrapped RPC queries using the classes provided by the squid-evm-typegen
tool.
Examples
Subscribe to event logs
const processor = new SubstrateBatchProcessor()
.setGateway('https://v2.archive.subsquid.io/network/astar-substrate')
.setRpcEndpoint('https://astar-rpc.dwellir.com')
.addEvmLog({
address: [
'0xb654611f84a8dc429ba3cb4fda9fad236c505a1a',
'0x6a2d262d56735dba19dd70682b39f6be9a931d98'
],
topic0: [erc721.events.Transfer.topic],
extrinsic: true
})
.setFields({
event: {
phase: true
},
extrinsics: {
hash: true
}
})
Request all EVM calls to two contracts
processor.addEthereumTransaction({
to: [
'0x6a2d262d56735dba19dd70682b39f6be9a931d98'
'0x3795c36e7d12a8c252a20c5a7b455f7c57b60283'
]
})
Request all transfer(address,uint256)
EVM calls on the network:
processor.addEthereumTransaction({sighash: ['0xa9059cbb']})
Parse events and transactions
const processor = new SubstrateBatchProcessor()
.setGateway('https://v2.archive.subsquid.io/network/astar-substrate')
.setRpcEndpoint('https://astar-rpc.dwellir.com')
.addEthereumTransaction({})
.addEvmLog({})
processor.run(new TypeormDatabase(), async ctx => {
for (const block of ctx.blocks) {
for (const event of block.events) {
if (event.name === 'EVM.Log') {
// no need to supply any extra data to determine
// the runtime version: event has all necessary references
const {address, data, topics} = getEvmLog(event)
// process evm log data
}
}
for (const call of block.calls) {
if (call.name==='Ethereum.transact') {
const txn = getTransaction(call)
// process evm txn data
}
}
}
})
Access contract state
// ...
const CONTRACT_ADDRESS= "0xb654611f84a8dc429ba3cb4fda9fad236c505a1a"
processor.run(new TypeormDatabase(), async ctx => {
for (const block of ctx.blocks) {
for (const event of block.events) {
if (event.name === "EVM.Log") {
const contract = new erc721.Contract(ctx, block, CONTRACT_ADDRESS);
// query the contract state
const uri = await contract.tokenURI(1137)
}
}
}
})
Factory contracts
It some cases the set of contracts to be indexed by the squid is not known in advance. For example, a DEX contract typically creates a new contract for each trading pair added, and each such trading contract is of interest.
While the set of handler subscriptions is static and defined at the processor creation, one can leverage the wildcard subscriptions and filter the contracts of interest in runtime. This pattern is described extensively in EVM documentation, but it can be used with EVM methods of SubstrateBatchProcessor
as well. A (somewhat outdated) example is available in this archive repo.
Caveats
-
If your use case does not require any Substrate-specific data (e.g. extrinsic hashes), use
EvmBatchProcessor
instead. EVM-only SQD Network gateways are available for all major EVM-on-Substrate chains. -
Passing
[]
as a set of parameter values selects no data. Passundefined
for a wildcard selection:.addEvmLog({address: []}) // selects no events
.addEvmLog({}) // selects all events -
If contract address(es) supplied to the processor configuration methods are stored in any wide-scope variables, it is recommended to convert them to flat lower case. This precaution is necessary because same variable(s) are often reused in the batch handler for item filtration, and all contract addresses in the items are always in flat lower case.