Comment on page
Factory parameterization
Parameterization of a Factory contract
It's quite common for a smart contract to be deployed on different networks or even by different dApps within the same network. Uniswap Factory smart contract is a good example of that.
When running Substreams for a dApp, you need to know the smart contract deployment address and for obvious reasons, this address will be different for each deployment.
Instead of hard-coding the address in the Substreams binary, you can customize it without having to rebuild or even repackage the Substreams package. The consumer can then just provide the address as a parameter.
First, you need to add the
params
field as an input. Note that it's always a string and it's always the first input for the module:modules:
- name: map_pools_created
kind: map
inputs:
- params: string
- source: sf.ethereum.type.v2.Block
output:
type: proto:uniswap.types.v1.Pools
params:
map_params: 1f98431c8ad98523631ae4a59f267346ea31f984
You can specify the default value directly in the manifest. In this case, we use
0x1f98431c8ad98523631ae4a59f267346ea31f984
- the deployment address for UniswapV3 contract on Ethereum Mainnet.Handling the parameter in the module is easy. The module handler receives it as a first input parameter and you can use it to filter transactions instead of the hard-coded value:
#[substreams::handlers::map]
pub fn map_pools_created(params: String, block: Block) -> Result<Pools, Error> {
let factory_address = Hex::decode(params).unwrap();
Ok(Pools {
pools: block
.events::<abi::factory::events::PoolCreated>(&[&factory_address])
.filter_map(|(event, log)| {
// skipped: extracting pool information from the transaction
Some(Pool {
address,
token0,
token1,
..Default::default()
})
})
.collect(),
})
}
To pass the parameter to the module using
substreams
CLI you can use -p
key:substreams gui -e $SUBSTREAMS_ENDPOINT map_pools_created -t +1000 -p map_pools_created="1f98431c8ad98523631ae4a59f267346ea31f984"`
It's always a good idea to document what the params represent and how they are structured, so the consumers of your modules know how to properly parameterize them. You can use
doc
field for the module definition in the manifest.modules:
- name: map_pools_created
kind: map
inputs:
- source: sf.ethereum.type.v2.Block
- params: string
output:
type: proto:uniswap.types.v1.Pools
doc: |
Params contains Uniswap factory smart contract address without `0x` prefix, i.e. 1f98431c8ad98523631ae4a59f267346ea31f984 for Ethereum Mainnet
Last modified 5mo ago