diff --git a/.github/workflows/test.yml b/.github/workflows/evm.yml similarity index 92% rename from .github/workflows/test.yml rename to .github/workflows/evm.yml index c64c94f..c75f40d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/evm.yml @@ -1,6 +1,9 @@ -name: test +name: test evm -on: workflow_dispatch +on: + push: + paths: + - "evm/**" env: FOUNDRY_PROFILE: ci diff --git a/.github/workflows/substream.cd.yaml b/.github/workflows/substream.cd.yaml new file mode 100644 index 0000000..8e99d96 --- /dev/null +++ b/.github/workflows/substream.cd.yaml @@ -0,0 +1,45 @@ +name: Substreams CD + +on: + push: + tags: + - "ethereum-*" + workflow_dispatch: + inputs: + package: + required: true + description: "Package to build" + +jobs: + Release: + name: Release ${{ inputs.package }} + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: stable + targets: wasm32-unknown-unknown + + - name: Setup Rust Cache + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Install Substreams CLI + run: | + # Use correct binary for your platform + LINK=$(curl -s https://api.github.com/repos/streamingfast/substreams/releases/latest | awk "/download.url.*linux_$(uname -m)/ {print \$2}" | sed 's/"//g') + curl -L "$LINK" | tar zxf - -C /usr/local/bin + chmod +x /usr/local/bin/substreams + substreams --version + + - name: Run checks + run: | + cd substreams + ./release.sh ${{ inputs.package }} diff --git a/.github/workflows/substream.ci.yaml b/.github/workflows/substream.ci.yaml new file mode 100644 index 0000000..32c2aee --- /dev/null +++ b/.github/workflows/substream.ci.yaml @@ -0,0 +1,59 @@ +name: Substreams CI + +on: + push: + paths: + - "substreams/**" + +jobs: + lint: + name: Substreams Lint + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: nightly + components: clippy, rustfmt + + - name: Setup Rust Cache + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Run checks + run: | + cd substreams + cargo +nightly fmt -- --check + cargo +nightly clippy --all --all-features --all-targets -- -D warnings + + test: + name: Substreams Test + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: stable + targets: wasm32-unknown-unknown + + - name: Setup Rust Cache + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Run checks + run: | + cd substreams + cargo build --target wasm32-unknown-unknown --all-targets --all-features + cargo test --workspace --all-targets --all-features diff --git a/.gitignore b/.gitignore index 2c65d74..8ab5a15 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ target/ .vscode .idea *.log + +substreams/ethereum-template/Cargo.lock diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index b00c8e4..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "solidity.formatter": "forge", - "solidity.compileUsingRemoteVersion": "v0.8.20", - "solidity.packageDefaultDependenciesContractsDirectory": "evm/src", - "solidity.packageDefaultDependenciesDirectory": "evm/lib", -} \ No newline at end of file diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 1e70a1c..64e1431 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -10,5 +10,4 @@ ## Indexing -* [Substreams Integration](indexing/substreams-integration/README.md) - * [Tutorial: Ambient](indexing/substreams-integration/tutorial-ambient.md) +* [Substreams Integration](indexing/substreams-integration.md) diff --git a/docs/indexing/substreams-integration.md b/docs/indexing/substreams-integration.md new file mode 100644 index 0000000..5572939 --- /dev/null +++ b/docs/indexing/substreams-integration.md @@ -0,0 +1,153 @@ +# Substreams Integration + +This page describes the data model required to ingest protocol state into the PropellerHeads solver. + +To integrate a protocol PropellerHeads rely on either native or vm logic. Most integration will likely choose to use the VM, as this is usually less effort, the guide will focus mostly on providing state for vm integrations. + +Native integration should operate following exactly the same pattern, just that they should emit changed attributes instead of changes contract storage slots. + +### Understanding the Data Model + +PropellerHeads ingest all data versioned by block and transaction. This helps maintain a low latency feed and deal correctly with chains that can experience reverts. + +This means each state change that is communicated must be communicated with its respective transaction that caused the change. + +Next, for each emitted transactions that carries state changes, the corresponding block must be provided as well. + +So basically when processing a block we need to emit the block itself, all transactions that introduced protocol state changes and last but not least the state changes themselves, associated to their corresponding transaction. + +**The data model that encodes changes, transaction and blocks in messages, can be found** [**here**](https://github.com/propeller-heads/propeller-protocol-lib/tree/main/proto/tycho/evm/v1)**.** + +#### Common Models + +The following models are shared for both vm and native integrations. + +{% @github-files/github-code-block url="https://github.com/propeller-heads/propeller-protocol-lib/blob/main/proto/tycho/evm/v1/common.proto" %} + +#### VM Specific Models + +The models shown below are specific to vm integrations: + +{% @github-files/github-code-block url="https://github.com/propeller-heads/propeller-protocol-lib/blob/main/proto/tycho/evm/v1/vm.proto" %} + +Please be aware that changes need to be aggregated on the transaction level, it is considered an error to emit `BlockContractChanges` with duplicated transactions present in the `changes` attributes. + +All attributes are expected to be set in the final message unless the docs (in the comments) indicate otherwise. + +#### Native Integration Models + +The models below are very similar to the vm integration models but have a few modifications necessary to support native integrations. + +{% @github-files/github-code-block url="https://github.com/propeller-heads/propeller-protocol-lib/blob/main/proto/tycho/evm/v1/entity.proto" %} + +Once again changes must be aggregated on a transaction level, emitting these models with duplicated transaction as the final output would be considered an error. + +#### Integer Byte encoding + +Many of the types above are variable length bytes. This allows for flexibility across blockchains but require agreeing on an informal interface, so later applications know how to interpret these bytes. + +**Integers:** especially integers used to communicate balances, should always be encoded as unsigned big-endian integer. This is simply because balances serve multiple purposes within the system and need to be decoded in multiple location of the messages journey. + +**Strings**: If you need to store strings, please use utf-8 encoding to store them as bytes. + +**Attributes:** the value encoding for attributes in the native implementation messages is variable. It depends on the use case. Since the attributes are highly dynamic they are only used by the corresponding logic components, so the encoding can be tailored to the logic implementation: E.g. since Rust uses little endian one may choose to use little endian encoding for integers if the native logic module is written in Rust. + + + +### Changes of interest + +PropellerHeads integration should at least communicate the following changes: + +* Any changes to the protocol state, for VM integrations that usually means contract storage changes of all contracts whose state may be accessed during a swap operation. +* Any newly added protocol component such as a pool, pair, market, etc. Basically anything that signifies that a new operation can be executed now using the protocol. +* ERC20 Balances, whenever the balances of one contracts involved with the protocol change, this change should be communicated in terms of absolute balances. + +In the next section we will show a few common techniques that can be leveraged to quickly implement an integration. + +### How to Integrate + +Before starting, it is important to be aware of the protocol we are aiming to integrate functions. + +It is especially important to know: + +* Which contracts are involved in the protocol and what functions do they serve. How do they affect the behaviour of the component being integrated? +* What conditions (e.g. oracle update) or what kind of method calls can lead to a relevant state change on the protocol, which ultimately changes the protocols behaviour if observed externally. +* Are there components added or removed, and how are they added. Most protocols use either a factory contract, which can be used to deploy new components, or they use a method call that provisiona a new component within the overall system. + +Once the workings of the protocol are clear the implementation can start. + +#### Setup + +PropellerHeads indexing integrations are provided as [substreams](https://substreams.streamingfast.io/) skpg files. If you do not know substreams yet, make sure to go check them out and set up their [cli](https://substreams.streamingfast.io/documentation/consume/installing-the-cli) before continuing. + +Please start a new package for your integration, by copying the `ethereum-template` to a new name. The convention is: `[CHAIN]-[PROTOCOL_SYSTEM]` please make sure to also adjust: `cargo.toml` as well as `substreams.yaml` accordingly. + +It should be possible now to generate the necessary protobuf code: + +``` +substreams protogen substreams.yaml --exclude-paths="sf/substreams,google" +``` + +You are ready to start coding. Please refer to the substreams documentation for more information on the available tools such as handlers and stores. + +#### Tracking Components + +Usually the first step consists in detecting the creation of new components and store their contract addresses in a store, so they can be properly tracked further downstream. + +Later we'll have to emit balance and state changes based on the set of currently tracked components. + +{% hint style="info" %} +Note that emitting state changes of components that have not been previously announced is considered an error. +{% endhint %} + +Newly created components are detected by mapping over the `sf.ethereum.type.v2.Block model`. + +The output message should usually contain as much information about the component available at that time as well as the transaction that created the protocol component. + +We have found that using the final model prefilled with only component changes is usually good enough since it holds all the information that will be necessary at the end. + +For VM Integrations the final model is `BlockContractChanges`: + +```protobuf +// A set of changes aggregated by transaction. +message TransactionContractChanges { + // The transaction instance that results in the changes. + Transaction tx = 1; + // Contains the changes induced by the above transaction, aggregated on a per-contract basis. + // Must include changes to every contract that is tracked by all ProtocolComponents. + repeated ContractChange contract_changes = 2; + // An array of any component changes. + repeated ProtocolComponent component_changes = 3; + // An array of balance changes to components. + repeated BalanceChange balance_changes = 4; +} + +// A set of transaction changes within a single block. +message BlockContractChanges { + // The block for which these changes are collectively computed. + Block block = 1; + // The set of transaction changes observed in the specified block. + repeated TransactionContractChanges changes = 2; +} +``` + +Note that a single transaction may emit multiple newly created components. In this case it is expected that the `TransactionContractChanges.component_changes`, contains multiple `ProtocolComponents`. + +Once emitted, the protocol components should be stored in a Store, since we will later have to use this store to decide whether a contract is interesting to us or not. + +#### Tracking Absolute Balances + +Tracking balances can be tricky since often balance information is only available in relative values. + +This means the relative values have to be aggregated by component, to arrive at an absolute value. Additionally throughout this aggregation we need to track the balance change inducing transaction. + +Since this is challenging the following approach is recommended: + +* Use a handler to process a block and emit the `BalanceDeltas` struct. Make sure to sort the balance deltas by `component_id, token_address` +* Aggregate the BalanceDelta messages using a `BigIntAddStore`. +* In a final handler, use as inputs: A `DeltaStore` input from step 2 and the `BalanceDeltas` from step 1. You can now zip the deltas from the store with the balance deltas from step 1. The store deltas contains the aggregated (absolute) balance at each version and the balance deltas contain the corresponding transaction. + +#### Tracking State Changes + +To track contract changes, you can simply use the `extract_contract_changes` function (see balancer implementation). This function will extract all relevant contract storage changes given the full block model and a store that flags contract addresses as relevant. + diff --git a/evm/.gitignore b/evm/.gitignore index 85198aa..409f575 100644 --- a/evm/.gitignore +++ b/evm/.gitignore @@ -1,6 +1,7 @@ # Compiler files cache/ out/ +coverage/ # Ignores development broadcast logs !/broadcast @@ -12,3 +13,7 @@ docs/ # Dotenv file .env + +# Others +.DS_STORE +lcov.info diff --git a/evm/src/integral/IntegralSwapAdapter.sol b/evm/src/integral/IntegralSwapAdapter.sol new file mode 100644 index 0000000..4797132 --- /dev/null +++ b/evm/src/integral/IntegralSwapAdapter.sol @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.13; + +import {IERC20, ISwapAdapter} from "src/interfaces/ISwapAdapter.sol"; +import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @dev Integral submitted deadline of 3600 seconds (1 hour) to Paraswap, but it is not strictly necessary to be this long +/// as the contract allows less durations, we use 1000 seconds (15 minutes) as a deadline +uint256 constant SWAP_DEADLINE_SEC = 1000; +uint256 constant STANDARD_TOKEN_DECIMALS = 10**18; + +/// @title Integral Swap Adapter +contract IntegralSwapAdapter is ISwapAdapter { + using SafeERC20 for IERC20; + + ITwapRelayer immutable relayer; + + constructor(address relayer_) { + relayer = ITwapRelayer(relayer_); + } + + /// @inheritdoc ISwapAdapter + /// @dev Integral always relies on a single pool linked to the factory to map two pairs, and does not use routing + /// we can then use getPriceByTokenAddresses() instead of getPriceByPairAddresses() + /// as they both return the same value and the first also handles the order of tokens inside. + /// @dev Since the price of a token is determined externally by Integral Oracles and not by reserves + /// it will always be the same (pre and post trade) and independent of the amounts swapped, + /// but we still return an array of length=specifiedAmounts.length with same values to make sure the return value is the expected from caller. + function price( + bytes32, + IERC20 _sellToken, + IERC20 _buyToken, + uint256[] memory _specifiedAmounts + ) external view override returns (Fraction[] memory _prices) { + _prices = new Fraction[](_specifiedAmounts.length); + Fraction memory price = getPriceAt(address(_sellToken), address(_buyToken)); + + for (uint256 i = 0; i < _specifiedAmounts.length; i++) { + _prices[i] = price; + } + } + + /// @inheritdoc ISwapAdapter + function swap( + bytes32, + IERC20 sellToken, + IERC20 buyToken, + OrderSide side, + uint256 specifiedAmount + ) external override returns (Trade memory trade) { + if (specifiedAmount == 0) { + return trade; + } + + uint256 gasBefore = gasleft(); + if (side == OrderSide.Sell) { // sell + trade.calculatedAmount = + sell(sellToken, buyToken, specifiedAmount); + } else { // buy + trade.calculatedAmount = + buy(sellToken, buyToken, specifiedAmount); + } + trade.gasUsed = gasBefore - gasleft(); + trade.price = getPriceAt(address(sellToken), address(buyToken)); + } + + /// @inheritdoc ISwapAdapter + function getLimits(bytes32, IERC20 sellToken, IERC20 buyToken) + external + view + override + returns (uint256[] memory limits) + { + ( + , + , + , + uint256 limitMax0, + , + uint256 limitMax1 + ) = relayer.getPoolState(address(sellToken), address(buyToken)); + + limits = new uint256[](2); + limits[0] = limitMax0; + limits[1] = limitMax1; + /** + * @dev minLimits in integral are the args: 2(for sellToken, the one before limitMax0) + * and 4(for buyToken, the one before limitMax1) of the function relayer.getPoolState(sellToken, buyToken); + * an implementation of them can be found in the test of this adapter + */ + } + + /// @inheritdoc ISwapAdapter + function getCapabilities(bytes32, IERC20, IERC20) + external + pure + override + returns (Capability[] memory capabilities) + { + capabilities = new Capability[](4); + capabilities[0] = Capability.SellOrder; + capabilities[1] = Capability.BuyOrder; + capabilities[2] = Capability.PriceFunction; + capabilities[3] = Capability.ConstantPrice; + } + + /// @inheritdoc ISwapAdapter + function getTokens(bytes32 poolId) + external + view + override + returns (IERC20[] memory tokens) + { + tokens = new IERC20[](2); + ITwapPair pair = ITwapPair(address(bytes20(poolId))); + tokens[0] = IERC20(pair.token0()); + tokens[1] = IERC20(pair.token1()); + } + + /// @inheritdoc ISwapAdapter + function getPoolIds(uint256 offset, uint256 limit) + external + view + override + returns (bytes32[] memory ids) + { + ITwapFactory factory = ITwapFactory(relayer.factory()); + uint256 endIdx = offset + limit; + if (endIdx > factory.allPairsLength()) { + endIdx = factory.allPairsLength(); + } + ids = new bytes32[](endIdx - offset); + for (uint256 i = 0; i < ids.length; i++) { + ids[i] = bytes20(factory.allPairs(offset + i)); + } + } + + /// @notice Executes a sell order on a given pool. + /// @param sellToken The address of the token being sold. + /// @param buyToken The address of the token being bought. + /// @param amount The amount to be traded. + /// @return uint256 The amount of tokens received. + function sell( + IERC20 sellToken, + IERC20 buyToken, + uint256 amount + ) internal returns (uint256) { + uint256 amountOut = relayer.quoteSell(address(sellToken), address(buyToken), amount); + if (amountOut == 0) { + revert Unavailable("AmountOut is zero!"); + } + + sellToken.safeTransferFrom(msg.sender, address(this), amount); + sellToken.safeIncreaseAllowance(address(relayer), amount); + + relayer.sell(ITwapRelayer.SellParams({ + tokenIn: address(sellToken), + tokenOut: address(buyToken), + wrapUnwrap: false, + to: msg.sender, + submitDeadline: uint32(block.timestamp + SWAP_DEADLINE_SEC), + amountIn: amount, + amountOutMin: amountOut + })); + + return amountOut; + } + + /// @notice Executes a buy order on a given pool. + /// @param sellToken The address of the token being sold. + /// @param buyToken The address of the token being bought. + /// @param amountBought The amount of buyToken tokens to buy. + /// @return uint256 The amount of tokens received. + function buy( + IERC20 sellToken, + IERC20 buyToken, + uint256 amountBought + ) internal returns (uint256) { + uint256 amountIn = relayer.quoteBuy(address(sellToken), address(buyToken), amountBought); + if (amountIn == 0) { + revert Unavailable("AmountIn is zero!"); + } + + sellToken.safeTransferFrom(msg.sender, address(this), amountIn); + sellToken.safeIncreaseAllowance(address(relayer), amountIn); + + relayer.buy(ITwapRelayer.BuyParams({ + tokenIn: address(sellToken), + tokenOut: address(buyToken), + wrapUnwrap: false, + to: msg.sender, + submitDeadline: uint32(block.timestamp + SWAP_DEADLINE_SEC), + amountInMax: amountIn, + amountOut: amountBought + })); + + return amountIn; + } + + /// @notice Get swap price including fee + /// @param sellToken token to sell + /// @param buyToken token to buy + function getPriceAt(address sellToken, address buyToken) internal view returns(Fraction memory) { + uint256 priceWithoutFee = relayer.getPriceByTokenAddresses(address(sellToken), address(buyToken)); + ITwapFactory factory = ITwapFactory(relayer.factory()); + address pairAddress = factory.getPair(address(sellToken), address(buyToken)); + + // get swapFee formatted; swapFee is a constant + uint256 swapFeeFormatted = (STANDARD_TOKEN_DECIMALS - relayer.swapFee(pairAddress)); + + // get token decimals + uint256 sellTokenDecimals = 10**ERC20(sellToken).decimals(); + uint256 buyTokenDecimals = 10**ERC20(buyToken).decimals(); + + /** + * @dev + * Denominator works as a "standardizer" for the price rather than a reserve value + * as Integral takes prices from oracles and do not operate with reserves; + * it is therefore used to maintain integrity for the Fraction division, + * as numerator and denominator could have different token decimals(es. ETH(18)-USDC(6)). + * Both numerator and denominator are also multiplied by STANDARD_TOKEN_DECIMALS + * to ensure that precision losses are minimized or null. + */ + return Fraction( + priceWithoutFee * STANDARD_TOKEN_DECIMALS, + STANDARD_TOKEN_DECIMALS * sellTokenDecimals * swapFeeFormatted / buyTokenDecimals + ); + } +} + +interface ITwapRelayer { + event OwnerSet(address owner); + event RebalancerSet(address rebalancer); + event DelaySet(address delay); + event PairEnabledSet(address pair, bool enabled); + event SwapFeeSet(address pair, uint256 fee); + event TwapIntervalSet(address pair, uint32 interval); + event EthTransferGasCostSet(uint256 gasCost); + event ExecutionGasLimitSet(uint256 limit); + event TokenLimitMinSet(address token, uint256 limit); + event TokenLimitMaxMultiplierSet(address token, uint256 limit); + event ToleranceSet(address pair, uint16 tolerance); + event Approve(address token, address to, uint256 amount); + event Withdraw(address token, address to, uint256 amount); + event Sell( + address indexed sender, + address tokenIn, + address tokenOut, + uint256 amountIn, + uint256 amountOut, + uint256 amountOutMin, + bool wrapUnwrap, + uint256 fee, + address indexed to, + address orderContract, + uint256 indexed orderId + ); + event Buy( + address indexed sender, + address tokenIn, + address tokenOut, + uint256 amountIn, + uint256 amountInMax, + uint256 amountOut, + bool wrapUnwrap, + uint256 fee, + address indexed to, + address orderContract, + uint256 indexed orderId + ); + event RebalanceSellWithDelay( + address indexed sender, + address tokenIn, + address tokenOut, + uint256 amountIn, + uint256 indexed delayOrderId + ); + event RebalanceSellWithOneInch(address indexed oneInchRouter, uint256 gas, bytes data); + event OneInchRouterWhitelisted(address indexed oneInchRouter, bool whitelisted); + + function factory() external pure returns (address); + + function delay() external pure returns (address); + + function weth() external pure returns (address); + + function owner() external view returns (address); + + function rebalancer() external view returns (address); + + function isOneInchRouterWhitelisted(address oneInchRouter) external view returns (bool); + + function setOwner(address _owner) external; + + function swapFee(address pair) external view returns (uint256); + + function setSwapFee(address pair, uint256 fee) external; + + function twapInterval(address pair) external pure returns (uint32); + + function isPairEnabled(address pair) external view returns (bool); + + function setPairEnabled(address pair, bool enabled) external; + + function ethTransferGasCost() external pure returns (uint256); + + function executionGasLimit() external pure returns (uint256); + + function tokenLimitMin(address token) external pure returns (uint256); + + function tokenLimitMaxMultiplier(address token) external pure returns (uint256); + + function tolerance(address pair) external pure returns (uint16); + + function setRebalancer(address _rebalancer) external; + + function whitelistOneInchRouter(address oneInchRouter, bool whitelisted) external; + + function getTolerance(address pair) external pure returns (uint16); + + function getTokenLimitMin(address token) external pure returns (uint256); + + function getTokenLimitMaxMultiplier(address token) external pure returns (uint256); + + function getTwapInterval(address pair) external pure returns (uint32); + + struct SellParams { + address tokenIn; + address tokenOut; + uint256 amountIn; + uint256 amountOutMin; + bool wrapUnwrap; + address to; + uint32 submitDeadline; + } + + function sell(SellParams memory sellParams) external payable returns (uint256 orderId); + + struct BuyParams { + address tokenIn; + address tokenOut; + uint256 amountInMax; + uint256 amountOut; + bool wrapUnwrap; + address to; + uint32 submitDeadline; + } + + function buy(BuyParams memory buyParams) external payable returns (uint256 orderId); + + function getPriceByPairAddress(address pair, bool inverted) + external + view + returns ( + uint8 xDecimals, + uint8 yDecimals, + uint256 price + ); + + function getPriceByTokenAddresses(address tokenIn, address tokenOut) external view returns (uint256 price); + + function getPoolState(address token0, address token1) + external + view + returns ( + uint256 price, + uint256 fee, + uint256 limitMin0, + uint256 limitMax0, + uint256 limitMin1, + uint256 limitMax1 + ); + + function quoteSell( + address tokenIn, + address tokenOut, + uint256 amountIn + ) external view returns (uint256 amountOut); + + function quoteBuy( + address tokenIn, + address tokenOut, + uint256 amountOut + ) external view returns (uint256 amountIn); + + function approve( + address token, + uint256 amount, + address to + ) external; + + function withdraw( + address token, + uint256 amount, + address to + ) external; + + function rebalanceSellWithDelay( + address tokenIn, + address tokenOut, + uint256 amountIn + ) external; + + function rebalanceSellWithOneInch( + address tokenIn, + uint256 amountIn, + address oneInchRouter, + uint256 _gas, + bytes calldata data + ) external; +} + +interface ITwapFactory { + event PairCreated(address indexed token0, address indexed token1, address pair, uint256); + event OwnerSet(address owner); + + function owner() external view returns (address); + + function getPair(address tokenA, address tokenB) external view returns (address pair); + + function allPairs(uint256) external view returns (address pair); + + function allPairsLength() external view returns (uint256); + + function createPair( + address tokenA, + address tokenB, + address oracle, + address trader + ) external returns (address pair); + + function setOwner(address) external; + + function setMintFee( + address tokenA, + address tokenB, + uint256 fee + ) external; + + function setBurnFee( + address tokenA, + address tokenB, + uint256 fee + ) external; + + function setSwapFee( + address tokenA, + address tokenB, + uint256 fee + ) external; + + function setOracle( + address tokenA, + address tokenB, + address oracle + ) external; + + function setTrader( + address tokenA, + address tokenB, + address trader + ) external; + + function collect( + address tokenA, + address tokenB, + address to + ) external; + + function withdraw( + address tokenA, + address tokenB, + uint256 amount, + address to + ) external; +} + +interface ITwapERC20 is IERC20 { + function PERMIT_TYPEHASH() external pure returns (bytes32); + + function nonces(address owner) external view returns (uint256); + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + function increaseAllowance(address spender, uint256 addedValue) external returns (bool); + + function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); +} + +interface IReserves { + function getReserves() external view returns (uint112 reserve0, uint112 reserve1); + + function getFees() external view returns (uint256 fee0, uint256 fee1); +} + +interface ITwapPair is ITwapERC20, IReserves { + event Mint(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 liquidityOut, address indexed to); + event Burn(address indexed sender, uint256 amount0Out, uint256 amount1Out, uint256 liquidityIn, address indexed to); + event Swap( + address indexed sender, + uint256 amount0In, + uint256 amount1In, + uint256 amount0Out, + uint256 amount1Out, + address indexed to + ); + event SetMintFee(uint256 fee); + event SetBurnFee(uint256 fee); + event SetSwapFee(uint256 fee); + event SetOracle(address account); + event SetTrader(address trader); + + function MINIMUM_LIQUIDITY() external pure returns (uint256); + + function factory() external view returns (address); + + function token0() external view returns (address); + + function token1() external view returns (address); + + function oracle() external view returns (address); + + function trader() external view returns (address); + + function mintFee() external view returns (uint256); + + function setMintFee(uint256 fee) external; + + function mint(address to) external returns (uint256 liquidity); + + function burnFee() external view returns (uint256); + + function setBurnFee(uint256 fee) external; + + function burn(address to) external returns (uint256 amount0, uint256 amount1); + + function swapFee() external view returns (uint256); + + function setSwapFee(uint256 fee) external; + + function setOracle(address account) external; + + function setTrader(address account) external; + + function collect(address to) external; + + function swap( + uint256 amount0Out, + uint256 amount1Out, + address to, + bytes calldata data + ) external; + + function sync() external; + + function initialize( + address _token0, + address _token1, + address _oracle, + address _trader + ) external; + + function getSwapAmount0In(uint256 amount1Out, bytes calldata data) external view returns (uint256 swapAmount0In); + + function getSwapAmount1In(uint256 amount0Out, bytes calldata data) external view returns (uint256 swapAmount1In); + + function getSwapAmount0Out(uint256 amount1In, bytes calldata data) external view returns (uint256 swapAmount0Out); + + function getSwapAmount1Out(uint256 amount0In, bytes calldata data) external view returns (uint256 swapAmount1Out); + + function getDepositAmount0In(uint256 amount0, bytes calldata data) external view returns (uint256 depositAmount0In); + + function getDepositAmount1In(uint256 amount1, bytes calldata data) external view returns (uint256 depositAmount1In); +} diff --git a/evm/src/integral/manifest.yaml b/evm/src/integral/manifest.yaml new file mode 100644 index 0000000..ac31df9 --- /dev/null +++ b/evm/src/integral/manifest.yaml @@ -0,0 +1,36 @@ +# information about the author helps us reach out in case of issues. +author: + name: Propellerheads.xyz + email: alan@propellerheads.xyz + +# Protocol Constants +constants: + protocol_gas: 30000 + # minimum capabilities we can expect, individual pools may extend these + capabilities: + - SellSide + - BuySide + - PriceFunction + +# The file containing the adapter contract +contract: IntegralSwapAdapter.sol + +# Deployment instances used to generate chain specific bytecode. +instances: + - chain: + name: mainnet + id: 0 + arguments: + - "0xd17b3c9784510E33cD5B87b490E79253BcD81e2E" + +# Specify some automatic test cases in case getPoolIds and +# getTokens are not implemented. +tests: + instances: + - pool_id: "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc" + sell_token: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + buy_token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + block: 17000000 + chain: + id: 0 + name: mainnet diff --git a/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol b/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol index cd07683..16a1673 100644 --- a/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol +++ b/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol @@ -87,7 +87,12 @@ contract UniswapV2SwapAdapter is ISwapAdapter { buy(pair, sellToken, zero2one, r0, r1, specifiedAmount); } trade.gasUsed = gasBefore - gasleft(); - trade.price = getPriceAt(specifiedAmount, r0, r1); + if(side == OrderSide.Sell) { + trade.price = getPriceAt(specifiedAmount, r0, r1); + } + else { + trade.price = getPriceAt(trade.calculatedAmount, r0, r1); + } } /// @notice Executes a sell order on a given pool. diff --git a/evm/test/IntegralSwapAdapter.t.sol b/evm/test/IntegralSwapAdapter.t.sol new file mode 100644 index 0000000..3d41885 --- /dev/null +++ b/evm/test/IntegralSwapAdapter.t.sol @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; +import "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; +import "src/interfaces/ISwapAdapterTypes.sol"; +import "src/libraries/FractionMath.sol"; +import "src/integral/IntegralSwapAdapter.sol"; + +contract IntegralSwapAdapterTest is Test, ISwapAdapterTypes { + using FractionMath for Fraction; + + IntegralSwapAdapter adapter; + ITwapRelayer relayer; + IERC20 constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); + IERC20 constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); + address constant USDC_WETH_PAIR = + 0x2fe16Dd18bba26e457B7dD2080d5674312b026a2; + address constant relayerAddress = + 0xd17b3c9784510E33cD5B87b490E79253BcD81e2E; + + uint256 constant TEST_ITERATIONS = 100; + + function setUp() public { + uint256 forkBlock = 18835309; + vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); + adapter = new IntegralSwapAdapter(relayerAddress); + relayer = ITwapRelayer(relayerAddress); + + vm.label(address(WETH), "WETH"); + vm.label(address(USDC), "USDC"); + vm.label(address(USDC_WETH_PAIR), "USDC_WETH_PAIR"); + } + + function testPriceFuzzIntegral(uint256 amount0, uint256 amount1) public { + bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); + uint256[] memory limits = adapter.getLimits(pair, USDC, WETH); + vm.assume(amount0 < limits[0]); + vm.assume(amount1 < limits[1]); + + uint256[] memory amounts = new uint256[](2); + amounts[0] = amount0; + amounts[1] = amount1; + + Fraction[] memory prices = adapter.price(pair, WETH, USDC, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + /// @dev Since TwapRelayer's calculateAmountOut function is internal, and using quoteSell would + /// revert the transaction if calculateAmountOut is not enough, + /// we need a threshold to cover this internal amount, applied to + function testSwapFuzzIntegral(uint256 specifiedAmount, bool isBuy) public { + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + + bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); + uint256[] memory limits = new uint256[](2); + uint256[] memory limitsMin = new uint256[](2); + + if (side == OrderSide.Buy) { + limits = adapter.getLimits(pair, USDC, WETH); + vm.assume(specifiedAmount < limits[1]); + + limitsMin = getMinLimits(USDC, WETH); + vm.assume(specifiedAmount > limitsMin[1] * 115 / 100); + + deal(address(USDC), address(this), type(uint256).max); + USDC.approve(address(adapter), type(uint256).max); + } else { + limits = adapter.getLimits(pair, USDC, WETH); + vm.assume(specifiedAmount < limits[0]); + + limitsMin = getMinLimits(USDC, WETH); + vm.assume(specifiedAmount > limitsMin[0] * 115 / 100); + + deal(address(USDC), address(this), type(uint256).max); + USDC.approve(address(adapter), specifiedAmount); + } + + uint256 usdc_balance_before = USDC.balanceOf(address(this)); + uint256 weth_balance_before = WETH.balanceOf(address(this)); + + Trade memory trade = adapter.swap( + pair, + USDC, + WETH, + side, + specifiedAmount + ); + + if (trade.calculatedAmount > 0) { + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, + WETH.balanceOf(address(this)) - weth_balance_before + ); + + assertEq( + trade.calculatedAmount, + usdc_balance_before - USDC.balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, + usdc_balance_before - USDC.balanceOf(address(this)) + ); + + assertEq( + trade.calculatedAmount, + WETH.balanceOf(address(this)) - weth_balance_before + ); + } + } + } + + function testSwapSellIncreasingIntegral() public { + executeIncreasingSwapsIntegral(OrderSide.Sell); + } + + function testSwapBuyIncreasing() public { + executeIncreasingSwapsIntegral(OrderSide.Buy); + } + + function executeIncreasingSwapsIntegral(OrderSide side) internal { + bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); + + uint256 amountConstant_ = side == OrderSide.Sell ? 1000 * 10**6 : 10**17; + + uint256[] memory amounts = new uint256[](TEST_ITERATIONS); + amounts[0] = amountConstant_; + for (uint256 i = 1; i < TEST_ITERATIONS; i++) { + amounts[i] = amountConstant_ * i; + } + + Trade[] memory trades = new Trade[](TEST_ITERATIONS); + uint256 beforeSwap; + for (uint256 i = 1; i < TEST_ITERATIONS; i++) { + beforeSwap = vm.snapshot(); + + deal(address(USDC), address(this), amounts[i]); + USDC.approve(address(adapter), amounts[i]); + + trades[i] = adapter.swap(pair, USDC, WETH, side, amounts[i]); + vm.revertTo(beforeSwap); + } + + for (uint256 i = 1; i < TEST_ITERATIONS - 1; i++) { + assertLe( + trades[i].calculatedAmount, + trades[i + 1].calculatedAmount + ); + assertLe(trades[i].gasUsed, trades[i + 1].gasUsed); + assertEq(trades[i].price.compareFractions(trades[i + 1].price), 0); + } + } + + function testGetCapabilitiesIntegral( + bytes32 pair, + address t0, + address t1 + ) public { + Capability[] memory res = adapter.getCapabilities( + pair, + IERC20(t0), + IERC20(t1) + ); + + assertEq(res.length, 4); + } + + function testGetTokensIntegral() public { + bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); + IERC20[] memory tokens = adapter.getTokens(pair); + + assertEq(tokens.length, 2); + } + + function testGetLimitsIntegral() public { + bytes32 pair = bytes32(bytes20(USDC_WETH_PAIR)); + uint256[] memory limits = adapter.getLimits(pair, USDC, WETH); + + assertEq(limits.length, 2); + } + + function getMinLimits(IERC20 sellToken, IERC20 buyToken) public view returns (uint256[] memory limits) { + ( + , + , + uint256 limitMin0, + , + uint256 limitMin1 + , + ) = relayer.getPoolState(address(sellToken), address(buyToken)); + + limits = new uint256[](2); + limits[0] = limitMin0; + limits[1] = limitMin1; + } +} \ No newline at end of file diff --git a/proto/tycho/evm/v1/common.proto b/proto/tycho/evm/v1/common.proto index d52dbed..7f6d369 100644 --- a/proto/tycho/evm/v1/common.proto +++ b/proto/tycho/evm/v1/common.proto @@ -25,6 +25,7 @@ message Transaction { // The receiver of the transaction. bytes to = 3; // The transactions index within the block. + // TODO: should this be uint32? to match the type from the native substream type? uint64 index = 4; } @@ -47,6 +48,26 @@ message Attribute { ChangeType change = 3; } +enum FinancialType{ + SWAP = 0; + LEND = 1; + LEVERAGE = 2; + PSM = 3; +} + + +enum ImplementationType { + VM = 0; + CUSTOM = 1; +} + +message ProtocolType{ + string name = 1; + FinancialType financial_type = 2; + repeated Attribute attribute_schema = 3; + ImplementationType implementation_type = 4; +} + // A struct describing a part of the protocol. // Note: For example this can be a UniswapV2 pair, that tracks the two ERC20 tokens used by the pair, // the component would represent a single contract. In case of VM integration, such component would @@ -67,6 +88,10 @@ message ProtocolComponent { repeated Attribute static_att = 4; // Type of change the component underwent. ChangeType change = 5; + /// Represents the functionality of the component. + ProtocolType protocol_type = 6; + // Transaction where this component was created + Transaction tx = 7; } // A struct for following the changes of Total Value Locked (TVL) of a protocol component. @@ -75,9 +100,9 @@ message ProtocolComponent { message BalanceChange { // The address of the ERC20 token whose balance changed. bytes token = 1; - // The new balance of the token. + // The new balance of the token. Note: it must be a big endian encoded int. bytes balance = 2; - // The id of the component whose TVL is tracked. + // The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. // If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. bytes component_id = 3; } diff --git a/proto/tycho/evm/v1/utils.proto b/proto/tycho/evm/v1/utils.proto new file mode 100644 index 0000000..ea3f5d5 --- /dev/null +++ b/proto/tycho/evm/v1/utils.proto @@ -0,0 +1,41 @@ +syntax = "proto3"; + +package tycho.evm.v1; + +import "tycho/evm/v1/common.proto"; + +// A message containing relative balance changes. +// +// Used to track token balances of protocol components in case they are only +// available as relative values within a block. +message BalanceDelta { + // The ordinal of the balance change. Must be unique & deterministic over all balances + // changes within a block. + uint64 ord = 1; + // The tx hash of the transaction that caused the balance change. + Transaction tx = 2; + // The address of the ERC20 token whose balance changed. + bytes token = 3; + // The delta balance of the token. + bytes delta = 4; + // The id of the component whose TVL is tracked. + // If the protocol component includes multiple contracts, the balance change must be + // aggregated to reflect how much tokens can be traded. + bytes component_id = 5; +} + +// A set of balances deltas, usually a group of changes within a single block. +message BlockBalanceDeltas { + repeated BalanceDelta balance_deltas = 1; +} + +// A message containing protocol components that were created by a single tx. +message TransactionProtocolComponents { + Transaction tx = 1; + repeated ProtocolComponent components = 2; +} + +// All protocol components that were created within a block with their corresponding tx. +message BlockTransactionProtocolComponents { + repeated TransactionProtocolComponents tx_components = 1; +} \ No newline at end of file diff --git a/substreams/ethereum-template/Cargo.lock b/substreams/Cargo.lock similarity index 77% rename from substreams/ethereum-template/Cargo.lock rename to substreams/Cargo.lock index ada8eab..f89bb92 100644 --- a/substreams/ethereum-template/Cargo.lock +++ b/substreams/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arrayvec" @@ -42,15 +42,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.3.2" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitvec" @@ -99,9 +93,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -134,9 +128,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "equivalent" @@ -151,7 +145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -160,7 +154,24 @@ version = "17.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b" dependencies = [ - "ethereum-types", + "ethereum-types 0.13.1", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types 0.14.1", "hex", "once_cell", "regex", @@ -178,23 +189,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" dependencies = [ "crunchy", - "fixed-hash", + "fixed-hash 0.7.0", "impl-rlp", - "impl-serde", + "impl-serde 0.3.2", "tiny-keccak", ] +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash 0.8.0", + "impl-rlp", + "impl-serde 0.4.0", + "tiny-keccak", +] + +[[package]] +name = "ethereum-balancer" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "ethabi 18.0.0", + "getrandom", + "hex", + "hex-literal 0.4.1", + "itertools 0.12.1", + "num-bigint", + "prost 0.11.9", + "prost-types 0.12.3", + "substreams", + "substreams-ethereum", + "tycho-substreams", +] + [[package]] name = "ethereum-types" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" dependencies = [ - "ethbloom", - "fixed-hash", + "ethbloom 0.12.1", + "fixed-hash 0.7.0", "impl-rlp", - "impl-serde", - "primitive-types", + "impl-serde 0.3.2", + "primitive-types 0.11.1", + "uint", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom 0.13.0", + "fixed-hash 0.8.0", + "impl-rlp", + "impl-serde 0.4.0", + "primitive-types 0.12.2", "uint", ] @@ -216,6 +273,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -240,9 +309,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -273,13 +342,19 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + [[package]] name = "home" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -309,6 +384,15 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -322,9 +406,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown", @@ -339,6 +423,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -347,9 +440,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -362,27 +455,27 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "multimap" @@ -403,19 +496,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -493,18 +585,31 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" dependencies = [ - "fixed-hash", + "fixed-hash 0.7.0", "impl-codec", "impl-rlp", - "impl-serde", + "impl-serde 0.3.2", + "uint", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash 0.8.0", + "impl-codec", + "impl-rlp", + "impl-serde 0.4.0", "uint", ] [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" dependencies = [ "toml_datetime", "toml_edit", @@ -512,9 +617,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -526,7 +631,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.11.9", +] + +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive 0.12.3", ] [[package]] @@ -537,14 +652,14 @@ checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ "bytes", "heck", - "itertools", + "itertools 0.10.5", "lazy_static", "log", "multimap", "petgraph", "prettyplease", - "prost", - "prost-types", + "prost 0.11.9", + "prost-types 0.11.9", "regex", "syn 1.0.109", "tempfile", @@ -558,26 +673,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "prost-types" version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" dependencies = [ - "prost", + "prost 0.11.9", +] + +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost 0.12.3", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -618,20 +755,11 @@ dependencies = [ "getrandom", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -641,9 +769,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -674,48 +802,48 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -740,21 +868,21 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "substreams" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3524a4e2931ff6cd58783e62adbd7e44f461752eca0c423793cfb462351f24" +checksum = "3520661f782c338f0e3c6cfc001ac790ed5e68d8f28515139e2aa674f8bb54da" dependencies = [ "anyhow", "bigdecimal", "hex", - "hex-literal", + "hex-literal 0.3.4", "num-bigint", "num-integer", "num-traits", "pad", - "prost", + "prost 0.11.9", "prost-build", - "prost-types", + "prost-types 0.11.9", "substreams-macro", "thiserror", ] @@ -780,7 +908,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c04307913a355aaf2a1bb7186d4bc7e36875f3d4aff77b47e83f1b63b24da55" dependencies = [ "anyhow", - "ethabi", + "ethabi 17.2.0", "heck", "hex", "prettyplease", @@ -797,12 +925,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db9048cc9a66873ab7069ef958c2684994e6ee323da49c186b19156fdb4ca131" dependencies = [ "bigdecimal", - "ethabi", + "ethabi 17.2.0", "getrandom", "num-bigint", - "prost", + "prost 0.11.9", "prost-build", - "prost-types", + "prost-types 0.11.9", "substreams", ] @@ -812,7 +940,7 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e862928bee8653f5c9291ac619c8dc0da14ca61d8cd8d89b3acdbbde4d0bf304" dependencies = [ - "ethabi", + "ethabi 17.2.0", "heck", "hex", "num-bigint", @@ -822,20 +950,11 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "substreams-ethereum-template" -version = "0.1.0" -dependencies = [ - "prost", - "substreams", - "substreams-ethereum", -] - [[package]] name = "substreams-macro" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c2b15adf5b4d7a6d1a73c73df951a6b2df6fbb4f0b41304dc28c5550ce0ed0" +checksum = "c15595ceab80fece579e462d4823048fe85d67922584c681f5e94305727ad9ee" dependencies = [ "proc-macro2", "quote", @@ -856,9 +975,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -873,35 +992,34 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.52", ] [[package]] @@ -930,6 +1048,17 @@ dependencies = [ "winnow", ] +[[package]] +name = "tycho-substreams" +version = "0.1.0" +dependencies = [ + "hex", + "itertools 0.12.1", + "prost 0.11.9", + "substreams", + "substreams-ethereum", +] + [[package]] name = "typenum" version = "1.17.0" @@ -984,143 +1113,77 @@ dependencies = [ "rustix", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.5.30" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] diff --git a/substreams/Cargo.toml b/substreams/Cargo.toml new file mode 100644 index 0000000..8bcd85d --- /dev/null +++ b/substreams/Cargo.toml @@ -0,0 +1,22 @@ +[workspace] +members = [ + "ethereum-balancer", + "crates/tycho-substreams", +] +resolver = "2" + + +[workspace.dependencies] +substreams-ethereum = "0.9.9" +substreams = "0.5" +prost = "0.11" +prost-types = "0.12.3" +hex-literal = "0.4.1" +hex = "0.4.3" +ethabi = "18.0.0" +tycho-substreams = {path ="crates/tycho-substreams"} + +[profile.release] +lto = true +opt-level = 's' +strip = "debuginfo" \ No newline at end of file diff --git a/substreams/Readme.md b/substreams/Readme.md index f4f9aa3..0ceaea5 100644 --- a/substreams/Readme.md +++ b/substreams/Readme.md @@ -1,99 +1,24 @@ -# Subtreams packages +# Substreams Indexing Integrations -This directory contains all substream packages that are used to index integrated protocols across different blockchains. +Please refer to the official [Substreams Indexing](https://app.gitbook.com/o/9wMvRDQIhk1xOsIZ0Zde/s/Yx9kvxtpT2xWdzvFiB3t/indexing/substreams-integration) docs. -## Adding a new package +## Release -To add a new package add a folder. The naming convention is `[CHAIN]-[PROTOCOL_SYSTEM]`. +To release a package simply tag a commit with the package name and its version: +e.g. `ethereum-balancer-0.1.0`. This will create a release and automatically build +and push the spkg into our registry. -### Manifest -In this new folder add a manifest file `substreams.yaml`. You can use the template below to get started: +### Note +The CD pipeline will error if the Cargo version is not the same as the version in +the tag. -```yaml -specVersion: v0.1.0 -package: - name: 'substreams_[CHAIN]_[PROTOCOL_SYSTEM]' - version: v0.1.0 +Releases are immutable so do no try to delete tags or build the same release twice +since this will error. -protobuf: - files: - - vm.proto - - common.proto - # You can specify any internal proto files here - importPaths: - - ../../proto/tycho/evm/v1/ - # Any private message types only used in internal modules - # can remain local to the folder. - - ./proto +### Pre release -binaries: - default: - type: wasm/rust-v1 - # this points to the workspace target directory we use a special - # substreams build profile to optimise wasm binaries - file: ../../target/wasm32-unknown-unknown/substreams/substreams_[CHAIN]_[PROTOCOL_SYSTEM].wasm +To create a pre release for testing in dev you can start CD pipeline manually supplying +the package you'd like to pre release. This will create a +`[package]-[semver].pre-[commit-sha]` release in our spkg repository which you can use +to run the substream´. -modules: - - name: map_changes - kind: map - inputs: - - source: sf.ethereum.type.v2.Block - output: - type: proto:tycho.evm.state.v1.BlockContractChanges -``` - -Substreams packages are Rust crates so we also need a `cargo.toml`. -The example from the official docs will serve us just well: - -```toml -[package] -name = "substreams_[CHAIN]_[PROTOCOL_SYSTEM]" -version = "0.1.0" -edition = "2021" - -[lib] -name = "substreams_[CHAIN]_[PROTOCOL_SYSTEM]" -crate-type = ["cdylib"] - -[dependencies] -substreams = "0.5" -substreams-ethereum = "0.9" -prost = "0.11" - -``` - -There are already some generated rust files in the `src/pb` directory. These are generated -from the protobuf files in the `/proto/tycho/evm/v1` directory. They specify the output protobuf messages -we want to generate. The input Block is specified by the subtreams crate, specifically the [sf.ethereum.type.v2.Block](https://github.com/streamingfast/substreams-ethereum/blob/develop/core/src/pb/sf.ethereum.type.v2.rs) message. - -You can define your own protobuf messages, make a new directory `/substreams/[CHAIN]-[PROTOCOL]/proto` for them. - - -Now we can generate the Rust protobuf code: - -``` -substreams protogen substreams.yaml --exclude-paths="sf/substreams,google" -``` - -The command above should put the generate rust files under `/src/pb`. You -can start using these now in your module handlers: See -the [official substreams documentation](https://thegraph.com/docs/en/substreams/getting-started/quickstart/#create-substreams-module-handlers) -on -how to implement module handlers. - -You can also look into already existing substreams packages to see how it -is done. E.g. [ethereum-ambient](./ethereum-ambient/) provides a pretty good -example of how to get access to raw contract storage. - -# Tests - -To create a block test asset for ethereum do the following: - -- Follow [this tutorial](https://substreams.streamingfast.io/tutorials/overview/map_block_meta_module). Make sure you - set up the substreams-explorer repo in the same directory as this repo. - - Comment out `image: ./ethereum.png` in `ethereum-explorer/substreams.yaml` - - Add `prost-types = "0.11.0"` to `ethereum-explorer/Cargo.toml` -- Make sure you set up your key env vars. -- Run `sh scripts/download-ethereum-block-to-s3 BLOCK_NUMBER` - -Do not commit the block files (they are quite big). \ No newline at end of file diff --git a/substreams/check.sh b/substreams/check.sh new file mode 100755 index 0000000..1821d18 --- /dev/null +++ b/substreams/check.sh @@ -0,0 +1,6 @@ +set -e + +cargo +nightly fmt -- --check +cargo +nightly clippy --all --all-features --all-targets -- -D warnings +cargo build --target wasm32-unknown-unknown --all-targets --all-features +cargo test --workspace --all-targets --all-features diff --git a/substreams/crates/tycho-substreams/Cargo.toml b/substreams/crates/tycho-substreams/Cargo.toml new file mode 100644 index 0000000..3908f81 --- /dev/null +++ b/substreams/crates/tycho-substreams/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "tycho-substreams" +version = "0.1.0" +edition = "2021" + +[dependencies] +substreams-ethereum.workspace = true +substreams.workspace = true +prost.workspace = true +hex.workspace = true +itertools = "0.12.0" \ No newline at end of file diff --git a/substreams/crates/tycho-substreams/Readme.md b/substreams/crates/tycho-substreams/Readme.md new file mode 100644 index 0000000..20f868b --- /dev/null +++ b/substreams/crates/tycho-substreams/Readme.md @@ -0,0 +1,18 @@ +# Tycho Substreams SDK + +Some shared functionality that is used to create tycho substream packages. + +## Protobuf Models + +Protobuf models are manually synced from the `tycho-indexer` repository whenever they +changed. + +To generate the rust structs run the following command from within the `./proto` +directory: + +```bash +buf generate \ + --path tycho \ + --template ../substreams/crates/tycho-substreams/buf.gen.yaml \ + --output ../substreams/crates/tycho-substreams/ +``` \ No newline at end of file diff --git a/substreams/crates/tycho-substreams/buf.gen.yaml b/substreams/crates/tycho-substreams/buf.gen.yaml new file mode 100644 index 0000000..07f4f81 --- /dev/null +++ b/substreams/crates/tycho-substreams/buf.gen.yaml @@ -0,0 +1,12 @@ +version: v1 +plugins: + - plugin: buf.build/community/neoeinstein-prost:v0.2.2 + out: src/pb + opt: + - file_descriptor_set=false + - type_attribute=.tycho.evm.v1.Transaction=#[derive(Eq\, Hash)] + + - plugin: buf.build/community/neoeinstein-prost-crate:v0.3.1 + out: src/pb + opt: + - no_features diff --git a/substreams/crates/tycho-substreams/src/balances.rs b/substreams/crates/tycho-substreams/src/balances.rs new file mode 100644 index 0000000..707f60d --- /dev/null +++ b/substreams/crates/tycho-substreams/src/balances.rs @@ -0,0 +1,380 @@ +//! Module for Handling Relative Balance Changes. +//! +//! This module facilitates the conversion of relative balance changes into absolute balances, +//! employing a structured approach to ensure the accurate representation of balance data. +//! +//! Process Overview: +//! +//! 1. **Mapping (User-Implemented)**: The initial step requires the user to implement a mapping +//! function that extracts `BlockBalanceDeltas` messages. It's crucial that `BalanceDelta` +//! messages within these messages have strictly increasing ordinals, which guarantees the order +//! of balance changes is preserved and unambiguous. This step is not provided by the SDK and +//! must be custom-implemented to suit the specific protocol. +//! +//! 2. **Storing Changes**: Utilize the `store_balance_changes` function to apply relative balance +//! changes. This function handles changes additively, preparing them for final aggregation. +//! +//! 3. **Aggregation**: Use the `aggregate_balance_changes` function to compile the processed +//! changes into a detailed map of absolute balances. This final step produces the comprehensive +//! balance data ready for output modules or further analysis. +//! +//! Through this sequence, the module ensures the transformation from relative to absolute +//! balances is conducted with high fidelity, upholding the integrity of transactional data. + +use crate::pb::tycho::evm::v1::{BalanceChange, BlockBalanceDeltas, Transaction}; +use itertools::Itertools; +use std::{collections::HashMap, str::FromStr}; +use substreams::{ + key, + pb::substreams::StoreDeltas, + prelude::{BigInt, StoreAdd}, +}; + +/// Stores relative balance changes in an additive manner. +/// +/// Aggregates the relative balance changes from a `BlockBalanceDeltas` message into the store +/// in an additive way. This function ensures that balance changes are applied correctly +/// according to the order specified by their ordinal values. Each token's balance changes +/// must have strictly increasing ordinals; otherwise, the function will panic. +/// +/// This method is designed to work in conjunction with `aggregate_balances_changes`, +/// which consumes the data stored by this function. The stored data is intended for use +/// in a "deltas mode" processing pattern, as described in the +/// [Substreams documentation](https://substreams.streamingfast.io/documentation/develop/manifest-modules/types#deltas-mode). +/// +/// ## Arguments +/// * `deltas` - A `BlockBalanceDeltas` message containing the relative balance changes. It is +/// crucial that the relative balance deltas for each token address have strictly increasing +/// ordinals; the function will panic otherwise. +/// * `store` - An implementation of the `StoreAdd` trait that will be used to add relative balance +/// changes. This store should support the addition of `BigInt` values. +/// +/// ## Panics +/// This function will panic if: +/// - The `component_id` of any delta is not valid UTF-8. +/// - The ordinals for any given token address are not strictly increasing. +pub fn store_balance_changes(deltas: BlockBalanceDeltas, store: impl StoreAdd) { + let mut previous_ordinal = HashMap::::new(); + deltas + .balance_deltas + .iter() + .for_each(|delta| { + let balance_key = format!( + "{0}:{1}", + String::from_utf8(delta.component_id.clone()) + .expect("delta.component_id is not valid utf-8!"), + hex::encode(&delta.token) + ); + let current_ord = delta.ord; + previous_ordinal + .entry(balance_key.clone()) + .and_modify(|ord| { + // ordinals must arrive in increasing order + if *ord >= current_ord { + panic!( + "Invalid ordinal sequence for {}: {} >= {}", + balance_key, *ord, current_ord + ); + } + *ord = current_ord; + }) + .or_insert(delta.ord); + store.add(delta.ord, balance_key, BigInt::from_signed_bytes_be(&delta.delta)); + }); +} + +type TxAggregatedBalances = HashMap, (Transaction, HashMap, BalanceChange>)>; + +/// Aggregates absolute balances per transaction and token. +/// +/// ## Arguments +/// * `balance_store` - A `StoreDeltas` with all changes that occured in the source store module. +/// * `deltas` - A `BlockBalanceDeltas` message containing the relative balances changes. +/// +/// This function reads absolute balance values from an additive store (see `store_balance_changes` +/// for how to create such a store). It zips these values with the relative balance deltas to +/// associate balance values with tokens and components, ensuring the last balance change per token +/// per transaction is kept if there are multiple changes. Negative balances are set to 0, adhering +/// to the expectation that absolute balances must be non-negative. +/// +/// Will keep the last balance change per token per transaction if there are multiple +/// changes. In case a balance ends up being negative, it will be clipped to 0 since +/// absolute balances are expected to be either zero or positive. +/// +/// ## Panics +/// May panic if the store deltas values are not in the correct format. Values are +/// expected to be utf-8 encoded string integers, which is the default behaviour +/// for substreams stores. +/// +/// ## Returns +/// A map of transactions hashes to a tuple of `Transaction` and aggregated +/// absolute balance changes. +pub fn aggregate_balances_changes( + balance_store: StoreDeltas, + deltas: BlockBalanceDeltas, +) -> TxAggregatedBalances { + balance_store + .deltas + .into_iter() + .zip(deltas.balance_deltas) + .map(|(store_delta, balance_delta)| { + let component_id = key::segment_at(&store_delta.key, 0); + let token_id = key::segment_at(&store_delta.key, 1); + // store_delta.new_value is an ASCII string representing an integer + let ascii_string = + String::from_utf8(store_delta.new_value.clone()).expect("Invalid UTF-8 sequence"); + let balance = BigInt::from_str(&ascii_string).expect("Failed to parse integer"); + + // If the absolute balance is negative, we set it to zero. + let big_endian_bytes_balance = if balance < BigInt::zero() { + BigInt::zero().to_bytes_be().1 + } else { + balance.to_bytes_be().1 + }; + + ( + balance_delta + .tx + .expect("Missing transaction on delta"), + BalanceChange { + token: hex::decode(token_id).expect("Token ID not valid hex"), + balance: big_endian_bytes_balance, + component_id: component_id.as_bytes().to_vec(), + }, + ) + }) + // We need to group the balance changes by tx hash for the `TransactionContractChanges` agg + .group_by(|(tx, _)| tx.hash.clone()) + .into_iter() + .map(|(txh, group)| { + let (mut transactions, balance_changes): (Vec<_>, Vec<_>) = group.into_iter().unzip(); + + let balances = balance_changes + .into_iter() + .map(|balance_change| (balance_change.token.clone(), balance_change)) + .collect(); + (txh, (transactions.pop().unwrap(), balances)) + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{mock_store::MockStore, pb::tycho::evm::v1::BalanceDelta}; + use substreams::{ + pb::substreams::StoreDelta, + prelude::{StoreGet, StoreNew}, + }; + + fn block_balance_deltas() -> BlockBalanceDeltas { + let comp_id = "0x42c0ffee" + .to_string() + .as_bytes() + .to_vec(); + let token_0 = hex::decode("bad999").unwrap(); + let token_1 = hex::decode("babe00").unwrap(); + BlockBalanceDeltas { + balance_deltas: vec![ + BalanceDelta { + ord: 0, + tx: Some(Transaction { + hash: vec![0, 1], + from: vec![9, 9], + to: vec![8, 8], + index: 0, + }), + token: token_0.clone(), + delta: BigInt::from_str("+1000") + .unwrap() + .to_signed_bytes_be(), + component_id: comp_id.clone(), + }, + BalanceDelta { + ord: 2, + tx: Some(Transaction { + hash: vec![0, 1], + from: vec![9, 9], + to: vec![8, 8], + index: 0, + }), + token: token_1.clone(), + delta: BigInt::from_str("+100") + .unwrap() + .to_signed_bytes_be(), + component_id: comp_id.clone(), + }, + BalanceDelta { + ord: 3, + tx: Some(Transaction { + hash: vec![0, 1], + from: vec![9, 9], + to: vec![8, 8], + index: 0, + }), + token: token_1.clone(), + delta: BigInt::from_str("50") + .unwrap() + .to_signed_bytes_be(), + component_id: comp_id.clone(), + }, + BalanceDelta { + ord: 10, + tx: Some(Transaction { + hash: vec![0, 1], + from: vec![9, 9], + to: vec![8, 8], + index: 0, + }), + token: token_0.clone(), + delta: BigInt::from_str("-1") + .unwrap() + .to_signed_bytes_be(), + component_id: comp_id.clone(), + }, + ], + } + } + fn store_deltas() -> StoreDeltas { + let comp_id = "0x42c0ffee" + .to_string() + .as_bytes() + .to_vec(); + let token_0 = hex::decode("bad999").unwrap(); + let token_1 = hex::decode("babe00").unwrap(); + + let t0_key = + format!("{}:{}", String::from_utf8(comp_id.clone()).unwrap(), hex::encode(token_0)); + let t1_key = + format!("{}:{}", String::from_utf8(comp_id.clone()).unwrap(), hex::encode(token_1)); + StoreDeltas { + deltas: vec![ + StoreDelta { + operation: 0, + ordinal: 0, + key: t0_key.clone(), + old_value: BigInt::from(0) + .to_string() + .as_bytes() + .to_vec(), + new_value: BigInt::from(1000) + .to_string() + .as_bytes() + .to_vec(), + }, + StoreDelta { + operation: 0, + ordinal: 2, + key: t1_key.clone(), + old_value: BigInt::from(0) + .to_string() + .as_bytes() + .to_vec(), + new_value: BigInt::from(100) + .to_string() + .as_bytes() + .to_vec(), + }, + StoreDelta { + operation: 0, + ordinal: 3, + key: t1_key.clone(), + old_value: BigInt::from(100) + .to_string() + .as_bytes() + .to_vec(), + new_value: BigInt::from(150) + .to_string() + .as_bytes() + .to_vec(), + }, + StoreDelta { + operation: 0, + ordinal: 10, + key: t0_key.clone(), + old_value: BigInt::from(1000) + .to_string() + .as_bytes() + .to_vec(), + new_value: BigInt::from(999) + .to_string() + .as_bytes() + .to_vec(), + }, + ], + } + } + + #[test] + fn test_store_balances() { + let comp_id = "0x42c0ffee" + .to_string() + .as_bytes() + .to_vec(); + let token_0 = hex::decode("bad999").unwrap(); + let token_1 = hex::decode("babe00").unwrap(); + let deltas = block_balance_deltas(); + let store = ::new(); + + store_balance_changes(deltas, store.clone()); + let res_0 = store.get_last(format!( + "{}:{}", + String::from_utf8(comp_id.clone()).unwrap(), + hex::encode(token_0) + )); + let res_1 = store.get_last(format!( + "{}:{}", + String::from_utf8(comp_id.clone()).unwrap(), + hex::encode(token_1) + )); + + assert_eq!(res_0, Some(BigInt::from_str("+999").unwrap())); + assert_eq!(res_1, Some(BigInt::from_str("+150").unwrap())); + } + + #[test] + fn test_aggregate_balances_changes() { + let store_deltas = store_deltas(); + let balance_deltas = block_balance_deltas(); + let comp_id = "0x42c0ffee" + .to_string() + .as_bytes() + .to_vec(); + let token_0 = hex::decode("bad999").unwrap(); + let token_1 = hex::decode("babe00").unwrap(); + + let exp = [( + vec![0, 1], + ( + Transaction { hash: vec![0, 1], from: vec![9, 9], to: vec![8, 8], index: 0 }, + [ + ( + token_0.clone(), + BalanceChange { + token: token_0, + balance: BigInt::from(999) + .to_signed_bytes_be() + .to_vec(), + component_id: comp_id.clone(), + }, + ), + ( + token_1.clone(), + BalanceChange { + token: token_1, + balance: vec![150], + component_id: comp_id.clone(), + }, + ), + ] + .into_iter() + .collect::>(), + ), + )] + .into_iter() + .collect::>(); + + let res = aggregate_balances_changes(store_deltas, balance_deltas); + assert_eq!(res, exp); + } +} diff --git a/substreams/crates/tycho-substreams/src/contract.rs b/substreams/crates/tycho-substreams/src/contract.rs new file mode 100644 index 0000000..250da36 --- /dev/null +++ b/substreams/crates/tycho-substreams/src/contract.rs @@ -0,0 +1,223 @@ +/// Helpers to extract relevant contract storage. +/// +/// This file contains helpers to capture contract changes from the expanded block +/// model. These leverage the `code_changes`, `balance_changes`, and `storage_changes` +/// fields available on the `Call` type provided by block model in a substream +/// (i.e. `logs_and_calls`, etc). +/// +/// ## Warning +/// ⚠️ These helpers *only* work if the **extended block model** is available, +/// more [here](https://streamingfastio.medium.com/new-block-model-to-accelerate-chain-integration-9f65126e5425) +use std::collections::HashMap; + +use substreams_ethereum::pb::{ + eth, + eth::v2::{block::DetailLevel, StorageChange}, +}; + +use crate::pb::tycho::evm::v1::{self as tycho}; + +struct SlotValue { + new_value: Vec, + start_value: Vec, +} + +impl From<&StorageChange> for SlotValue { + fn from(change: &StorageChange) -> Self { + Self { new_value: change.new_value.clone(), start_value: change.old_value.clone() } + } +} + +impl SlotValue { + fn has_changed(&self) -> bool { + self.start_value != self.new_value + } +} + +// Uses a map for slots, protobuf does not allow bytes in hashmap keys +struct InterimContractChange { + address: Vec, + balance: Vec, + code: Vec, + slots: HashMap, SlotValue>, + change: tycho::ChangeType, +} + +impl InterimContractChange { + fn new(address: &[u8], creation: bool) -> Self { + Self { + address: address.to_vec(), + balance: vec![], + code: vec![], + slots: Default::default(), + change: if creation { tycho::ChangeType::Creation } else { tycho::ChangeType::Update }, + } + } +} + +impl From for tycho::ContractChange { + fn from(value: InterimContractChange) -> Self { + tycho::ContractChange { + address: value.address, + balance: value.balance, + code: value.code, + slots: value + .slots + .into_iter() + .filter(|(_, value)| value.has_changed()) + .map(|(slot, value)| tycho::ContractSlot { slot, value: value.new_value }) + .collect(), + change: value.change.into(), + } + } +} + +/// Extracts and aggregates contract changes from a block. +/// +/// This function identifies and collects changes to contract storage, code, and native balance for +/// contracts of interest within a given block. It filters contracts based on a user-defined +/// predicate and aggregates changes into a provided mutable map. +/// +/// ## Arguments +/// * `block` - The block from which to extract contract changes, expected to be an extended block +/// model. +/// * `inclusion_predicate` - A closure that determines if a contract's address is of interest for +/// the collection of changes. Only contracts satisfying this predicate are included. +/// * `transaction_contract_changes` - A mutable reference to a map where extracted contract changes +/// are stored. Keyed by transaction index, it aggregates changes into +/// `tycho::TransactionContractChanges`. +/// +/// ## Panics +/// Panics if the provided block is not an extended block model, as indicated by its detail level. +/// +/// ## Operation +/// The function iterates over transactions and their calls within the block, collecting contract +/// changes (storage, balance, code) that pass the inclusion predicate. Changes are then sorted by +/// their ordinals to maintain the correct sequence of events. Aggregated changes for each contract +/// are stored in `transaction_contract_changes`, categorized by transaction index. +/// +/// Contracts created within the block are tracked to differentiate between new and existing +/// contracts. The aggregation process respects transaction boundaries, ensuring that changes are +/// mapped accurately to their originating transactions. +pub fn extract_contract_changes bool>( + block: ð::v2::Block, + inclusion_predicate: F, + transaction_contract_changes: &mut HashMap, +) { + if block.detail_level != Into::::into(DetailLevel::DetaillevelExtended) { + panic!("Only extended blocks are supported"); + } + let mut changed_contracts: HashMap, InterimContractChange> = HashMap::new(); + + // Collect all accounts created in this block + let created_accounts: HashMap<_, _> = block + .transactions() + .flat_map(|tx| { + tx.calls.iter().flat_map(|call| { + call.account_creations + .iter() + .map(|ac| (&ac.account, ac.ordinal)) + }) + }) + .collect(); + + block + .transactions() + .for_each(|block_tx| { + let mut storage_changes = Vec::new(); + let mut balance_changes = Vec::new(); + let mut code_changes = Vec::new(); + + block_tx + .calls + .iter() + .filter(|call| !call.state_reverted && inclusion_predicate(&call.address)) + .for_each(|call| { + storage_changes.extend(call.storage_changes.iter()); + balance_changes.extend(call.balance_changes.iter()); + code_changes.extend(call.code_changes.iter()); + }); + + storage_changes.sort_unstable_by_key(|change| change.ordinal); + balance_changes.sort_unstable_by_key(|change| change.ordinal); + code_changes.sort_unstable_by_key(|change| change.ordinal); + + storage_changes + .iter() + .filter(|changes| inclusion_predicate(&changes.address)) + .for_each(|&storage_change| { + let contract_change = changed_contracts + .entry(storage_change.address.clone()) + .or_insert_with(|| { + InterimContractChange::new( + &storage_change.address, + created_accounts.contains_key(&storage_change.address), + ) + }); + + let slot_value = contract_change + .slots + .entry(storage_change.key.clone()) + .or_insert_with(|| storage_change.into()); + + slot_value + .new_value + .copy_from_slice(&storage_change.new_value); + }); + + balance_changes + .iter() + .filter(|changes| inclusion_predicate(&changes.address)) + .for_each(|balance_change| { + let contract_change = changed_contracts + .entry(balance_change.address.clone()) + .or_insert_with(|| { + InterimContractChange::new( + &balance_change.address, + created_accounts.contains_key(&balance_change.address), + ) + }); + + if let Some(new_balance) = &balance_change.new_value { + contract_change.balance.clear(); + contract_change + .balance + .extend_from_slice(&new_balance.bytes); + } + }); + + code_changes + .iter() + .filter(|changes| inclusion_predicate(&changes.address)) + .for_each(|code_change| { + let contract_change = changed_contracts + .entry(code_change.address.clone()) + .or_insert_with(|| { + InterimContractChange::new( + &code_change.address, + created_accounts.contains_key(&code_change.address), + ) + }); + + contract_change.code.clear(); + contract_change + .code + .extend_from_slice(&code_change.new_code); + }); + + if !storage_changes.is_empty() || + !balance_changes.is_empty() || + !code_changes.is_empty() + { + transaction_contract_changes + .entry(block_tx.index.into()) + .or_insert_with(|| tycho::TransactionContractChanges::new(&(block_tx.into()))) + .contract_changes + .extend( + changed_contracts + .drain() + .map(|(_, change)| change.into()), + ); + } + }); +} diff --git a/substreams/crates/tycho-substreams/src/lib.rs b/substreams/crates/tycho-substreams/src/lib.rs new file mode 100644 index 0000000..03e9e03 --- /dev/null +++ b/substreams/crates/tycho-substreams/src/lib.rs @@ -0,0 +1,9 @@ +pub mod balances; +pub mod contract; +mod mock_store; +pub mod models; +mod pb; + +pub mod prelude { + pub use super::models::*; +} diff --git a/substreams/crates/tycho-substreams/src/mock_store.rs b/substreams/crates/tycho-substreams/src/mock_store.rs new file mode 100644 index 0000000..70b252b --- /dev/null +++ b/substreams/crates/tycho-substreams/src/mock_store.rs @@ -0,0 +1,95 @@ +//! Contains a mock store for internal testing. +//! +//! Might make this public alter to users can test their store handlers. +use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use substreams::{ + prelude::{BigInt, StoreDelete, StoreGet, StoreNew}, + store::StoreAdd, +}; + +type BigIntStore = HashMap>; + +#[derive(Debug, Clone)] +pub struct MockStore { + data: Rc>, +} + +impl StoreDelete for MockStore { + fn delete_prefix(&self, _ord: i64, prefix: &String) { + self.data + .borrow_mut() + .retain(|k, _| !k.starts_with(prefix)); + } +} + +impl StoreNew for MockStore { + fn new() -> Self { + Self { data: Rc::new(RefCell::new(HashMap::new())) } + } +} + +impl StoreAdd for MockStore { + fn add>(&self, ord: u64, key: K, value: BigInt) { + let mut guard = self.data.borrow_mut(); + guard + .entry(key.as_ref().to_string()) + .and_modify(|v| { + let prev_value = v.last().unwrap().1.clone(); + v.push((ord, prev_value + value.clone())); + }) + .or_insert(vec![(ord, value)]); + } + + fn add_many>(&self, _ord: u64, _keys: &Vec, _value: BigInt) { + todo!() + } +} + +impl StoreGet for MockStore { + fn new(_idx: u32) -> Self { + Self { data: Rc::new(RefCell::new(HashMap::new())) } + } + + fn get_at>(&self, ord: u64, key: K) -> Option { + self.data + .borrow() + .get(&key.as_ref().to_string()) + .map(|v| { + v.iter() + .find(|(current_ord, _)| *current_ord == ord) + .unwrap() + .1 + .clone() + }) + } + + fn get_last>(&self, key: K) -> Option { + self.data + .borrow() + .get(&key.as_ref().to_string()) + .map(|v| v.last().unwrap().1.clone()) + } + + fn get_first>(&self, key: K) -> Option { + self.data + .borrow() + .get(&key.as_ref().to_string()) + .map(|v| v.first().unwrap().1.clone()) + } + + fn has_at>(&self, ord: u64, key: K) -> bool { + self.data + .borrow() + .get(&key.as_ref().to_string()) + .map(|v| v.iter().any(|(v, _)| *v == ord)) + .unwrap_or(false) + } + + fn has_last>(&self, _key: K) -> bool { + todo!() + } + + fn has_first>(&self, _key: K) -> bool { + todo!() + } +} diff --git a/substreams/crates/tycho-substreams/src/models.rs b/substreams/crates/tycho-substreams/src/models.rs new file mode 100644 index 0000000..fa0fa07 --- /dev/null +++ b/substreams/crates/tycho-substreams/src/models.rs @@ -0,0 +1,145 @@ +use substreams_ethereum::pb::eth::v2::{self as sf}; + +// re-export the protobuf types here. +pub use crate::pb::tycho::evm::v1::*; + +impl TransactionContractChanges { + /// Creates a new empty `TransactionContractChanges` instance. + pub fn new(tx: &Transaction) -> Self { + Self { + tx: Some(tx.clone()), + contract_changes: vec![], + component_changes: vec![], + balance_changes: vec![], + } + } +} + +impl From<&sf::TransactionTrace> for Transaction { + fn from(tx: &sf::TransactionTrace) -> Self { + Self { + hash: tx.hash.clone(), + from: tx.from.clone(), + to: tx.to.clone(), + index: tx.index.into(), + } + } +} + +impl From<&sf::Block> for Block { + fn from(block: &sf::Block) -> Self { + Self { + number: block.number, + hash: block.hash.clone(), + parent_hash: block + .header + .as_ref() + .expect("Block header not present") + .parent_hash + .clone(), + ts: block.timestamp_seconds(), + } + } +} + +impl ProtocolComponent { + /// Constructs a new, empty `ProtocolComponent`. + /// + /// Initializes an instance with default values. Use `with_*` methods to populate fields + /// conveniently. + /// + /// ## Parameters + /// - `id`: Identifier for the component. + /// - `tx`: Reference to the associated transaction. + pub fn new(id: &str, tx: &Transaction) -> Self { + Self { + id: id.to_string(), + tokens: Vec::new(), + contracts: Vec::new(), + static_att: Vec::new(), + change: ChangeType::Creation.into(), + protocol_type: None, + tx: Some(tx.clone()), + } + } + + /// Initializes a `ProtocolComponent` with a direct association to a contract. + /// + /// Sets the component's ID to the hex-encoded address with a `0x` prefix and includes the + /// contract in the contracts list. + /// + /// ## Parameters + /// - `id`: Contract address to be encoded and set as the component's ID. + /// - `tx`: Reference to the associated transaction. + pub fn at_contract(id: &[u8], tx: &Transaction) -> Self { + Self { + id: format!("0x{}", hex::encode(id)), + tokens: Vec::new(), + contracts: vec![id.to_vec()], + static_att: Vec::new(), + change: ChangeType::Creation.into(), + protocol_type: None, + tx: Some(tx.clone()), + } + } + + /// Updates the tokens associated with this component. + /// + /// ## Parameters + /// - `tokens`: Slice of byte slices representing the tokens to associate. + pub fn with_tokens>(mut self, tokens: &[B]) -> Self { + self.tokens = tokens + .iter() + .map(|e| e.as_ref().to_vec()) + .collect::>>(); + self + } + + /// Updates the contracts associated with this component. + /// + /// ## Parameters + /// - `contracts`: Slice of byte slices representing the contracts to associate. + pub fn with_contracts>(mut self, contracts: &[B]) -> Self { + self.contracts = contracts + .iter() + .map(|e| e.as_ref().to_vec()) + .collect::>>(); + self + } + + /// Updates the static attributes of this component. + /// + /// Sets the change type to `Creation` for all attributes. + /// + /// ## Parameters + /// - `attributes`: Slice of key-value pairs representing the attributes to set. + pub fn with_attributes, V: AsRef<[u8]>>(mut self, attributes: &[(K, V)]) -> Self { + self.static_att = attributes + .iter() + .map(|(k, v)| Attribute { + name: k.as_ref().to_string(), + value: v.as_ref().to_vec(), + change: ChangeType::Creation.into(), + }) + .collect::>(); + self + } + + /// Designates this component as a swap type within the protocol. + /// + /// Sets the `protocol_type` accordingly, including `financial_type` as `Swap` and leaving + /// `attribute_schema` empty. + /// + /// ## Parameters + /// - `name`: The name of the swap protocol. + /// - `implementation_type`: The implementation type of the protocol. + pub fn as_swap_type(mut self, name: &str, implementation_type: ImplementationType) -> Self { + self.protocol_type = Some(ProtocolType { + name: name.to_string(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: implementation_type.into(), + }); + self + } +} diff --git a/substreams/ethereum-template/src/pb/mod.rs b/substreams/crates/tycho-substreams/src/pb/mod.rs similarity index 100% rename from substreams/ethereum-template/src/pb/mod.rs rename to substreams/crates/tycho-substreams/src/pb/mod.rs diff --git a/substreams/crates/tycho-substreams/src/pb/tycho.evm.v1.rs b/substreams/crates/tycho-substreams/src/pb/tycho.evm.v1.rs new file mode 100644 index 0000000..5409eff --- /dev/null +++ b/substreams/crates/tycho-substreams/src/pb/tycho.evm.v1.rs @@ -0,0 +1,358 @@ +// @generated +// This file contains the proto definitions for Substreams common to all integrations. + +/// A struct describing a block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Block { + /// The blocks hash. + #[prost(bytes="vec", tag="1")] + pub hash: ::prost::alloc::vec::Vec, + /// The parent blocks hash. + #[prost(bytes="vec", tag="2")] + pub parent_hash: ::prost::alloc::vec::Vec, + /// The block number. + #[prost(uint64, tag="3")] + pub number: u64, + /// The block timestamp. + #[prost(uint64, tag="4")] + pub ts: u64, +} +/// A struct describing a transaction. +#[derive(Eq, Hash)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Transaction { + /// The transaction hash. + #[prost(bytes="vec", tag="1")] + pub hash: ::prost::alloc::vec::Vec, + /// The sender of the transaction. + #[prost(bytes="vec", tag="2")] + pub from: ::prost::alloc::vec::Vec, + /// The receiver of the transaction. + #[prost(bytes="vec", tag="3")] + pub to: ::prost::alloc::vec::Vec, + /// The transactions index within the block. + /// TODO: should this be uint32? to match the type from the native substream type? + #[prost(uint64, tag="4")] + pub index: u64, +} +/// A custom struct representing an arbitrary attribute of a protocol component. +/// This is mainly used by the native integration to track the necessary information about the protocol. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Attribute { + /// The name of the attribute. + #[prost(string, tag="1")] + pub name: ::prost::alloc::string::String, + /// The value of the attribute. + #[prost(bytes="vec", tag="2")] + pub value: ::prost::alloc::vec::Vec, + /// The type of change the attribute underwent. + #[prost(enumeration="ChangeType", tag="3")] + pub change: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProtocolType { + #[prost(string, tag="1")] + pub name: ::prost::alloc::string::String, + #[prost(enumeration="FinancialType", tag="2")] + pub financial_type: i32, + #[prost(message, repeated, tag="3")] + pub attribute_schema: ::prost::alloc::vec::Vec, + #[prost(enumeration="ImplementationType", tag="4")] + pub implementation_type: i32, +} +/// A struct describing a part of the protocol. +/// Note: For example this can be a UniswapV2 pair, that tracks the two ERC20 tokens used by the pair, +/// the component would represent a single contract. In case of VM integration, such component would +/// not need any attributes, because all the relevant info would be tracked via storage slots and balance changes. +/// It can also be a wrapping contract, like WETH, that has a constant price, but it allows swapping tokens. +/// This is why the name ProtocolComponent is used instead of "Pool" or "Pair". +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProtocolComponent { + /// A unique identifier for the component within the protocol. + /// Can be e.g. a stringified address or a string describing the trading pair. + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + /// Addresses of the ERC20 tokens used by the component. + #[prost(bytes="vec", repeated, tag="2")] + pub tokens: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + /// Addresses of the contracts used by the component. + /// Usually it is a single contract, but some protocols use multiple contracts. + #[prost(bytes="vec", repeated, tag="3")] + pub contracts: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + /// Attributes of the component. Used mainly be the native integration. + /// The inner ChangeType of the attribute has to match the ChangeType of the ProtocolComponent. + #[prost(message, repeated, tag="4")] + pub static_att: ::prost::alloc::vec::Vec, + /// Type of change the component underwent. + #[prost(enumeration="ChangeType", tag="5")] + pub change: i32, + /// / Represents the functionality of the component. + #[prost(message, optional, tag="6")] + pub protocol_type: ::core::option::Option, + /// Transaction where this component was created + #[prost(message, optional, tag="7")] + pub tx: ::core::option::Option, +} +/// A struct for following the changes of Total Value Locked (TVL) of a protocol component. +/// Note that if a ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. +/// E.g. for UniswapV2 pair WETH/USDC, this tracks the USDC and WETH balance of the pair contract. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceChange { + /// The address of the ERC20 token whose balance changed. + #[prost(bytes="vec", tag="1")] + pub token: ::prost::alloc::vec::Vec, + /// The new balance of the token. Note: it must be a big endian encoded int. + #[prost(bytes="vec", tag="2")] + pub balance: ::prost::alloc::vec::Vec, + /// The id of the component whose TVL is tracked. Note: This MUST be utf8 encoded. + /// If the protocol component includes multiple contracts, the balance change must be aggregated to reflect how much tokens can be traded. + #[prost(bytes="vec", tag="3")] + pub component_id: ::prost::alloc::vec::Vec, +} +/// Enum to specify the type of a change. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ChangeType { + Unspecified = 0, + Update = 1, + Creation = 2, + Deletion = 3, +} +impl ChangeType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ChangeType::Unspecified => "CHANGE_TYPE_UNSPECIFIED", + ChangeType::Update => "CHANGE_TYPE_UPDATE", + ChangeType::Creation => "CHANGE_TYPE_CREATION", + ChangeType::Deletion => "CHANGE_TYPE_DELETION", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "CHANGE_TYPE_UNSPECIFIED" => Some(Self::Unspecified), + "CHANGE_TYPE_UPDATE" => Some(Self::Update), + "CHANGE_TYPE_CREATION" => Some(Self::Creation), + "CHANGE_TYPE_DELETION" => Some(Self::Deletion), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum FinancialType { + Swap = 0, + Lend = 1, + Leverage = 2, + Psm = 3, +} +impl FinancialType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + FinancialType::Swap => "SWAP", + FinancialType::Lend => "LEND", + FinancialType::Leverage => "LEVERAGE", + FinancialType::Psm => "PSM", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SWAP" => Some(Self::Swap), + "LEND" => Some(Self::Lend), + "LEVERAGE" => Some(Self::Leverage), + "PSM" => Some(Self::Psm), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ImplementationType { + Vm = 0, + Custom = 1, +} +impl ImplementationType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ImplementationType::Vm => "VM", + ImplementationType::Custom => "CUSTOM", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "VM" => Some(Self::Vm), + "CUSTOM" => Some(Self::Custom), + _ => None, + } + } +} +// This file contains the definition for the native integration of Substreams. + +/// A component is a set of attributes that are associated with a custom entity. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EntityChanges { + /// A unique identifier of the entity within the protocol. + #[prost(string, tag="1")] + pub component_id: ::prost::alloc::string::String, + /// The set of attributes that are associated with the entity. + #[prost(message, repeated, tag="2")] + pub attributes: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionEntityChanges { + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + #[prost(message, repeated, tag="2")] + pub entity_changes: ::prost::alloc::vec::Vec, + /// An array of newly added components. + #[prost(message, repeated, tag="3")] + pub component_changes: ::prost::alloc::vec::Vec, + /// An array of balance changes to components. + #[prost(message, repeated, tag="4")] + pub balance_changes: ::prost::alloc::vec::Vec, +} +/// A set of transaction changes within a single block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockEntityChanges { + /// The block for which these changes are collectively computed. + #[prost(message, optional, tag="1")] + pub block: ::core::option::Option, + /// The set of transaction changes observed in the specified block. + #[prost(message, repeated, tag="2")] + pub changes: ::prost::alloc::vec::Vec, +} +/// A message containing relative balance changes. +/// +/// Used to track token balances of protocol components in case they are only +/// available as relative values within a block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BalanceDelta { + /// The ordinal of the balance change. Must be unique & deterministic over all balances + /// changes within a block. + #[prost(uint64, tag="1")] + pub ord: u64, + /// The tx hash of the transaction that caused the balance change. + #[prost(message, optional, tag="2")] + pub tx: ::core::option::Option, + /// The address of the ERC20 token whose balance changed. + #[prost(bytes="vec", tag="3")] + pub token: ::prost::alloc::vec::Vec, + /// The delta balance of the token. + #[prost(bytes="vec", tag="4")] + pub delta: ::prost::alloc::vec::Vec, + /// The id of the component whose TVL is tracked. + /// If the protocol component includes multiple contracts, the balance change must be + /// aggregated to reflect how much tokens can be traded. + #[prost(bytes="vec", tag="5")] + pub component_id: ::prost::alloc::vec::Vec, +} +/// A set of balances deltas, usually a group of changes within a single block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockBalanceDeltas { + #[prost(message, repeated, tag="1")] + pub balance_deltas: ::prost::alloc::vec::Vec, +} +/// A message containing protocol components that were created by a single tx. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionProtocolComponents { + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + #[prost(message, repeated, tag="2")] + pub components: ::prost::alloc::vec::Vec, +} +/// All protocol components that were created within a block with their corresponding tx. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockTransactionProtocolComponents { + #[prost(message, repeated, tag="1")] + pub tx_components: ::prost::alloc::vec::Vec, +} +// This file contains proto definitions specific to the VM integration. + +/// A key value entry into contract storage. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ContractSlot { + /// A contract's storage slot. + #[prost(bytes="vec", tag="2")] + pub slot: ::prost::alloc::vec::Vec, + /// The new value for this storage slot. + #[prost(bytes="vec", tag="3")] + pub value: ::prost::alloc::vec::Vec, +} +/// Changes made to a single contract's state. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ContractChange { + /// The contract's address + #[prost(bytes="vec", tag="1")] + pub address: ::prost::alloc::vec::Vec, + /// The new native balance of the contract, empty bytes indicates no change. + #[prost(bytes="vec", tag="2")] + pub balance: ::prost::alloc::vec::Vec, + /// The new code of the contract, empty bytes indicates no change. + #[prost(bytes="vec", tag="3")] + pub code: ::prost::alloc::vec::Vec, + /// The changes to this contract's slots, empty sequence indicates no change. + #[prost(message, repeated, tag="4")] + pub slots: ::prost::alloc::vec::Vec, + /// Whether this is an update, a creation or a deletion. + #[prost(enumeration="ChangeType", tag="5")] + pub change: i32, +} +/// A set of changes aggregated by transaction. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionContractChanges { + /// The transaction instance that results in the changes. + #[prost(message, optional, tag="1")] + pub tx: ::core::option::Option, + /// Contains the changes induced by the above transaction, aggregated on a per-contract basis. + /// Must include changes to every contract that is tracked by all ProtocolComponents. + #[prost(message, repeated, tag="2")] + pub contract_changes: ::prost::alloc::vec::Vec, + /// An array of any component changes. + #[prost(message, repeated, tag="3")] + pub component_changes: ::prost::alloc::vec::Vec, + /// An array of balance changes to components. + #[prost(message, repeated, tag="4")] + pub balance_changes: ::prost::alloc::vec::Vec, +} +/// A set of transaction changes within a single block. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockContractChanges { + /// The block for which these changes are collectively computed. + #[prost(message, optional, tag="1")] + pub block: ::core::option::Option, + /// The set of transaction changes observed in the specified block. + #[prost(message, repeated, tag="2")] + pub changes: ::prost::alloc::vec::Vec, +} +// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-balancer/Cargo.toml b/substreams/ethereum-balancer/Cargo.toml new file mode 100644 index 0000000..2aca957 --- /dev/null +++ b/substreams/ethereum-balancer/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "ethereum-balancer" +version = "0.1.0" +edition = "2021" + +[lib] +name = "ethereum_balancer" +crate-type = ["cdylib"] + +[dependencies] +substreams.workspace = true +substreams-ethereum.workspace = true +prost.workspace = true +prost-types.workspace = true +hex-literal.workspace = true +ethabi.workspace = true +hex.workspace = true +bytes = "1.5.0" +anyhow = "1.0.75" +num-bigint = "0.4.4" +itertools = "0.12.0" +tycho-substreams.workspace = true + +[build-dependencies] +anyhow = "1" +substreams-ethereum = "0.9" + +# Required so that ethabi > ethereum-types build correctly under wasm32-unknown-unknown +[target.wasm32-unknown-unknown.dependencies] +getrandom = { version = "0.2", features = ["custom"] } diff --git a/substreams/ethereum-balancer/abi/README.md b/substreams/ethereum-balancer/abi/README.md new file mode 100644 index 0000000..bcb5ddc --- /dev/null +++ b/substreams/ethereum-balancer/abi/README.md @@ -0,0 +1,22 @@ +# ABIs + +`get_abis.py` is a simple python script using the etherscan API (free plan) to gather ABIs for all of the contracts we are tracking! + +We then can define all of the abis via `substreams_ethereum::Abigen::new` in our `build.rs`. + +## Recommendation + +It would be apt to convert (maybe through copilot) the python code into the `build.rs` file and then automate the `Abigen` functionality. + +## Usage + +Requires `python 3.8+`, + +```bash +cd abi +python get_abis.py +``` + +This will populate the files in the `abi` folder. + +When the `build.rs` file runs (when `rust-analyzer` activates or `cargo build` is manually ran), Abigen will generate new rust src files from the abis in the `src/abi` folder. diff --git a/substreams/ethereum-balancer/abi/composable_stable_pool_factory.json b/substreams/ethereum-balancer/abi/composable_stable_pool_factory.json new file mode 100644 index 0000000..a8eb0fd --- /dev/null +++ b/substreams/ethereum-balancer/abi/composable_stable_pool_factory.json @@ -0,0 +1,283 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "protocolFeeProvider", + "type": "address" + }, + { + "internalType": "string", + "name": "factoryVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "poolVersion", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [], + "name": "FactoryDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "amplificationParameter", + "type": "uint256" + }, + { + "internalType": "contract IRateProvider[]", + "name": "rateProviders", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "tokenRateCacheDurations", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "exemptFromYieldProtocolFeeFlag", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "contract ComposableStablePool", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCodeContracts", + "outputs": [ + { + "internalType": "address", + "name": "contractA", + "type": "address" + }, + { + "internalType": "address", + "name": "contractB", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeePercentagesProvider", + "outputs": [ + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/erc_linear_pool_factory.json b/substreams/ethereum-balancer/abi/erc_linear_pool_factory.json new file mode 100644 index 0000000..caa4a33 --- /dev/null +++ b/substreams/ethereum-balancer/abi/erc_linear_pool_factory.json @@ -0,0 +1,325 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "protocolFeeProvider", + "type": "address" + }, + { + "internalType": "contract IBalancerQueries", + "name": "queries", + "type": "address" + }, + { + "internalType": "string", + "name": "factoryVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "poolVersion", + "type": "string" + }, + { + "internalType": "uint256", + "name": "initialPauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + } + ], + "name": "Erc4626LinearPoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "FactoryDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20", + "name": "mainToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperTarget", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "contract LinearPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCodeContracts", + "outputs": [ + { + "internalType": "address", + "name": "contractA", + "type": "address" + }, + { + "internalType": "address", + "name": "contractB", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastCreatedPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeePercentagesProvider", + "outputs": [ + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/euler_linear_pool_factory.json b/substreams/ethereum-balancer/abi/euler_linear_pool_factory.json new file mode 100644 index 0000000..5c55933 --- /dev/null +++ b/substreams/ethereum-balancer/abi/euler_linear_pool_factory.json @@ -0,0 +1,338 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "protocolFeeProvider", + "type": "address" + }, + { + "internalType": "contract IBalancerQueries", + "name": "queries", + "type": "address" + }, + { + "internalType": "string", + "name": "factoryVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "poolVersion", + "type": "string" + }, + { + "internalType": "uint256", + "name": "initialPauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_eulerProtocol", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + } + ], + "name": "EulerLinearPoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "FactoryDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20", + "name": "mainToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperTarget", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "contract LinearPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "eulerProtocol", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCodeContracts", + "outputs": [ + { + "internalType": "address", + "name": "contractA", + "type": "address" + }, + { + "internalType": "address", + "name": "contractB", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastCreatedPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeePercentagesProvider", + "outputs": [ + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/gearbox_linear_pool_factory.json b/substreams/ethereum-balancer/abi/gearbox_linear_pool_factory.json new file mode 100644 index 0000000..e314f94 --- /dev/null +++ b/substreams/ethereum-balancer/abi/gearbox_linear_pool_factory.json @@ -0,0 +1,325 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "protocolFeeProvider", + "type": "address" + }, + { + "internalType": "contract IBalancerQueries", + "name": "queries", + "type": "address" + }, + { + "internalType": "string", + "name": "factoryVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "poolVersion", + "type": "string" + }, + { + "internalType": "uint256", + "name": "initialPauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [], + "name": "FactoryDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + } + ], + "name": "GearboxLinearPoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20", + "name": "mainToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperTarget", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "contract GearboxLinearPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCodeContracts", + "outputs": [ + { + "internalType": "address", + "name": "contractA", + "type": "address" + }, + { + "internalType": "address", + "name": "contractB", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastCreatedPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeePercentagesProvider", + "outputs": [ + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/get_abis.py b/substreams/ethereum-balancer/abi/get_abis.py new file mode 100644 index 0000000..6935391 --- /dev/null +++ b/substreams/ethereum-balancer/abi/get_abis.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +import json +import os +import re +import time +import urllib.request + +# Exports contract ABI in JSON + +abis = { + # Factories + "WeightedPoolFactory (v4)": "0x897888115Ada5773E02aA29F775430BFB5F34c51", + "WeightedPool2TokensFactory": "0xA5bf2ddF098bb0Ef6d120C98217dD6B141c74EE0", # 80Bal-20WETH + "ComposableStablePoolFactory (v5)": "0xDB8d758BCb971e482B2C45f7F8a7740283A1bd3A", + "ERC4626LinearPoolFactory (v4)": "0x813EE7a840CE909E7Fea2117A44a90b8063bd4fd", + "EulerLinearPoolFactory": "0x5F43FBa61f63Fa6bFF101a0A0458cEA917f6B347", + # "GearboxLinearPoolFactory (v2)": "0x39A79EB449Fc05C92c39aA6f0e9BfaC03BE8dE5B", + "ManagedPoolFactory (v2)": "0xBF904F9F340745B4f0c4702c7B6Ab1e808eA6b93", + "SiloLinearPoolFactory (v2)": "0x4E11AEec21baF1660b1a46472963cB3DA7811C89", + "YearnLinearPoolFactory (v2)": "0x5F5222Ffa40F2AEd6380D022184D6ea67C776eE0", + # Vault + "Vault": "0xBA12222222228d8Ba445958a75a0704d566BF2C8", +} + +ABI_ENDPOINT = ( + "https://api.etherscan.io/api?module=contract&action=getabi&address={address}" +) + +if etherscan_key := os.environ.get("ETHERSCAN_API_TOKEN"): + print("API KEY Loaded!") + ABI_ENDPOINT += f"&apikey={etherscan_key}" + + +def __main__(): + for name, addr in abis.items(): + normalized_name = "_".join(re.findall(r"[A-Z]+[a-z]*", name)).lower() + print(f"Getting ABI for {name} at {addr} ({normalized_name})") + + try: + with urllib.request.urlopen(ABI_ENDPOINT.format(address=addr)) as response: + response_json = json.loads(response.read().decode()) + abi_json = json.loads(response_json["result"]) + result = json.dumps(abi_json, indent=4, sort_keys=True) + with open(f"{normalized_name}.json", "w") as f: + f.write(result) + except Exception as err: + print(response.content) + raise err + time.sleep(0.25) + + +if __name__ == "__main__": + __main__() diff --git a/substreams/ethereum-balancer/abi/managed_pool_factory.json b/substreams/ethereum-balancer/abi/managed_pool_factory.json new file mode 100644 index 0000000..76ae0ed --- /dev/null +++ b/substreams/ethereum-balancer/abi/managed_pool_factory.json @@ -0,0 +1,353 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "protocolFeeProvider", + "type": "address" + }, + { + "internalType": "contract IExternalWeightedMath", + "name": "externalWeightedMath", + "type": "address" + }, + { + "internalType": "contract IRecoveryModeHelper", + "name": "recoveryModeHelper", + "type": "address" + }, + { + "internalType": "string", + "name": "factoryVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "poolVersion", + "type": "string" + }, + { + "internalType": "uint256", + "name": "initialPauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [], + "name": "FactoryDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address[]", + "name": "assetManagers", + "type": "address[]" + } + ], + "internalType": "struct ManagedPool.ManagedPoolParams", + "name": "params", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "normalizedWeights", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "swapEnabledOnStart", + "type": "bool" + }, + { + "internalType": "bool", + "name": "mustAllowlistLPs", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "managementAumFeePercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "aumFeeId", + "type": "uint256" + } + ], + "internalType": "struct ManagedPoolSettings.ManagedPoolSettingsParams", + "name": "settingsParams", + "type": "tuple" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCodeContracts", + "outputs": [ + { + "internalType": "address", + "name": "contractA", + "type": "address" + }, + { + "internalType": "address", + "name": "contractB", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeePercentagesProvider", + "outputs": [ + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRecoveryModeHelper", + "outputs": [ + { + "internalType": "contract IRecoveryModeHelper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWeightedMath", + "outputs": [ + { + "internalType": "contract IExternalWeightedMath", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/silo_linear_pool_factory.json b/substreams/ethereum-balancer/abi/silo_linear_pool_factory.json new file mode 100644 index 0000000..8df940f --- /dev/null +++ b/substreams/ethereum-balancer/abi/silo_linear_pool_factory.json @@ -0,0 +1,325 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "protocolFeeProvider", + "type": "address" + }, + { + "internalType": "contract IBalancerQueries", + "name": "queries", + "type": "address" + }, + { + "internalType": "string", + "name": "factoryVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "poolVersion", + "type": "string" + }, + { + "internalType": "uint256", + "name": "initialPauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [], + "name": "FactoryDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + } + ], + "name": "SiloLinearPoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20", + "name": "mainToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperTarget", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "contract SiloLinearPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCodeContracts", + "outputs": [ + { + "internalType": "address", + "name": "contractA", + "type": "address" + }, + { + "internalType": "address", + "name": "contractB", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastCreatedPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeePercentagesProvider", + "outputs": [ + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/vault.json b/substreams/ethereum-balancer/abi/vault.json new file mode 100644 index 0000000..79d8dd8 --- /dev/null +++ b/substreams/ethereum-balancer/abi/vault.json @@ -0,0 +1,1179 @@ +[ + { + "inputs": [ + { + "internalType": "contract IAuthorizer", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "contract IWETH", + "name": "weth", + "type": "address" + }, + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IAuthorizer", + "name": "newAuthorizer", + "type": "address" + } + ], + "name": "AuthorizerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ExternalBalanceTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IFlashLoanRecipient", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + } + ], + "name": "FlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "int256", + "name": "delta", + "type": "int256" + } + ], + "name": "InternalBalanceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "PausedStateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "liquidityProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "int256[]", + "name": "deltas", + "type": "int256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "protocolFeeAmounts", + "type": "uint256[]" + } + ], + "name": "PoolBalanceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "assetManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "int256", + "name": "cashDelta", + "type": "int256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "managedDelta", + "type": "int256" + } + ], + "name": "PoolBalanceManaged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "poolAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum IVault.PoolSpecialization", + "name": "specialization", + "type": "uint8" + } + ], + "name": "PoolRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "relayer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "RelayerApprovalChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "TokensDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "assetManagers", + "type": "address[]" + } + ], + "name": "TokensRegistered", + "type": "event" + }, + { + "inputs": [], + "name": "WETH", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "assetInIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "assetOutIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IVault.BatchSwapStep[]", + "name": "swaps", + "type": "tuple[]" + }, + { + "internalType": "contract IAsset[]", + "name": "assets", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.FundManagement", + "name": "funds", + "type": "tuple" + }, + { + "internalType": "int256[]", + "name": "limits", + "type": "int256[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "batchSwap", + "outputs": [ + { + "internalType": "int256[]", + "name": "assetDeltas", + "type": "int256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "deregisterTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract IAsset[]", + "name": "assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "minAmountsOut", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.ExitPoolRequest", + "name": "request", + "type": "tuple" + } + ], + "name": "exitPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IFlashLoanRecipient", + "name": "recipient", + "type": "address" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "flashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDomainSeparator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getInternalBalance", + "outputs": [ + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getNextNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPausedState", + "outputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "pauseWindowEndTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodEndTime", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + } + ], + "name": "getPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum IVault.PoolSpecialization", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "name": "getPoolTokenInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "managed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "address", + "name": "assetManager", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + } + ], + "name": "getPoolTokens", + "outputs": [ + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeesCollector", + "outputs": [ + { + "internalType": "contract ProtocolFeesCollector", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "relayer", + "type": "address" + } + ], + "name": "hasApprovedRelayer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract IAsset[]", + "name": "assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "maxAmountsIn", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.JoinPoolRequest", + "name": "request", + "type": "tuple" + } + ], + "name": "joinPool", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IVault.PoolBalanceOpKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct IVault.PoolBalanceOp[]", + "name": "ops", + "type": "tuple[]" + } + ], + "name": "managePoolBalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IVault.UserBalanceOpKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "contract IAsset", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "internalType": "struct IVault.UserBalanceOp[]", + "name": "ops", + "type": "tuple[]" + } + ], + "name": "manageUserBalance", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "assetInIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "assetOutIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IVault.BatchSwapStep[]", + "name": "swaps", + "type": "tuple[]" + }, + { + "internalType": "contract IAsset[]", + "name": "assets", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.FundManagement", + "name": "funds", + "type": "tuple" + } + ], + "name": "queryBatchSwap", + "outputs": [ + { + "internalType": "int256[]", + "name": "", + "type": "int256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IVault.PoolSpecialization", + "name": "specialization", + "type": "uint8" + } + ], + "name": "registerPool", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "assetManagers", + "type": "address[]" + } + ], + "name": "registerTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IAuthorizer", + "name": "newAuthorizer", + "type": "address" + } + ], + "name": "setAuthorizer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "relayer", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setRelayerApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "contract IAsset", + "name": "assetIn", + "type": "address" + }, + { + "internalType": "contract IAsset", + "name": "assetOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IVault.SingleSwap", + "name": "singleSwap", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.FundManagement", + "name": "funds", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "amountCalculated", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/weighted_pool_factory.json b/substreams/ethereum-balancer/abi/weighted_pool_factory.json new file mode 100644 index 0000000..eae16ae --- /dev/null +++ b/substreams/ethereum-balancer/abi/weighted_pool_factory.json @@ -0,0 +1,273 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "protocolFeeProvider", + "type": "address" + }, + { + "internalType": "string", + "name": "factoryVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "poolVersion", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [], + "name": "FactoryDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "normalizedWeights", + "type": "uint256[]" + }, + { + "internalType": "contract IRateProvider[]", + "name": "rateProviders", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCodeContracts", + "outputs": [ + { + "internalType": "address", + "name": "contractA", + "type": "address" + }, + { + "internalType": "address", + "name": "contractB", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeePercentagesProvider", + "outputs": [ + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/weighted_pool_tokens_factory.json b/substreams/ethereum-balancer/abi/weighted_pool_tokens_factory.json new file mode 100644 index 0000000..9fc8cf2 --- /dev/null +++ b/substreams/ethereum-balancer/abi/weighted_pool_tokens_factory.json @@ -0,0 +1,125 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "weights", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "oracleEnabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/abi/yearn_linear_pool_factory.json b/substreams/ethereum-balancer/abi/yearn_linear_pool_factory.json new file mode 100644 index 0000000..bd5465d --- /dev/null +++ b/substreams/ethereum-balancer/abi/yearn_linear_pool_factory.json @@ -0,0 +1,325 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "protocolFeeProvider", + "type": "address" + }, + { + "internalType": "contract IBalancerQueries", + "name": "queries", + "type": "address" + }, + { + "internalType": "string", + "name": "factoryVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "poolVersion", + "type": "string" + }, + { + "internalType": "uint256", + "name": "initialPauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [], + "name": "FactoryDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + } + ], + "name": "YearnLinearPoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20", + "name": "mainToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperTarget", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolId", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "contract LinearPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCreationCodeContracts", + "outputs": [ + { + "internalType": "address", + "name": "contractA", + "type": "address" + }, + { + "internalType": "address", + "name": "contractB", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastCreatedPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPauseConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeePercentagesProvider", + "outputs": [ + { + "internalType": "contract IProtocolFeePercentagesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/substreams/ethereum-balancer/buf.gen.yaml b/substreams/ethereum-balancer/buf.gen.yaml new file mode 100644 index 0000000..d2e6544 --- /dev/null +++ b/substreams/ethereum-balancer/buf.gen.yaml @@ -0,0 +1,12 @@ + +version: v1 +plugins: +- plugin: buf.build/community/neoeinstein-prost:v0.2.2 + out: src/pb + opt: + - file_descriptor_set=false + +- plugin: buf.build/community/neoeinstein-prost-crate:v0.3.1 + out: src/pb + opt: + - no_features diff --git a/substreams/ethereum-balancer/build.rs b/substreams/ethereum-balancer/build.rs new file mode 100644 index 0000000..90e1f1e --- /dev/null +++ b/substreams/ethereum-balancer/build.rs @@ -0,0 +1,44 @@ +use anyhow::Result; +use std::{fs, io::Write}; +use substreams_ethereum::Abigen; + +fn main() -> Result<()> { + let abi_folder = "abi"; + let output_folder = "src/abi"; + + let files = fs::read_dir(abi_folder)?; + let mut mod_rs_content = String::new(); + mod_rs_content.push_str("#![allow(clippy::all)]\n"); + + for file in files { + let file = file?; + let file_name = file.file_name(); + let file_name = file_name.to_string_lossy(); + + if !file_name.ends_with(".json") { + continue; + } + + let contract_name = file_name.split('.').next().unwrap(); + + let input_path = format!("{}/{}", abi_folder, file_name); + let output_path = format!("{}/{}.rs", output_folder, contract_name); + + mod_rs_content.push_str(&format!("pub mod {};\n", contract_name)); + + if std::path::Path::new(&output_path).exists() { + continue; + } + + Abigen::new(contract_name, &input_path)? + .generate()? + .write_to_file(&output_path)?; + } + + let mod_rs_path = format!("{}/mod.rs", output_folder); + let mut mod_rs_file = fs::File::create(mod_rs_path)?; + + mod_rs_file.write_all(mod_rs_content.as_bytes())?; + + Ok(()) +} diff --git a/substreams/ethereum-balancer/src/abi/composable_stable_pool_factory.rs b/substreams/ethereum-balancer/src/abi/composable_stable_pool_factory.rs new file mode 100644 index 0000000..0d2a930 --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/composable_stable_pool_factory.rs @@ -0,0 +1,1545 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub name: String, + pub symbol: String, + pub tokens: Vec>, + pub amplification_parameter: substreams::scalar::BigInt, + pub rate_providers: Vec>, + pub token_rate_cache_durations: Vec, + pub exempt_from_yield_protocol_fee_flag: bool, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub owner: Vec, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [151u8, 30u8, 24u8, 51u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Bool, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + amplification_parameter: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + rate_providers: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + token_rate_cache_durations: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + exempt_from_yield_protocol_fee_flag: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + swap_fee_percentage: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + salt: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + { + let v = self + .tokens + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amplification_parameter.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + { + let v = self + .rate_providers + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + { + let v = self + .token_rate_cache_durations + .iter() + .map(|inner| ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match inner.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + )) + .collect(); + ethabi::Token::Array(v) + }, + ethabi::Token::Bool( + self.exempt_from_yield_protocol_fee_flag.clone(), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.swap_fee_percentage.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::FixedBytes(self.salt.as_ref().to_vec()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Disable {} + impl Disable { + const METHOD_ID: [u8; 4] = [47u8, 39u8, 112u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for Disable { + const NAME: &'static str = "disable"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCode {} + impl GetCreationCode { + const METHOD_ID: [u8; 4] = [0u8, 193u8, 148u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bytes], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bytes() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCode { + const NAME: &'static str = "getCreationCode"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetCreationCode { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCodeContracts {} + impl GetCreationCodeContracts { + const METHOD_ID: [u8; 4] = [23u8, 68u8, 129u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, Vec), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<(Vec, Vec)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCodeContracts { + const NAME: &'static str = "getCreationCodeContracts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<(Vec, Vec)> + for GetCreationCodeContracts { + fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolVersion {} + impl GetPoolVersion { + const METHOD_ID: [u8; 4] = [63u8, 129u8, 155u8, 111u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolVersion { + const NAME: &'static str = "getPoolVersion"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for GetPoolVersion { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeePercentagesProvider {} + impl GetProtocolFeePercentagesProvider { + const METHOD_ID: [u8; 4] = [115u8, 146u8, 56u8, 214u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeePercentagesProvider { + const NAME: &'static str = "getProtocolFeePercentagesProvider"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeePercentagesProvider { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsDisabled {} + impl IsDisabled { + const METHOD_ID: [u8; 4] = [108u8, 87u8, 245u8, 169u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsDisabled { + const NAME: &'static str = "isDisabled"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsDisabled { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Version {} + impl Version { + const METHOD_ID: [u8; 4] = [84u8, 253u8, 77u8, 80u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Version { + const NAME: &'static str = "version"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Version { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct FactoryDisabled {} + impl FactoryDisabled { + const TOPIC_ID: [u8; 32] = [ + 67u8, + 42u8, + 203u8, + 253u8, + 102u8, + 45u8, + 187u8, + 93u8, + 139u8, + 55u8, + 131u8, + 132u8, + 166u8, + 113u8, + 89u8, + 180u8, + 124u8, + 169u8, + 208u8, + 241u8, + 183u8, + 159u8, + 151u8, + 207u8, + 100u8, + 207u8, + 133u8, + 133u8, + 250u8, + 54u8, + 45u8, + 80u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self {}) + } + } + impl substreams_ethereum::Event for FactoryDisabled { + const NAME: &'static str = "FactoryDisabled"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/erc_linear_pool_factory.rs b/substreams/ethereum-balancer/src/abi/erc_linear_pool_factory.rs new file mode 100644 index 0000000..5905670 --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/erc_linear_pool_factory.rs @@ -0,0 +1,1689 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub name: String, + pub symbol: String, + pub main_token: Vec, + pub wrapped_token: Vec, + pub upper_target: substreams::scalar::BigInt, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub owner: Vec, + pub protocol_id: substreams::scalar::BigInt, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [118u8, 137u8, 91u8, 231u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + main_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + wrapped_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + upper_target: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + swap_fee_percentage: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + salt: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.main_token), + ), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.wrapped_token), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.upper_target.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.swap_fee_percentage.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.protocol_id.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::FixedBytes(self.salt.as_ref().to_vec()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Disable {} + impl Disable { + const METHOD_ID: [u8; 4] = [47u8, 39u8, 112u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for Disable { + const NAME: &'static str = "disable"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCode {} + impl GetCreationCode { + const METHOD_ID: [u8; 4] = [0u8, 193u8, 148u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bytes], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bytes() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCode { + const NAME: &'static str = "getCreationCode"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetCreationCode { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCodeContracts {} + impl GetCreationCodeContracts { + const METHOD_ID: [u8; 4] = [23u8, 68u8, 129u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, Vec), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<(Vec, Vec)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCodeContracts { + const NAME: &'static str = "getCreationCodeContracts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<(Vec, Vec)> + for GetCreationCodeContracts { + fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetLastCreatedPool {} + impl GetLastCreatedPool { + const METHOD_ID: [u8; 4] = [94u8, 211u8, 18u8, 130u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetLastCreatedPool { + const NAME: &'static str = "getLastCreatedPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetLastCreatedPool { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolVersion {} + impl GetPoolVersion { + const METHOD_ID: [u8; 4] = [63u8, 129u8, 155u8, 111u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolVersion { + const NAME: &'static str = "getPoolVersion"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for GetPoolVersion { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeePercentagesProvider {} + impl GetProtocolFeePercentagesProvider { + const METHOD_ID: [u8; 4] = [115u8, 146u8, 56u8, 214u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeePercentagesProvider { + const NAME: &'static str = "getProtocolFeePercentagesProvider"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeePercentagesProvider { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsDisabled {} + impl IsDisabled { + const METHOD_ID: [u8; 4] = [108u8, 87u8, 245u8, 169u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsDisabled { + const NAME: &'static str = "isDisabled"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsDisabled { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Version {} + impl Version { + const METHOD_ID: [u8; 4] = [84u8, 253u8, 77u8, 80u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Version { + const NAME: &'static str = "version"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Version { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Erc4626LinearPoolCreated { + pub pool: Vec, + pub protocol_id: substreams::scalar::BigInt, + } + impl Erc4626LinearPoolCreated { + const TOPIC_ID: [u8; 32] = [ + 69u8, + 221u8, + 97u8, + 93u8, + 46u8, + 215u8, + 153u8, + 79u8, + 152u8, + 254u8, + 200u8, + 55u8, + 178u8, + 208u8, + 146u8, + 175u8, + 147u8, + 60u8, + 101u8, + 32u8, + 184u8, + 113u8, + 124u8, + 58u8, + 100u8, + 49u8, + 121u8, + 97u8, + 202u8, + 165u8, + 50u8, + 234u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'protocol_id' from topic of type 'uint256': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for Erc4626LinearPoolCreated { + const NAME: &'static str = "Erc4626LinearPoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct FactoryDisabled {} + impl FactoryDisabled { + const TOPIC_ID: [u8; 32] = [ + 67u8, + 42u8, + 203u8, + 253u8, + 102u8, + 45u8, + 187u8, + 93u8, + 139u8, + 55u8, + 131u8, + 132u8, + 166u8, + 113u8, + 89u8, + 180u8, + 124u8, + 169u8, + 208u8, + 241u8, + 183u8, + 159u8, + 151u8, + 207u8, + 100u8, + 207u8, + 133u8, + 133u8, + 250u8, + 54u8, + 45u8, + 80u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self {}) + } + } + impl substreams_ethereum::Event for FactoryDisabled { + const NAME: &'static str = "FactoryDisabled"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/euler_linear_pool_factory.rs b/substreams/ethereum-balancer/src/abi/euler_linear_pool_factory.rs new file mode 100644 index 0000000..afc20e3 --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/euler_linear_pool_factory.rs @@ -0,0 +1,1765 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub name: String, + pub symbol: String, + pub main_token: Vec, + pub wrapped_token: Vec, + pub upper_target: substreams::scalar::BigInt, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub owner: Vec, + pub protocol_id: substreams::scalar::BigInt, + } + impl Create { + const METHOD_ID: [u8; 4] = [223u8, 138u8, 249u8, 137u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + main_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + wrapped_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + upper_target: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + swap_fee_percentage: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.main_token), + ), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.wrapped_token), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.upper_target.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.swap_fee_percentage.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.protocol_id.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Disable {} + impl Disable { + const METHOD_ID: [u8; 4] = [47u8, 39u8, 112u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for Disable { + const NAME: &'static str = "disable"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct EulerProtocol {} + impl EulerProtocol { + const METHOD_ID: [u8; 4] = [82u8, 8u8, 252u8, 43u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for EulerProtocol { + const NAME: &'static str = "eulerProtocol"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for EulerProtocol { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCode {} + impl GetCreationCode { + const METHOD_ID: [u8; 4] = [0u8, 193u8, 148u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bytes], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bytes() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCode { + const NAME: &'static str = "getCreationCode"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetCreationCode { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCodeContracts {} + impl GetCreationCodeContracts { + const METHOD_ID: [u8; 4] = [23u8, 68u8, 129u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, Vec), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<(Vec, Vec)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCodeContracts { + const NAME: &'static str = "getCreationCodeContracts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<(Vec, Vec)> + for GetCreationCodeContracts { + fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetLastCreatedPool {} + impl GetLastCreatedPool { + const METHOD_ID: [u8; 4] = [94u8, 211u8, 18u8, 130u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetLastCreatedPool { + const NAME: &'static str = "getLastCreatedPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetLastCreatedPool { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolVersion {} + impl GetPoolVersion { + const METHOD_ID: [u8; 4] = [63u8, 129u8, 155u8, 111u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolVersion { + const NAME: &'static str = "getPoolVersion"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for GetPoolVersion { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeePercentagesProvider {} + impl GetProtocolFeePercentagesProvider { + const METHOD_ID: [u8; 4] = [115u8, 146u8, 56u8, 214u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeePercentagesProvider { + const NAME: &'static str = "getProtocolFeePercentagesProvider"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeePercentagesProvider { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsDisabled {} + impl IsDisabled { + const METHOD_ID: [u8; 4] = [108u8, 87u8, 245u8, 169u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsDisabled { + const NAME: &'static str = "isDisabled"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsDisabled { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Version {} + impl Version { + const METHOD_ID: [u8; 4] = [84u8, 253u8, 77u8, 80u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Version { + const NAME: &'static str = "version"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Version { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct EulerLinearPoolCreated { + pub pool: Vec, + pub protocol_id: substreams::scalar::BigInt, + } + impl EulerLinearPoolCreated { + const TOPIC_ID: [u8; 32] = [ + 222u8, + 57u8, + 57u8, + 206u8, + 202u8, + 16u8, + 20u8, + 97u8, + 253u8, + 126u8, + 56u8, + 151u8, + 5u8, + 2u8, + 10u8, + 31u8, + 139u8, + 21u8, + 24u8, + 237u8, + 183u8, + 93u8, + 5u8, + 40u8, + 75u8, + 33u8, + 170u8, + 39u8, + 3u8, + 84u8, + 195u8, + 220u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'protocol_id' from topic of type 'uint256': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for EulerLinearPoolCreated { + const NAME: &'static str = "EulerLinearPoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct FactoryDisabled {} + impl FactoryDisabled { + const TOPIC_ID: [u8; 32] = [ + 67u8, + 42u8, + 203u8, + 253u8, + 102u8, + 45u8, + 187u8, + 93u8, + 139u8, + 55u8, + 131u8, + 132u8, + 166u8, + 113u8, + 89u8, + 180u8, + 124u8, + 169u8, + 208u8, + 241u8, + 183u8, + 159u8, + 151u8, + 207u8, + 100u8, + 207u8, + 133u8, + 133u8, + 250u8, + 54u8, + 45u8, + 80u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self {}) + } + } + impl substreams_ethereum::Event for FactoryDisabled { + const NAME: &'static str = "FactoryDisabled"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/gearbox_linear_pool_factory.rs b/substreams/ethereum-balancer/src/abi/gearbox_linear_pool_factory.rs new file mode 100644 index 0000000..89a2b16 --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/gearbox_linear_pool_factory.rs @@ -0,0 +1,1689 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub name: String, + pub symbol: String, + pub main_token: Vec, + pub wrapped_token: Vec, + pub upper_target: substreams::scalar::BigInt, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub owner: Vec, + pub protocol_id: substreams::scalar::BigInt, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [118u8, 137u8, 91u8, 231u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + main_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + wrapped_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + upper_target: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + swap_fee_percentage: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + salt: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.main_token), + ), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.wrapped_token), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.upper_target.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.swap_fee_percentage.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.protocol_id.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::FixedBytes(self.salt.as_ref().to_vec()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Disable {} + impl Disable { + const METHOD_ID: [u8; 4] = [47u8, 39u8, 112u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for Disable { + const NAME: &'static str = "disable"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCode {} + impl GetCreationCode { + const METHOD_ID: [u8; 4] = [0u8, 193u8, 148u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bytes], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bytes() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCode { + const NAME: &'static str = "getCreationCode"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetCreationCode { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCodeContracts {} + impl GetCreationCodeContracts { + const METHOD_ID: [u8; 4] = [23u8, 68u8, 129u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, Vec), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<(Vec, Vec)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCodeContracts { + const NAME: &'static str = "getCreationCodeContracts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<(Vec, Vec)> + for GetCreationCodeContracts { + fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetLastCreatedPool {} + impl GetLastCreatedPool { + const METHOD_ID: [u8; 4] = [94u8, 211u8, 18u8, 130u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetLastCreatedPool { + const NAME: &'static str = "getLastCreatedPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetLastCreatedPool { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolVersion {} + impl GetPoolVersion { + const METHOD_ID: [u8; 4] = [63u8, 129u8, 155u8, 111u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolVersion { + const NAME: &'static str = "getPoolVersion"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for GetPoolVersion { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeePercentagesProvider {} + impl GetProtocolFeePercentagesProvider { + const METHOD_ID: [u8; 4] = [115u8, 146u8, 56u8, 214u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeePercentagesProvider { + const NAME: &'static str = "getProtocolFeePercentagesProvider"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeePercentagesProvider { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsDisabled {} + impl IsDisabled { + const METHOD_ID: [u8; 4] = [108u8, 87u8, 245u8, 169u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsDisabled { + const NAME: &'static str = "isDisabled"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsDisabled { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Version {} + impl Version { + const METHOD_ID: [u8; 4] = [84u8, 253u8, 77u8, 80u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Version { + const NAME: &'static str = "version"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Version { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct FactoryDisabled {} + impl FactoryDisabled { + const TOPIC_ID: [u8; 32] = [ + 67u8, + 42u8, + 203u8, + 253u8, + 102u8, + 45u8, + 187u8, + 93u8, + 139u8, + 55u8, + 131u8, + 132u8, + 166u8, + 113u8, + 89u8, + 180u8, + 124u8, + 169u8, + 208u8, + 241u8, + 183u8, + 159u8, + 151u8, + 207u8, + 100u8, + 207u8, + 133u8, + 133u8, + 250u8, + 54u8, + 45u8, + 80u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self {}) + } + } + impl substreams_ethereum::Event for FactoryDisabled { + const NAME: &'static str = "FactoryDisabled"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GearboxLinearPoolCreated { + pub pool: Vec, + pub protocol_id: substreams::scalar::BigInt, + } + impl GearboxLinearPoolCreated { + const TOPIC_ID: [u8; 32] = [ + 247u8, + 233u8, + 204u8, + 1u8, + 56u8, + 242u8, + 70u8, + 13u8, + 229u8, + 105u8, + 50u8, + 195u8, + 236u8, + 237u8, + 29u8, + 78u8, + 21u8, + 121u8, + 168u8, + 54u8, + 100u8, + 80u8, + 108u8, + 25u8, + 212u8, + 48u8, + 74u8, + 242u8, + 106u8, + 164u8, + 139u8, + 212u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'protocol_id' from topic of type 'uint256': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for GearboxLinearPoolCreated { + const NAME: &'static str = "GearboxLinearPoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/managed_pool_factory.rs b/substreams/ethereum-balancer/src/abi/managed_pool_factory.rs new file mode 100644 index 0000000..afd6cab --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/managed_pool_factory.rs @@ -0,0 +1,1735 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub params: (String, String, Vec>), + pub settings_params: ( + Vec>, + Vec, + substreams::scalar::BigInt, + bool, + bool, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + ), + pub owner: Vec, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [115u8, 4u8, 184u8, 185u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::String, ethabi::ParamType::String, + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Address)) + ], + ), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Address)), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Uint(256usize), ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize) + ], + ), + ethabi::ParamType::Address, + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + params: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_string() + .expect(INTERNAL_ERR), + tuple_elements[1usize] + .clone() + .into_string() + .expect(INTERNAL_ERR), + tuple_elements[2usize] + .clone() + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec() + }) + .collect(), + ) + }, + settings_params: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec() + }) + .collect(), + tuple_elements[1usize] + .clone() + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + { + let mut v = [0 as u8; 32]; + tuple_elements[2usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + tuple_elements[3usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + tuple_elements[4usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + { + let mut v = [0 as u8; 32]; + tuple_elements[5usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[6usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + ) + }, + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + salt: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Tuple( + vec![ + ethabi::Token::String(self.params.0.clone()), + ethabi::Token::String(self.params.1.clone()), { let v = self + .params.2.iter().map(| inner | + ethabi::Token::Address(ethabi::Address::from_slice(& + inner))).collect(); ethabi::Token::Array(v) } + ], + ), + ethabi::Token::Tuple( + vec![ + { let v = self.settings_params.0.iter().map(| inner | + ethabi::Token::Address(ethabi::Address::from_slice(& + inner))).collect(); ethabi::Token::Array(v) }, { let v = + self.settings_params.1.iter().map(| inner | + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),)).collect(); ethabi::Token::Array(v) }, + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .settings_params.2.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), ethabi::Token::Bool(self.settings_params.3 + .clone()), ethabi::Token::Bool(self.settings_params.4 + .clone()), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .settings_params.5.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .settings_params.6.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),) + ], + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::FixedBytes(self.salt.as_ref().to_vec()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Disable {} + impl Disable { + const METHOD_ID: [u8; 4] = [47u8, 39u8, 112u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for Disable { + const NAME: &'static str = "disable"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCode {} + impl GetCreationCode { + const METHOD_ID: [u8; 4] = [0u8, 193u8, 148u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bytes], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bytes() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCode { + const NAME: &'static str = "getCreationCode"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetCreationCode { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCodeContracts {} + impl GetCreationCodeContracts { + const METHOD_ID: [u8; 4] = [23u8, 68u8, 129u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, Vec), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<(Vec, Vec)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCodeContracts { + const NAME: &'static str = "getCreationCodeContracts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<(Vec, Vec)> + for GetCreationCodeContracts { + fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolVersion {} + impl GetPoolVersion { + const METHOD_ID: [u8; 4] = [63u8, 129u8, 155u8, 111u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolVersion { + const NAME: &'static str = "getPoolVersion"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for GetPoolVersion { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeePercentagesProvider {} + impl GetProtocolFeePercentagesProvider { + const METHOD_ID: [u8; 4] = [115u8, 146u8, 56u8, 214u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeePercentagesProvider { + const NAME: &'static str = "getProtocolFeePercentagesProvider"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeePercentagesProvider { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetRecoveryModeHelper {} + impl GetRecoveryModeHelper { + const METHOD_ID: [u8; 4] = [138u8, 71u8, 174u8, 59u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetRecoveryModeHelper { + const NAME: &'static str = "getRecoveryModeHelper"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetRecoveryModeHelper { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetWeightedMath {} + impl GetWeightedMath { + const METHOD_ID: [u8; 4] = [80u8, 143u8, 14u8, 174u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetWeightedMath { + const NAME: &'static str = "getWeightedMath"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetWeightedMath { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsDisabled {} + impl IsDisabled { + const METHOD_ID: [u8; 4] = [108u8, 87u8, 245u8, 169u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsDisabled { + const NAME: &'static str = "isDisabled"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsDisabled { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Version {} + impl Version { + const METHOD_ID: [u8; 4] = [84u8, 253u8, 77u8, 80u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Version { + const NAME: &'static str = "version"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Version { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct FactoryDisabled {} + impl FactoryDisabled { + const TOPIC_ID: [u8; 32] = [ + 67u8, + 42u8, + 203u8, + 253u8, + 102u8, + 45u8, + 187u8, + 93u8, + 139u8, + 55u8, + 131u8, + 132u8, + 166u8, + 113u8, + 89u8, + 180u8, + 124u8, + 169u8, + 208u8, + 241u8, + 183u8, + 159u8, + 151u8, + 207u8, + 100u8, + 207u8, + 133u8, + 133u8, + 250u8, + 54u8, + 45u8, + 80u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self {}) + } + } + impl substreams_ethereum::Event for FactoryDisabled { + const NAME: &'static str = "FactoryDisabled"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/mod.rs b/substreams/ethereum-balancer/src/abi/mod.rs new file mode 100644 index 0000000..0f60dc0 --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/mod.rs @@ -0,0 +1,11 @@ +#![allow(clippy::all)] +pub mod yearn_linear_pool_factory; +pub mod composable_stable_pool_factory; +pub mod vault; +pub mod weighted_pool_tokens_factory; +pub mod silo_linear_pool_factory; +pub mod euler_linear_pool_factory; +pub mod weighted_pool_factory; +pub mod managed_pool_factory; +pub mod erc_linear_pool_factory; +pub mod gearbox_linear_pool_factory; diff --git a/substreams/ethereum-balancer/src/abi/silo_linear_pool_factory.rs b/substreams/ethereum-balancer/src/abi/silo_linear_pool_factory.rs new file mode 100644 index 0000000..aa0a62e --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/silo_linear_pool_factory.rs @@ -0,0 +1,1689 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub name: String, + pub symbol: String, + pub main_token: Vec, + pub wrapped_token: Vec, + pub upper_target: substreams::scalar::BigInt, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub owner: Vec, + pub protocol_id: substreams::scalar::BigInt, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [118u8, 137u8, 91u8, 231u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + main_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + wrapped_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + upper_target: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + swap_fee_percentage: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + salt: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.main_token), + ), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.wrapped_token), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.upper_target.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.swap_fee_percentage.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.protocol_id.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::FixedBytes(self.salt.as_ref().to_vec()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Disable {} + impl Disable { + const METHOD_ID: [u8; 4] = [47u8, 39u8, 112u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for Disable { + const NAME: &'static str = "disable"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCode {} + impl GetCreationCode { + const METHOD_ID: [u8; 4] = [0u8, 193u8, 148u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bytes], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bytes() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCode { + const NAME: &'static str = "getCreationCode"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetCreationCode { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCodeContracts {} + impl GetCreationCodeContracts { + const METHOD_ID: [u8; 4] = [23u8, 68u8, 129u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, Vec), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<(Vec, Vec)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCodeContracts { + const NAME: &'static str = "getCreationCodeContracts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<(Vec, Vec)> + for GetCreationCodeContracts { + fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetLastCreatedPool {} + impl GetLastCreatedPool { + const METHOD_ID: [u8; 4] = [94u8, 211u8, 18u8, 130u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetLastCreatedPool { + const NAME: &'static str = "getLastCreatedPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetLastCreatedPool { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolVersion {} + impl GetPoolVersion { + const METHOD_ID: [u8; 4] = [63u8, 129u8, 155u8, 111u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolVersion { + const NAME: &'static str = "getPoolVersion"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for GetPoolVersion { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeePercentagesProvider {} + impl GetProtocolFeePercentagesProvider { + const METHOD_ID: [u8; 4] = [115u8, 146u8, 56u8, 214u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeePercentagesProvider { + const NAME: &'static str = "getProtocolFeePercentagesProvider"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeePercentagesProvider { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsDisabled {} + impl IsDisabled { + const METHOD_ID: [u8; 4] = [108u8, 87u8, 245u8, 169u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsDisabled { + const NAME: &'static str = "isDisabled"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsDisabled { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Version {} + impl Version { + const METHOD_ID: [u8; 4] = [84u8, 253u8, 77u8, 80u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Version { + const NAME: &'static str = "version"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Version { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct FactoryDisabled {} + impl FactoryDisabled { + const TOPIC_ID: [u8; 32] = [ + 67u8, + 42u8, + 203u8, + 253u8, + 102u8, + 45u8, + 187u8, + 93u8, + 139u8, + 55u8, + 131u8, + 132u8, + 166u8, + 113u8, + 89u8, + 180u8, + 124u8, + 169u8, + 208u8, + 241u8, + 183u8, + 159u8, + 151u8, + 207u8, + 100u8, + 207u8, + 133u8, + 133u8, + 250u8, + 54u8, + 45u8, + 80u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self {}) + } + } + impl substreams_ethereum::Event for FactoryDisabled { + const NAME: &'static str = "FactoryDisabled"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SiloLinearPoolCreated { + pub pool: Vec, + pub protocol_id: substreams::scalar::BigInt, + } + impl SiloLinearPoolCreated { + const TOPIC_ID: [u8; 32] = [ + 51u8, + 255u8, + 20u8, + 158u8, + 158u8, + 34u8, + 79u8, + 133u8, + 82u8, + 43u8, + 217u8, + 79u8, + 245u8, + 135u8, + 189u8, + 84u8, + 170u8, + 248u8, + 170u8, + 90u8, + 22u8, + 253u8, + 146u8, + 79u8, + 240u8, + 1u8, + 55u8, + 93u8, + 114u8, + 156u8, + 173u8, + 41u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'protocol_id' from topic of type 'uint256': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for SiloLinearPoolCreated { + const NAME: &'static str = "SiloLinearPoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/vault.rs b/substreams/ethereum-balancer/src/abi/vault.rs new file mode 100644 index 0000000..ec00beb --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/vault.rs @@ -0,0 +1,5268 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Weth {} + impl Weth { + const METHOD_ID: [u8; 4] = [173u8, 92u8, 70u8, 72u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Weth { + const NAME: &'static str = "WETH"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Weth { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct BatchSwap { + pub kind: substreams::scalar::BigInt, + pub swaps: Vec< + ( + [u8; 32usize], + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + >, + pub assets: Vec>, + pub funds: (Vec, bool, Vec, bool), + pub limits: Vec, + pub deadline: substreams::scalar::BigInt, + } + impl BatchSwap { + const METHOD_ID: [u8; 4] = [148u8, 91u8, 206u8, 201u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(8usize), + ethabi::ParamType::Array( + Box::new( + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), ethabi::ParamType::Bytes + ], + ), + ), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Bool, + ethabi::ParamType::Address, ethabi::ParamType::Bool + ], + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Int(256usize)), + ), + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + kind: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + swaps: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let tuple_elements = inner.into_tuple().expect(INTERNAL_ERR); + ( + { + let mut result = [0u8; 32]; + let v = tuple_elements[0usize] + .clone() + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[1usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[2usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[3usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + tuple_elements[4usize] + .clone() + .into_bytes() + .expect(INTERNAL_ERR), + ) + }) + .collect(), + assets: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + funds: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[1usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + tuple_elements[2usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[3usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + ) + }, + limits: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_int() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_signed_bytes_be(&v) + }) + .collect(), + deadline: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.kind.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + { + let v = self + .swaps + .iter() + .map(|inner| ethabi::Token::Tuple( + vec![ + ethabi::Token::FixedBytes(inner.0.as_ref().to_vec()), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.1.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.2.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.3.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), ethabi::Token::Bytes(inner.4.clone()) + ], + )) + .collect(); + ethabi::Token::Array(v) + }, + { + let v = self + .assets + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + ethabi::Token::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& self + .funds.0)), ethabi::Token::Bool(self.funds.1.clone()), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .funds.2)), ethabi::Token::Bool(self.funds.3.clone()) + ], + ), + { + let v = self + .limits + .iter() + .map(|inner| { + let non_full_signed_bytes = inner.to_signed_bytes_be(); + let full_signed_bytes_init = if non_full_signed_bytes[0] + & 0x80 == 0x80 + { + 0xff + } else { + 0x00 + }; + let mut full_signed_bytes = [full_signed_bytes_init + as u8; 32]; + non_full_signed_bytes + .into_iter() + .rev() + .enumerate() + .for_each(|(i, byte)| full_signed_bytes[31 - i] = byte); + ethabi::Token::Int( + ethabi::Int::from_big_endian(full_signed_bytes.as_ref()), + ) + }) + .collect(); + ethabi::Token::Array(v) + }, + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.deadline.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result, String> { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Int(256usize)), + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_int() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_signed_bytes_be(&v) + }) + .collect(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for BatchSwap { + const NAME: &'static str = "batchSwap"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for BatchSwap { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct DeregisterTokens { + pub pool_id: [u8; 32usize], + pub tokens: Vec>, + } + impl DeregisterTokens { + const METHOD_ID: [u8; 4] = [125u8, 58u8, 235u8, 150u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::FixedBytes(self.pool_id.as_ref().to_vec()), + { + let v = self + .tokens + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for DeregisterTokens { + const NAME: &'static str = "deregisterTokens"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ExitPool { + pub pool_id: [u8; 32usize], + pub sender: Vec, + pub recipient: Vec, + pub request: (Vec>, Vec, Vec, bool), + } + impl ExitPool { + const METHOD_ID: [u8; 4] = [139u8, 219u8, 57u8, 19u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Address)), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Bytes, ethabi::ParamType::Bool + ], + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + sender: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + recipient: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + request: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec() + }) + .collect(), + tuple_elements[1usize] + .clone() + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + tuple_elements[2usize] + .clone() + .into_bytes() + .expect(INTERNAL_ERR), + tuple_elements[3usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::FixedBytes(self.pool_id.as_ref().to_vec()), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.sender), + ), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.recipient), + ), + ethabi::Token::Tuple( + vec![ + { let v = self.request.0.iter().map(| inner | + ethabi::Token::Address(ethabi::Address::from_slice(& + inner))).collect(); ethabi::Token::Array(v) }, { let v = + self.request.1.iter().map(| inner | + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),)).collect(); ethabi::Token::Array(v) }, + ethabi::Token::Bytes(self.request.2.clone()), + ethabi::Token::Bool(self.request.3.clone()) + ], + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for ExitPool { + const NAME: &'static str = "exitPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct FlashLoan { + pub recipient: Vec, + pub tokens: Vec>, + pub amounts: Vec, + pub user_data: Vec, + } + impl FlashLoan { + const METHOD_ID: [u8; 4] = [92u8, 56u8, 68u8, 158u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Address, + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Bytes, + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + recipient: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + amounts: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + user_data: values + .pop() + .expect(INTERNAL_ERR) + .into_bytes() + .expect(INTERNAL_ERR), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.recipient), + ), + { + let v = self + .tokens + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + { + let v = self + .amounts + .iter() + .map(|inner| ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match inner.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + )) + .collect(); + ethabi::Token::Array(v) + }, + ethabi::Token::Bytes(self.user_data.clone()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for FlashLoan { + const NAME: &'static str = "flashLoan"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetDomainSeparator {} + impl GetDomainSeparator { + const METHOD_ID: [u8; 4] = [237u8, 36u8, 145u8, 29u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetDomainSeparator { + const NAME: &'static str = "getDomainSeparator"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> + for GetDomainSeparator { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetInternalBalance { + pub user: Vec, + pub tokens: Vec>, + } + impl GetInternalBalance { + const METHOD_ID: [u8; 4] = [15u8, 90u8, 110u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Address, + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + user: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.user)), + { + let v = self + .tokens + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result, String> { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetInternalBalance { + const NAME: &'static str = "getInternalBalance"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetInternalBalance { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetNextNonce { + pub user: Vec, + } + impl GetNextNonce { + const METHOD_ID: [u8; 4] = [144u8, 25u8, 59u8, 124u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + user: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.user))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut v = [0 as u8; 32]; + values + .pop() + .expect("one output data should have existed") + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetNextNonce { + const NAME: &'static str = "getNextNonce"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable + for GetNextNonce { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPausedState {} + impl GetPausedState { + const METHOD_ID: [u8; 4] = [28u8, 13u8, 224u8, 81u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (bool, substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (bool, substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Bool, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values.pop().expect(INTERNAL_ERR).into_bool().expect(INTERNAL_ERR), + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(bool, substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPausedState { + const NAME: &'static str = "getPausedState"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (bool, substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPausedState { + fn output( + data: &[u8], + ) -> Result< + (bool, substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPool { + pub pool_id: [u8; 32usize], + } + impl GetPool { + const METHOD_ID: [u8; 4] = [246u8, 192u8, 9u8, 39u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.pool_id.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, substreams::scalar::BigInt), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result<(Vec, substreams::scalar::BigInt), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Uint(8usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(Vec, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPool { + const NAME: &'static str = "getPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (Vec, substreams::scalar::BigInt), + > for GetPool { + fn output( + data: &[u8], + ) -> Result<(Vec, substreams::scalar::BigInt), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolTokenInfo { + pub pool_id: [u8; 32usize], + pub token: Vec, + } + impl GetPoolTokenInfo { + const METHOD_ID: [u8; 4] = [176u8, 95u8, 142u8, 72u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Address, + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::FixedBytes(self.pool_id.as_ref().to_vec()), + ethabi::Token::Address(ethabi::Address::from_slice(&self.token)), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + > { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolTokenInfo { + const NAME: &'static str = "getPoolTokenInfo"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + > for GetPoolTokenInfo { + fn output( + data: &[u8], + ) -> Result< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolTokens { + pub pool_id: [u8; 32usize], + } + impl GetPoolTokens { + const METHOD_ID: [u8; 4] = [249u8, 77u8, 70u8, 104u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.pool_id.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + ( + Vec>, + Vec, + substreams::scalar::BigInt, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + Vec>, + Vec, + substreams::scalar::BigInt, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option< + ( + Vec>, + Vec, + substreams::scalar::BigInt, + ), + > { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolTokens { + const NAME: &'static str = "getPoolTokens"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (Vec>, Vec, substreams::scalar::BigInt), + > for GetPoolTokens { + fn output( + data: &[u8], + ) -> Result< + ( + Vec>, + Vec, + substreams::scalar::BigInt, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeesCollector {} + impl GetProtocolFeesCollector { + const METHOD_ID: [u8; 4] = [210u8, 148u8, 108u8, 43u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeesCollector { + const NAME: &'static str = "getProtocolFeesCollector"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeesCollector { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct HasApprovedRelayer { + pub user: Vec, + pub relayer: Vec, + } + impl HasApprovedRelayer { + const METHOD_ID: [u8; 4] = [254u8, 201u8, 13u8, 114u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + user: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + relayer: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.user)), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.relayer), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for HasApprovedRelayer { + const NAME: &'static str = "hasApprovedRelayer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for HasApprovedRelayer { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct JoinPool { + pub pool_id: [u8; 32usize], + pub sender: Vec, + pub recipient: Vec, + pub request: (Vec>, Vec, Vec, bool), + } + impl JoinPool { + const METHOD_ID: [u8; 4] = [185u8, 92u8, 172u8, 40u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Address)), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Bytes, ethabi::ParamType::Bool + ], + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + sender: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + recipient: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + request: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec() + }) + .collect(), + tuple_elements[1usize] + .clone() + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + tuple_elements[2usize] + .clone() + .into_bytes() + .expect(INTERNAL_ERR), + tuple_elements[3usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::FixedBytes(self.pool_id.as_ref().to_vec()), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.sender), + ), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.recipient), + ), + ethabi::Token::Tuple( + vec![ + { let v = self.request.0.iter().map(| inner | + ethabi::Token::Address(ethabi::Address::from_slice(& + inner))).collect(); ethabi::Token::Array(v) }, { let v = + self.request.1.iter().map(| inner | + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),)).collect(); ethabi::Token::Array(v) }, + ethabi::Token::Bytes(self.request.2.clone()), + ethabi::Token::Bool(self.request.3.clone()) + ], + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for JoinPool { + const NAME: &'static str = "joinPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ManagePoolBalance { + pub ops: Vec< + ( + substreams::scalar::BigInt, + [u8; 32usize], + Vec, + substreams::scalar::BigInt, + ), + >, + } + impl ManagePoolBalance { + const METHOD_ID: [u8; 4] = [230u8, 196u8, 96u8, 146u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new( + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Uint(8usize), + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize) + ], + ), + ), + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + ops: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let tuple_elements = inner.into_tuple().expect(INTERNAL_ERR); + ( + { + let mut v = [0 as u8; 32]; + tuple_elements[0usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut result = [0u8; 32]; + let v = tuple_elements[1usize] + .clone() + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + tuple_elements[2usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + let mut v = [0 as u8; 32]; + tuple_elements[3usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + ) + }) + .collect(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + { + let v = self + .ops + .iter() + .map(|inner| ethabi::Token::Tuple( + vec![ + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.0.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), ethabi::Token::FixedBytes(inner.1.as_ref() + .to_vec()), + ethabi::Token::Address(ethabi::Address::from_slice(& inner + .2)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.3.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),) + ], + )) + .collect(); + ethabi::Token::Array(v) + }, + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for ManagePoolBalance { + const NAME: &'static str = "managePoolBalance"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ManageUserBalance { + pub ops: Vec< + ( + substreams::scalar::BigInt, + Vec, + substreams::scalar::BigInt, + Vec, + Vec, + ), + >, + } + impl ManageUserBalance { + const METHOD_ID: [u8; 4] = [14u8, 142u8, 62u8, 132u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new( + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Uint(8usize), ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, ethabi::ParamType::Address + ], + ), + ), + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + ops: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let tuple_elements = inner.into_tuple().expect(INTERNAL_ERR); + ( + { + let mut v = [0 as u8; 32]; + tuple_elements[0usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + tuple_elements[1usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + let mut v = [0 as u8; 32]; + tuple_elements[2usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + tuple_elements[3usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[4usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + }) + .collect(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + { + let v = self + .ops + .iter() + .map(|inner| ethabi::Token::Tuple( + vec![ + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.0.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), + ethabi::Token::Address(ethabi::Address::from_slice(& inner + .1)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.2.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), + ethabi::Token::Address(ethabi::Address::from_slice(& inner + .3)), ethabi::Token::Address(ethabi::Address::from_slice(& + inner.4)) + ], + )) + .collect(); + ethabi::Token::Array(v) + }, + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for ManageUserBalance { + const NAME: &'static str = "manageUserBalance"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct QueryBatchSwap { + pub kind: substreams::scalar::BigInt, + pub swaps: Vec< + ( + [u8; 32usize], + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + >, + pub assets: Vec>, + pub funds: (Vec, bool, Vec, bool), + } + impl QueryBatchSwap { + const METHOD_ID: [u8; 4] = [248u8, 77u8, 6u8, 110u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(8usize), + ethabi::ParamType::Array( + Box::new( + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), ethabi::ParamType::Bytes + ], + ), + ), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Bool, + ethabi::ParamType::Address, ethabi::ParamType::Bool + ], + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + kind: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + swaps: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let tuple_elements = inner.into_tuple().expect(INTERNAL_ERR); + ( + { + let mut result = [0u8; 32]; + let v = tuple_elements[0usize] + .clone() + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[1usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[2usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[3usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + tuple_elements[4usize] + .clone() + .into_bytes() + .expect(INTERNAL_ERR), + ) + }) + .collect(), + assets: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + funds: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[1usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + tuple_elements[2usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[3usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.kind.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + { + let v = self + .swaps + .iter() + .map(|inner| ethabi::Token::Tuple( + vec![ + ethabi::Token::FixedBytes(inner.0.as_ref().to_vec()), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.1.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.2.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match + inner.3.clone().to_bytes_be() { (num_bigint::Sign::Plus, + bytes) => bytes, (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), ethabi::Token::Bytes(inner.4.clone()) + ], + )) + .collect(); + ethabi::Token::Array(v) + }, + { + let v = self + .assets + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + ethabi::Token::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& self + .funds.0)), ethabi::Token::Bool(self.funds.1.clone()), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .funds.2)), ethabi::Token::Bool(self.funds.3.clone()) + ], + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result, String> { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Int(256usize)), + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_int() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_signed_bytes_be(&v) + }) + .collect(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for QueryBatchSwap { + const NAME: &'static str = "queryBatchSwap"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for QueryBatchSwap { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct RegisterPool { + pub specialization: substreams::scalar::BigInt, + } + impl RegisterPool { + const METHOD_ID: [u8; 4] = [9u8, 178u8, 118u8, 15u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Uint(8usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + specialization: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.specialization.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for RegisterPool { + const NAME: &'static str = "registerPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for RegisterPool { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct RegisterTokens { + pub pool_id: [u8; 32usize], + pub tokens: Vec>, + pub asset_managers: Vec>, + } + impl RegisterTokens { + const METHOD_ID: [u8; 4] = [102u8, 169u8, 199u8, 210u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + asset_managers: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::FixedBytes(self.pool_id.as_ref().to_vec()), + { + let v = self + .tokens + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + { + let v = self + .asset_managers + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for RegisterTokens { + const NAME: &'static str = "registerTokens"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SetAuthorizer { + pub new_authorizer: Vec, + } + impl SetAuthorizer { + const METHOD_ID: [u8; 4] = [5u8, 138u8, 98u8, 143u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + new_authorizer: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.new_authorizer), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for SetAuthorizer { + const NAME: &'static str = "setAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SetPaused { + pub paused: bool, + } + impl SetPaused { + const METHOD_ID: [u8; 4] = [22u8, 195u8, 139u8, 60u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + paused: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[ethabi::Token::Bool(self.paused.clone())]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for SetPaused { + const NAME: &'static str = "setPaused"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SetRelayerApproval { + pub sender: Vec, + pub relayer: Vec, + pub approved: bool, + } + impl SetRelayerApproval { + const METHOD_ID: [u8; 4] = [250u8, 110u8, 103u8, 29u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Bool, + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + sender: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + relayer: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + approved: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.sender), + ), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.relayer), + ), + ethabi::Token::Bool(self.approved.clone()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for SetRelayerApproval { + const NAME: &'static str = "setRelayerApproval"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Swap { + pub single_swap: ( + [u8; 32usize], + substreams::scalar::BigInt, + Vec, + Vec, + substreams::scalar::BigInt, + Vec, + ), + pub funds: (Vec, bool, Vec, bool), + pub limit: substreams::scalar::BigInt, + pub deadline: substreams::scalar::BigInt, + } + impl Swap { + const METHOD_ID: [u8; 4] = [82u8, 187u8, 190u8, 41u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Uint(8usize), ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), ethabi::ParamType::Bytes + ], + ), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Bool, + ethabi::ParamType::Address, ethabi::ParamType::Bool + ], + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + single_swap: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + { + let mut result = [0u8; 32]; + let v = tuple_elements[0usize] + .clone() + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[1usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + tuple_elements[2usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[3usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + let mut v = [0 as u8; 32]; + tuple_elements[4usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + tuple_elements[5usize] + .clone() + .into_bytes() + .expect(INTERNAL_ERR), + ) + }, + funds: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[1usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + tuple_elements[2usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[3usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + ) + }, + limit: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + deadline: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Tuple( + vec![ + ethabi::Token::FixedBytes(self.single_swap.0.as_ref() + .to_vec()), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .single_swap.1.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .single_swap.2)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .single_swap.3)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .single_swap.4.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") }, } + .as_slice(),),), ethabi::Token::Bytes(self.single_swap.5 + .clone()) + ], + ), + ethabi::Token::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& self + .funds.0)), ethabi::Token::Bool(self.funds.1.clone()), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .funds.2)), ethabi::Token::Bool(self.funds.3.clone()) + ], + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.limit.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.deadline.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut v = [0 as u8; 32]; + values + .pop() + .expect("one output data should have existed") + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Swap { + const NAME: &'static str = "swap"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable + for Swap { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct AuthorizerChanged { + pub new_authorizer: Vec, + } + impl AuthorizerChanged { + const TOPIC_ID: [u8; 32] = [ + 148u8, + 185u8, + 121u8, + 182u8, + 131u8, + 26u8, + 81u8, + 41u8, + 62u8, + 38u8, + 65u8, + 66u8, + 111u8, + 151u8, + 116u8, + 127u8, + 238u8, + 212u8, + 111u8, + 23u8, + 119u8, + 159u8, + 237u8, + 156u8, + 209u8, + 141u8, + 30u8, + 206u8, + 252u8, + 254u8, + 146u8, + 239u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + new_authorizer: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'new_authorizer' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for AuthorizerChanged { + const NAME: &'static str = "AuthorizerChanged"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ExternalBalanceTransfer { + pub token: Vec, + pub sender: Vec, + pub recipient: Vec, + pub amount: substreams::scalar::BigInt, + } + impl ExternalBalanceTransfer { + const TOPIC_ID: [u8; 32] = [ + 84u8, + 10u8, + 26u8, + 63u8, + 40u8, + 52u8, + 12u8, + 174u8, + 195u8, + 54u8, + 200u8, + 29u8, + 141u8, + 123u8, + 61u8, + 241u8, + 57u8, + 238u8, + 92u8, + 220u8, + 24u8, + 57u8, + 164u8, + 242u8, + 131u8, + 215u8, + 235u8, + 183u8, + 234u8, + 174u8, + 45u8, + 92u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Uint(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + sender: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'sender' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + recipient: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + amount: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for ExternalBalanceTransfer { + const NAME: &'static str = "ExternalBalanceTransfer"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct FlashLoan { + pub recipient: Vec, + pub token: Vec, + pub amount: substreams::scalar::BigInt, + pub fee_amount: substreams::scalar::BigInt, + } + impl FlashLoan { + const TOPIC_ID: [u8; 32] = [ + 13u8, + 125u8, + 117u8, + 224u8, + 26u8, + 185u8, + 87u8, + 128u8, + 211u8, + 205u8, + 28u8, + 142u8, + 192u8, + 221u8, + 108u8, + 44u8, + 225u8, + 158u8, + 58u8, + 32u8, + 66u8, + 126u8, + 236u8, + 139u8, + 245u8, + 50u8, + 131u8, + 182u8, + 251u8, + 142u8, + 149u8, + 240u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + recipient: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'recipient' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + amount: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + fee_amount: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for FlashLoan { + const NAME: &'static str = "FlashLoan"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct InternalBalanceChanged { + pub user: Vec, + pub token: Vec, + pub delta: substreams::scalar::BigInt, + } + impl InternalBalanceChanged { + const TOPIC_ID: [u8; 32] = [ + 24u8, + 225u8, + 234u8, + 65u8, + 57u8, + 230u8, + 132u8, + 19u8, + 215u8, + 208u8, + 138u8, + 167u8, + 82u8, + 231u8, + 21u8, + 104u8, + 227u8, + 107u8, + 44u8, + 91u8, + 249u8, + 64u8, + 137u8, + 51u8, + 20u8, + 194u8, + 197u8, + 176u8, + 30u8, + 170u8, + 12u8, + 66u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 32usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Int(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + user: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'user' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + delta: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_int() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_signed_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for InternalBalanceChanged { + const NAME: &'static str = "InternalBalanceChanged"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PausedStateChanged { + pub paused: bool, + } + impl PausedStateChanged { + const TOPIC_ID: [u8; 32] = [ + 158u8, + 58u8, + 94u8, + 55u8, + 34u8, + 69u8, + 50u8, + 222u8, + 166u8, + 123u8, + 137u8, + 250u8, + 206u8, + 24u8, + 87u8, + 3u8, + 115u8, + 138u8, + 34u8, + 138u8, + 110u8, + 138u8, + 35u8, + 222u8, + 229u8, + 70u8, + 150u8, + 1u8, + 128u8, + 211u8, + 190u8, + 100u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 32usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + paused: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + }) + } + } + impl substreams_ethereum::Event for PausedStateChanged { + const NAME: &'static str = "PausedStateChanged"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolBalanceChanged { + pub pool_id: [u8; 32usize], + pub liquidity_provider: Vec, + pub tokens: Vec>, + pub deltas: Vec, + pub protocol_fee_amounts: Vec, + } + impl PoolBalanceChanged { + const TOPIC_ID: [u8; 32] = [ + 229u8, + 206u8, + 36u8, + 144u8, + 135u8, + 206u8, + 4u8, + 240u8, + 90u8, + 149u8, + 113u8, + 146u8, + 67u8, + 84u8, + 0u8, + 253u8, + 151u8, + 134u8, + 141u8, + 186u8, + 14u8, + 106u8, + 75u8, + 76u8, + 4u8, + 154u8, + 191u8, + 138u8, + 248u8, + 13u8, + 174u8, + 120u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() < 192usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Int(256usize)), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool_id' from topic of type 'bytes32': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + liquidity_provider: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'liquidity_provider' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + deltas: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_int() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_signed_bytes_be(&v) + }) + .collect(), + protocol_fee_amounts: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + }) + } + } + impl substreams_ethereum::Event for PoolBalanceChanged { + const NAME: &'static str = "PoolBalanceChanged"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolBalanceManaged { + pub pool_id: [u8; 32usize], + pub asset_manager: Vec, + pub token: Vec, + pub cash_delta: substreams::scalar::BigInt, + pub managed_delta: substreams::scalar::BigInt, + } + impl PoolBalanceManaged { + const TOPIC_ID: [u8; 32] = [ + 110u8, + 220u8, + 175u8, + 98u8, + 65u8, + 16u8, + 91u8, + 76u8, + 148u8, + 194u8, + 239u8, + 219u8, + 243u8, + 166u8, + 177u8, + 36u8, + 88u8, + 235u8, + 61u8, + 7u8, + 190u8, + 58u8, + 14u8, + 129u8, + 210u8, + 75u8, + 19u8, + 196u8, + 64u8, + 69u8, + 254u8, + 122u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 4usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Int(256usize), + ethabi::ParamType::Int(256usize), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool_id' from topic of type 'bytes32': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + asset_manager: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'asset_manager' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[3usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + cash_delta: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_int() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_signed_bytes_be(&v) + }, + managed_delta: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_int() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_signed_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for PoolBalanceManaged { + const NAME: &'static str = "PoolBalanceManaged"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolRegistered { + pub pool_id: [u8; 32usize], + pub pool_address: Vec, + pub specialization: substreams::scalar::BigInt, + } + impl PoolRegistered { + const TOPIC_ID: [u8; 32] = [ + 60u8, + 19u8, + 188u8, + 48u8, + 184u8, + 232u8, + 120u8, + 197u8, + 63u8, + 210u8, + 163u8, + 107u8, + 103u8, + 148u8, + 9u8, + 192u8, + 115u8, + 175u8, + 215u8, + 89u8, + 80u8, + 190u8, + 67u8, + 216u8, + 133u8, + 135u8, + 104u8, + 233u8, + 86u8, + 251u8, + 194u8, + 14u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 32usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Uint(8usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool_id' from topic of type 'bytes32': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + pool_address: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool_address' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + specialization: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for PoolRegistered { + const NAME: &'static str = "PoolRegistered"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct RelayerApprovalChanged { + pub relayer: Vec, + pub sender: Vec, + pub approved: bool, + } + impl RelayerApprovalChanged { + const TOPIC_ID: [u8; 32] = [ + 70u8, + 150u8, + 31u8, + 219u8, + 69u8, + 2u8, + 182u8, + 70u8, + 213u8, + 9u8, + 95u8, + 186u8, + 118u8, + 0u8, + 72u8, + 106u8, + 138u8, + 192u8, + 80u8, + 65u8, + 213u8, + 92u8, + 223u8, + 15u8, + 22u8, + 237u8, + 103u8, + 113u8, + 128u8, + 181u8, + 202u8, + 216u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 32usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + relayer: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'relayer' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + sender: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'sender' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + approved: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + }) + } + } + impl substreams_ethereum::Event for RelayerApprovalChanged { + const NAME: &'static str = "RelayerApprovalChanged"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Swap { + pub pool_id: [u8; 32usize], + pub token_in: Vec, + pub token_out: Vec, + pub amount_in: substreams::scalar::BigInt, + pub amount_out: substreams::scalar::BigInt, + } + impl Swap { + const TOPIC_ID: [u8; 32] = [ + 33u8, + 112u8, + 199u8, + 65u8, + 196u8, + 21u8, + 49u8, + 174u8, + 194u8, + 14u8, + 124u8, + 16u8, + 124u8, + 36u8, + 238u8, + 207u8, + 221u8, + 21u8, + 230u8, + 156u8, + 155u8, + 176u8, + 168u8, + 221u8, + 55u8, + 177u8, + 132u8, + 11u8, + 158u8, + 11u8, + 32u8, + 123u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 4usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool_id' from topic of type 'bytes32': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + token_in: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'token_in' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + token_out: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[3usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'token_out' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + amount_in: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + amount_out: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for Swap { + const NAME: &'static str = "Swap"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TokensDeregistered { + pub pool_id: [u8; 32usize], + pub tokens: Vec>, + } + impl TokensDeregistered { + const TOPIC_ID: [u8; 32] = [ + 125u8, + 205u8, + 198u8, + 208u8, + 46u8, + 244u8, + 12u8, + 124u8, + 26u8, + 112u8, + 70u8, + 160u8, + 17u8, + 176u8, + 88u8, + 189u8, + 127u8, + 152u8, + 143u8, + 161u8, + 78u8, + 32u8, + 166u8, + 99u8, + 68u8, + 249u8, + 212u8, + 230u8, + 6u8, + 87u8, + 214u8, + 16u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() < 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool_id' from topic of type 'bytes32': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + }) + } + } + impl substreams_ethereum::Event for TokensDeregistered { + const NAME: &'static str = "TokensDeregistered"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TokensRegistered { + pub pool_id: [u8; 32usize], + pub tokens: Vec>, + pub asset_managers: Vec>, + } + impl TokensRegistered { + const TOPIC_ID: [u8; 32] = [ + 245u8, + 132u8, + 125u8, + 63u8, + 33u8, + 151u8, + 177u8, + 108u8, + 220u8, + 210u8, + 9u8, + 142u8, + 201u8, + 93u8, + 9u8, + 5u8, + 205u8, + 26u8, + 189u8, + 175u8, + 65u8, + 95u8, + 7u8, + 187u8, + 124u8, + 239u8, + 43u8, + 186u8, + 138u8, + 197u8, + 222u8, + 196u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() < 128usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_id: { + let mut result = [0u8; 32]; + let v = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool_id' from topic of type 'bytes32': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + asset_managers: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + }) + } + } + impl substreams_ethereum::Event for TokensRegistered { + const NAME: &'static str = "TokensRegistered"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/weighted_pool_factory.rs b/substreams/ethereum-balancer/src/abi/weighted_pool_factory.rs new file mode 100644 index 0000000..db4e2bc --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/weighted_pool_factory.rs @@ -0,0 +1,1511 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub name: String, + pub symbol: String, + pub tokens: Vec>, + pub normalized_weights: Vec, + pub rate_providers: Vec>, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub owner: Vec, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [33u8, 130u8, 200u8, 254u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + normalized_weights: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + rate_providers: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + swap_fee_percentage: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + salt: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + { + let v = self + .tokens + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + { + let v = self + .normalized_weights + .iter() + .map(|inner| ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match inner.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + )) + .collect(); + ethabi::Token::Array(v) + }, + { + let v = self + .rate_providers + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.swap_fee_percentage.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::FixedBytes(self.salt.as_ref().to_vec()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Disable {} + impl Disable { + const METHOD_ID: [u8; 4] = [47u8, 39u8, 112u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for Disable { + const NAME: &'static str = "disable"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCode {} + impl GetCreationCode { + const METHOD_ID: [u8; 4] = [0u8, 193u8, 148u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bytes], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bytes() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCode { + const NAME: &'static str = "getCreationCode"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetCreationCode { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCodeContracts {} + impl GetCreationCodeContracts { + const METHOD_ID: [u8; 4] = [23u8, 68u8, 129u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, Vec), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<(Vec, Vec)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCodeContracts { + const NAME: &'static str = "getCreationCodeContracts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<(Vec, Vec)> + for GetCreationCodeContracts { + fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolVersion {} + impl GetPoolVersion { + const METHOD_ID: [u8; 4] = [63u8, 129u8, 155u8, 111u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolVersion { + const NAME: &'static str = "getPoolVersion"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for GetPoolVersion { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeePercentagesProvider {} + impl GetProtocolFeePercentagesProvider { + const METHOD_ID: [u8; 4] = [115u8, 146u8, 56u8, 214u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeePercentagesProvider { + const NAME: &'static str = "getProtocolFeePercentagesProvider"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeePercentagesProvider { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsDisabled {} + impl IsDisabled { + const METHOD_ID: [u8; 4] = [108u8, 87u8, 245u8, 169u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsDisabled { + const NAME: &'static str = "isDisabled"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsDisabled { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Version {} + impl Version { + const METHOD_ID: [u8; 4] = [84u8, 253u8, 77u8, 80u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Version { + const NAME: &'static str = "version"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Version { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct FactoryDisabled {} + impl FactoryDisabled { + const TOPIC_ID: [u8; 32] = [ + 67u8, + 42u8, + 203u8, + 253u8, + 102u8, + 45u8, + 187u8, + 93u8, + 139u8, + 55u8, + 131u8, + 132u8, + 166u8, + 113u8, + 89u8, + 180u8, + 124u8, + 169u8, + 208u8, + 241u8, + 183u8, + 159u8, + 151u8, + 207u8, + 100u8, + 207u8, + 133u8, + 133u8, + 250u8, + 54u8, + 45u8, + 80u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self {}) + } + } + impl substreams_ethereum::Event for FactoryDisabled { + const NAME: &'static str = "FactoryDisabled"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/weighted_pool_tokens_factory.rs b/substreams/ethereum-balancer/src/abi/weighted_pool_tokens_factory.rs new file mode 100644 index 0000000..95f7262 --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/weighted_pool_tokens_factory.rs @@ -0,0 +1,641 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub name: String, + pub symbol: String, + pub tokens: Vec>, + pub weights: Vec, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub oracle_enabled: bool, + pub owner: Vec, + } + impl Create { + const METHOD_ID: [u8; 4] = [21u8, 150u8, 1u8, 155u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Address), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Bool, + ethabi::ParamType::Address, + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + tokens: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .collect(), + weights: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + .collect(), + swap_fee_percentage: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + oracle_enabled: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + { + let v = self + .tokens + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::Array(v) + }, + { + let v = self + .weights + .iter() + .map(|inner| ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match inner.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + )) + .collect(); + ethabi::Token::Array(v) + }, + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.swap_fee_percentage.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Bool(self.oracle_enabled.clone()), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/abi/yearn_linear_pool_factory.rs b/substreams/ethereum-balancer/src/abi/yearn_linear_pool_factory.rs new file mode 100644 index 0000000..b5fbe27 --- /dev/null +++ b/substreams/ethereum-balancer/src/abi/yearn_linear_pool_factory.rs @@ -0,0 +1,1689 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Create { + pub name: String, + pub symbol: String, + pub main_token: Vec, + pub wrapped_token: Vec, + pub upper_target: substreams::scalar::BigInt, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub owner: Vec, + pub protocol_id: substreams::scalar::BigInt, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [118u8, 137u8, 91u8, 231u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + main_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + wrapped_token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + upper_target: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + swap_fee_percentage: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + salt: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.main_token), + ), + ethabi::Token::Address( + ethabi::Address::from_slice(&self.wrapped_token), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.upper_target.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.swap_fee_percentage.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.protocol_id.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::FixedBytes(self.salt.as_ref().to_vec()), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Create { + const NAME: &'static str = "create"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Create { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Disable {} + impl Disable { + const METHOD_ID: [u8; 4] = [47u8, 39u8, 112u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for Disable { + const NAME: &'static str = "disable"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetActionId { + pub selector: [u8; 4usize], + } + impl GetActionId { + const METHOD_ID: [u8; 4] = [133u8, 28u8, 27u8, 179u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(4usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + selector: { + let mut result = [0u8; 4]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::FixedBytes(self.selector.as_ref().to_vec())], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[u8; 32usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut result = [0u8; 32]; + let v = values + .pop() + .expect("one output data should have existed") + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[u8; 32usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetActionId { + const NAME: &'static str = "getActionId"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[u8; 32usize]> for GetActionId { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAuthorizer {} + impl GetAuthorizer { + const METHOD_ID: [u8; 4] = [170u8, 171u8, 173u8, 197u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetAuthorizer { + const NAME: &'static str = "getAuthorizer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetAuthorizer { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCode {} + impl GetCreationCode { + const METHOD_ID: [u8; 4] = [0u8, 193u8, 148u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bytes], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bytes() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCode { + const NAME: &'static str = "getCreationCode"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetCreationCode { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCreationCodeContracts {} + impl GetCreationCodeContracts { + const METHOD_ID: [u8; 4] = [23u8, 68u8, 129u8, 250u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<(Vec, Vec), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<(Vec, Vec)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCreationCodeContracts { + const NAME: &'static str = "getCreationCodeContracts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<(Vec, Vec)> + for GetCreationCodeContracts { + fn output(data: &[u8]) -> Result<(Vec, Vec), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetLastCreatedPool {} + impl GetLastCreatedPool { + const METHOD_ID: [u8; 4] = [94u8, 211u8, 18u8, 130u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetLastCreatedPool { + const NAME: &'static str = "getLastCreatedPool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetLastCreatedPool { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseConfiguration {} + impl GetPauseConfiguration { + const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPauseConfiguration { + const NAME: &'static str = "getPauseConfiguration"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetPauseConfiguration { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolVersion {} + impl GetPoolVersion { + const METHOD_ID: [u8; 4] = [63u8, 129u8, 155u8, 111u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetPoolVersion { + const NAME: &'static str = "getPoolVersion"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for GetPoolVersion { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetProtocolFeePercentagesProvider {} + impl GetProtocolFeePercentagesProvider { + const METHOD_ID: [u8; 4] = [115u8, 146u8, 56u8, 214u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetProtocolFeePercentagesProvider { + const NAME: &'static str = "getProtocolFeePercentagesProvider"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> + for GetProtocolFeePercentagesProvider { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVault {} + impl GetVault { + const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetVault { + const NAME: &'static str = "getVault"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetVault { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsDisabled {} + impl IsDisabled { + const METHOD_ID: [u8; 4] = [108u8, 87u8, 245u8, 169u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsDisabled { + const NAME: &'static str = "isDisabled"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsDisabled { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IsPoolFromFactory { + pub pool: Vec, + } + impl IsPoolFromFactory { + const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Bool], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for IsPoolFromFactory { + const NAME: &'static str = "isPoolFromFactory"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for IsPoolFromFactory { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Version {} + impl Version { + const METHOD_ID: [u8; 4] = [84u8, 253u8, 77u8, 80u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::String], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Version { + const NAME: &'static str = "version"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Version { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct FactoryDisabled {} + impl FactoryDisabled { + const TOPIC_ID: [u8; 32] = [ + 67u8, + 42u8, + 203u8, + 253u8, + 102u8, + 45u8, + 187u8, + 93u8, + 139u8, + 55u8, + 131u8, + 132u8, + 166u8, + 113u8, + 89u8, + 180u8, + 124u8, + 169u8, + 208u8, + 241u8, + 183u8, + 159u8, + 151u8, + 207u8, + 100u8, + 207u8, + 133u8, + 133u8, + 250u8, + 54u8, + 45u8, + 80u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self {}) + } + } + impl substreams_ethereum::Event for FactoryDisabled { + const NAME: &'static str = "FactoryDisabled"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCreated { + pub pool: Vec, + } + impl PoolCreated { + const TOPIC_ID: [u8; 32] = [ + 131u8, + 164u8, + 143u8, + 188u8, + 252u8, + 153u8, + 19u8, + 53u8, + 49u8, + 78u8, + 116u8, + 208u8, + 73u8, + 106u8, + 171u8, + 106u8, + 25u8, + 135u8, + 233u8, + 146u8, + 221u8, + 200u8, + 93u8, + 221u8, + 188u8, + 196u8, + 214u8, + 221u8, + 110u8, + 242u8, + 233u8, + 252u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for PoolCreated { + const NAME: &'static str = "PoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct YearnLinearPoolCreated { + pub pool: Vec, + pub protocol_id: substreams::scalar::BigInt, + } + impl YearnLinearPoolCreated { + const TOPIC_ID: [u8; 32] = [ + 218u8, + 47u8, + 85u8, + 125u8, + 110u8, + 128u8, + 210u8, + 220u8, + 243u8, + 137u8, + 79u8, + 43u8, + 183u8, + 79u8, + 233u8, + 132u8, + 14u8, + 77u8, + 85u8, + 142u8, + 53u8, + 15u8, + 106u8, + 173u8, + 99u8, + 175u8, + 14u8, + 11u8, + 18u8, + 241u8, + 165u8, + 134u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 0usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Ok(Self { + pool: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'pool' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + protocol_id: { + let mut v = [0 as u8; 32]; + ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'protocol_id' from topic of type 'uint256': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for YearnLinearPoolCreated { + const NAME: &'static str = "YearnLinearPoolCreated"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-balancer/src/lib.rs b/substreams/ethereum-balancer/src/lib.rs new file mode 100644 index 0000000..27bd15a --- /dev/null +++ b/substreams/ethereum-balancer/src/lib.rs @@ -0,0 +1,3 @@ +mod abi; +mod modules; +mod pool_factories; diff --git a/substreams/ethereum-balancer/src/modules.rs b/substreams/ethereum-balancer/src/modules.rs new file mode 100644 index 0000000..af6db11 --- /dev/null +++ b/substreams/ethereum-balancer/src/modules.rs @@ -0,0 +1,216 @@ +use crate::{abi, pool_factories}; +use anyhow::Result; +use itertools::Itertools; +use std::collections::HashMap; +use substreams::{ + hex, + pb::substreams::StoreDeltas, + store::{StoreAdd, StoreAddBigInt, StoreAddInt64, StoreGet, StoreGetInt64, StoreNew}, +}; +use substreams_ethereum::{pb::eth, Event}; +use tycho_substreams::{ + balances::aggregate_balances_changes, contract::extract_contract_changes, prelude::*, +}; + +const VAULT_ADDRESS: &[u8] = &hex!("BA12222222228d8Ba445958a75a0704d566BF2C8"); + +#[substreams::handlers::map] +pub fn map_components(block: eth::v2::Block) -> Result { + // Gather contract changes by indexing `PoolCreated` events and analysing the `Create` call + // We store these as a hashmap by tx hash since we need to agg by tx hash later + Ok(BlockTransactionProtocolComponents { + tx_components: block + .transactions() + .filter_map(|tx| { + let components = tx + .logs_with_calls() + .filter(|(_, call)| !call.call.state_reverted) + .filter_map(|(log, call)| { + pool_factories::address_map( + call.call.address.as_slice(), + log, + call.call, + &(tx.into()), + ) + }) + .collect::>(); + + if !components.is_empty() { + Some(TransactionProtocolComponents { tx: Some(tx.into()), components }) + } else { + None + } + }) + .collect::>(), + }) +} + +/// Simply stores the `ProtocolComponent`s with the pool id as the key +#[substreams::handlers::store] +pub fn store_components(map: BlockTransactionProtocolComponents, store: StoreAddInt64) { + store.add_many( + 0, + &map.tx_components + .iter() + .flat_map(|tx_components| &tx_components.components) + .map(|component| format!("pool:{0}", component.id)) + .collect::>(), + 1, + ); +} + +/// Since the `PoolBalanceChanged` and `Swap` events administer only deltas, we need to leverage a +/// map and a store to be able to tally up final balances for tokens in a pool. +#[substreams::handlers::map] +pub fn map_relative_balances( + block: eth::v2::Block, + store: StoreGetInt64, +) -> Result { + let balance_deltas = block + .logs() + .filter(|log| log.address() == VAULT_ADDRESS) + .flat_map(|vault_log| { + let mut deltas = Vec::new(); + + if let Some(ev) = + abi::vault::events::PoolBalanceChanged::match_and_decode(vault_log.log) + { + let component_id = + format!("0x{}", String::from_utf8(ev.pool_id[..20].to_vec()).unwrap()) + .as_bytes() + .to_vec(); + + if store + .get_last(format!("pool:{}", hex::encode(&component_id))) + .is_some() + { + for (token, delta) in ev.tokens.iter().zip(ev.deltas.iter()) { + deltas.push(BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: token.to_vec(), + delta: delta.to_signed_bytes_be(), + component_id: component_id.clone(), + }); + } + } + } else if let Some(ev) = abi::vault::events::Swap::match_and_decode(vault_log.log) { + let component_id = + format!("0x{}", String::from_utf8(ev.pool_id[..20].to_vec()).unwrap()) + .as_bytes() + .to_vec(); + + if store + .get_last(format!("pool:{}", hex::encode(&component_id))) + .is_some() + { + deltas.extend_from_slice(&[ + BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: ev.token_in.to_vec(), + delta: ev.amount_in.to_signed_bytes_be(), + component_id: component_id.clone(), + }, + BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: ev.token_out.to_vec(), + delta: ev.amount_out.neg().to_signed_bytes_be(), + component_id, + }, + ]); + } + } + + deltas + }) + .collect::>(); + + Ok(BlockBalanceDeltas { balance_deltas }) +} + +/// It's significant to include both the `pool_id` and the `token_id` for each balance delta as the +/// store key to ensure that there's a unique balance being tallied for each. +#[substreams::handlers::store] +pub fn store_balances(deltas: BlockBalanceDeltas, store: StoreAddBigInt) { + tycho_substreams::balances::store_balance_changes(deltas, store); +} + +/// This is the main map that handles most of the indexing of this substream. +/// Every contract change is grouped by transaction index via the `transaction_contract_changes` +/// map. Each block of code will extend the `TransactionContractChanges` struct with the +/// cooresponding changes (balance, component, contract), inserting a new one if it doesn't exist. +/// At the very end, the map can easily be sorted by index to ensure the final +/// `BlockContractChanges` is ordered by transactions properly. +#[substreams::handlers::map] +pub fn map_protocol_changes( + block: eth::v2::Block, + grouped_components: BlockTransactionProtocolComponents, + deltas: BlockBalanceDeltas, + components_store: StoreGetInt64, + balance_store: StoreDeltas, // Note, this map module is using the `deltas` mode for the store. +) -> Result { + // We merge contract changes by transaction (identified by transaction index) making it easy to + // sort them at the very end. + let mut transaction_contract_changes: HashMap<_, TransactionContractChanges> = HashMap::new(); + + // `ProtocolComponents` are gathered from `map_pools_created` which just need a bit of work to + // convert into `TransactionContractChanges` + grouped_components + .tx_components + .iter() + .for_each(|tx_component| { + let tx = tx_component.tx.as_ref().unwrap(); + transaction_contract_changes + .entry(tx.index) + .or_insert_with(|| TransactionContractChanges::new(tx)) + .component_changes + .extend_from_slice(&tx_component.components); + }); + + // Balance changes are gathered by the `StoreDelta` based on `PoolBalanceChanged` creating + // `BlockBalanceDeltas`. We essentially just process the changes that occurred to the `store` + // this block. Then, these balance changes are merged onto the existing map of tx contract + // changes, inserting a new one if it doesn't exist. + aggregate_balances_changes(balance_store, deltas) + .into_iter() + .for_each(|(_, (tx, balances))| { + transaction_contract_changes + .entry(tx.index) + .or_insert_with(|| TransactionContractChanges::new(&tx)) + .balance_changes + .extend(balances.into_values()); + }); + + // Extract and insert any storage changes that happened for any of the components. + extract_contract_changes( + &block, + |addr| { + components_store + .get_last(format!("pool:{0}", hex::encode(addr))) + .is_some() + }, + &mut transaction_contract_changes, + ); + + // Process all `transaction_contract_changes` for final output in the `BlockContractChanges`, + // sorted by transaction index (the key). + Ok(BlockContractChanges { + block: Some((&block).into()), + changes: transaction_contract_changes + .drain() + .sorted_unstable_by_key(|(index, _)| *index) + .filter_map(|(_, change)| { + if change.contract_changes.is_empty() && + change.component_changes.is_empty() && + change.balance_changes.is_empty() + { + None + } else { + Some(change) + } + }) + .collect::>(), + }) +} diff --git a/substreams/ethereum-balancer/src/pool_factories.rs b/substreams/ethereum-balancer/src/pool_factories.rs new file mode 100644 index 0000000..5c2cd59 --- /dev/null +++ b/substreams/ethereum-balancer/src/pool_factories.rs @@ -0,0 +1,236 @@ +use crate::abi; +use substreams::{hex, scalar::BigInt}; +use substreams_ethereum::{ + pb::eth::v2::{Call, Log}, + Event, Function, +}; +use tycho_substreams::prelude::*; + +/// This trait defines some helpers for serializing and deserializing `Vec Vec; + #[allow(dead_code)] + fn deserialize_bytes(bytes: &[u8]) -> Vec; +} + +impl SerializableVecBigInt for Vec { + fn serialize_bytes(&self) -> Vec { + self.iter() + .flat_map(|big_int| big_int.to_signed_bytes_be()) + .collect() + } + fn deserialize_bytes(bytes: &[u8]) -> Vec { + bytes + .chunks_exact(32) + .map(BigInt::from_signed_bytes_be) + .collect::>() + } +} + +/// This is the main function that handles the creation of `ProtocolComponent`s with `Attribute`s +/// based on the specific factory address. There's 3 factory groups that are represented here: +/// - Weighted Pool Factories +/// - Linear Pool Factories +/// - Stable Pool Factories +/// (Balancer does have a bit more (esp. in the deprecated section) that could be implemented as +/// desired.) +/// We use the specific ABIs to decode both the log event and corresponding call to gather +/// `PoolCreated` event information alongside the `Create` call data that provide us details to +/// fulfill both the required details + any extra `Attributes` +/// Ref: https://docs.balancer.fi/reference/contracts/deployment-addresses/mainnet.html +pub fn address_map( + pool_factory_address: &[u8], + log: &Log, + call: &Call, + tx: &Transaction, +) -> Option { + match *pool_factory_address { + hex!("897888115Ada5773E02aA29F775430BFB5F34c51") => { + let create_call = + abi::weighted_pool_factory::functions::Create::match_and_decode(call)?; + let pool_created = + abi::weighted_pool_factory::events::PoolCreated::match_and_decode(log)?; + + Some( + ProtocolComponent::at_contract(&pool_created.pool, tx) + .with_tokens(&create_call.tokens) + .with_attributes(&[ + ("pool_type", "WeightedPoolFactory".as_bytes()), + ( + "normalized_weights", + &create_call + .normalized_weights + .serialize_bytes(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) + } + hex!("DB8d758BCb971e482B2C45f7F8a7740283A1bd3A") => { + let create_call = + abi::composable_stable_pool_factory::functions::Create::match_and_decode(call)?; + let pool_created = + abi::composable_stable_pool_factory::events::PoolCreated::match_and_decode(log)?; + + Some( + ProtocolComponent::at_contract(&pool_created.pool, tx) + .with_tokens(&create_call.tokens) + .with_attributes(&[("pool_type", "ComposableStablePoolFactory".as_bytes())]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) + } + hex!("813EE7a840CE909E7Fea2117A44a90b8063bd4fd") => { + let create_call = + abi::erc_linear_pool_factory::functions::Create::match_and_decode(call)?; + let pool_created = + abi::erc_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; + + Some( + ProtocolComponent::at_contract(&pool_created.pool, tx) + .with_tokens(&[create_call.main_token, create_call.wrapped_token]) + .with_attributes(&[ + ("pool_type", "ERC4626LinearPoolFactory".as_bytes()), + ( + "upper_target", + &create_call + .upper_target + .to_signed_bytes_be(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) + } + hex!("5F43FBa61f63Fa6bFF101a0A0458cEA917f6B347") => { + let create_call = + abi::euler_linear_pool_factory::functions::Create::match_and_decode(call)?; + let pool_created = + abi::euler_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; + + Some( + ProtocolComponent::at_contract(&pool_created.pool, tx) + .with_tokens(&[create_call.main_token, create_call.wrapped_token]) + .with_attributes(&[ + ("pool_type", "EulerLinearPoolFactory".as_bytes()), + ( + "upper_target", + &create_call + .upper_target + .to_signed_bytes_be(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) + } + // ❌ Reading the deployed factory for Gearbox showcases that it's currently disabled + // hex!("39A79EB449Fc05C92c39aA6f0e9BfaC03BE8dE5B") => { + // let create_call = + // abi::gearbox_linear_pool_factory::functions::Create::match_and_decode(call)?; + // let pool_created = + // abi::gearbox_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; + + // Some(tycho::ProtocolComponent { + // id: hex::encode(&pool_created.pool), + // tokens: vec![create_call.main_token, create_call.wrapped_token], + // contracts: vec![pool_addr.into(), pool_created.pool], + // static_att: vec![ + // tycho::Attribute { + // name: "pool_type".into(), + // value: "GearboxLinearPoolFactory".into(), + // change: tycho::ChangeType::Creation.into(), + // }, + // tycho::Attribute { + // name: "upper_target".into(), + // value: create_call.upper_target.to_signed_bytes_be(), + // change: tycho::ChangeType::Creation.into(), + // }, + // ], + // change: tycho::ChangeType::Creation.into(), + // }) + // } + // ❌ The `ManagedPoolFactory` is a bit ✨ unique ✨, so we'll leave it commented out for + // now Take a look at it's `Create` call to see how the params are structured. + // hex!("BF904F9F340745B4f0c4702c7B6Ab1e808eA6b93") => { + // let create_call = + // abi::managed_pool_factory::functions::Create::match_and_decode(call)?; + // let pool_created = + // abi::managed_pool_factory::events::PoolCreated::match_and_decode(log)?; + + // Some(tycho::ProtocolComponent { + // id: hex::encode(&pool_created.pool), + // tokens: create_call.tokens, + // contracts: vec![pool_addr.into(), pool_created.pool], + // static_att: vec![ + // tycho::Attribute { + // name: "pool_type".into(), + // value: "ManagedPoolFactory".into(), + // change: tycho::ChangeType::Creation.into(), + // }, + // ], + // change: tycho::ChangeType::Creation.into(), + // }) + // } + hex!("4E11AEec21baF1660b1a46472963cB3DA7811C89") => { + let create_call = + abi::silo_linear_pool_factory::functions::Create::match_and_decode(call)?; + let pool_created = + abi::silo_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; + + Some( + ProtocolComponent::at_contract(&pool_created.pool, tx) + .with_tokens(&[create_call.main_token, create_call.wrapped_token]) + .with_attributes(&[ + ("pool_type", "SiloLinearPoolFactory".as_bytes()), + ( + "upper_target", + &create_call + .upper_target + .to_signed_bytes_be(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) + } + hex!("5F5222Ffa40F2AEd6380D022184D6ea67C776eE0") => { + let create_call = + abi::yearn_linear_pool_factory::functions::Create::match_and_decode(call)?; + let pool_created = + abi::yearn_linear_pool_factory::events::PoolCreated::match_and_decode(log)?; + + Some( + ProtocolComponent::at_contract(&pool_created.pool, tx) + .with_tokens(&[create_call.main_token, create_call.wrapped_token]) + .with_attributes(&[ + ("pool_type", "YearnLinearPoolFactory".as_bytes()), + ( + "upper_target", + &create_call + .upper_target + .to_signed_bytes_be(), + ), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) + } + // The `WeightedPool2TokenFactory` is a deprecated contract, but we've included + // it to be able to track one of the highest TVL pools: 80BAL-20WETH. + hex!("A5bf2ddF098bb0Ef6d120C98217dD6B141c74EE0") => { + let create_call = + abi::weighted_pool_tokens_factory::functions::Create::match_and_decode(call)?; + let pool_created = + abi::weighted_pool_tokens_factory::events::PoolCreated::match_and_decode(log)?; + + Some( + ProtocolComponent::at_contract(&pool_created.pool, tx) + .with_tokens(&create_call.tokens) + .with_attributes(&[ + ("pool_type", "WeightedPool2TokensFactory".as_bytes()), + ("weights", &create_call.weights.serialize_bytes()), + ]) + .as_swap_type("balancer_pool", ImplementationType::Vm), + ) + } + _ => None, + } +} diff --git a/substreams/ethereum-balancer/substreams.yaml b/substreams/ethereum-balancer/substreams.yaml new file mode 100644 index 0000000..9597334 --- /dev/null +++ b/substreams/ethereum-balancer/substreams.yaml @@ -0,0 +1,56 @@ +specVersion: v0.1.0 +package: + name: "ethereum_balancer" + version: v0.1.0 + +binaries: + default: + type: wasm/rust-v1 + file: ../target/wasm32-unknown-unknown/release/ethereum_balancer.wasm + +modules: + - name: map_components + kind: map + initialBlock: 12369300 + inputs: + - source: sf.ethereum.type.v2.Block + output: + type: proto:tycho.evm.v1.GroupedTransactionProtocolComponents + + - name: store_components + kind: store + initialBlock: 12369300 + updatePolicy: add + valueType: int64 + inputs: + - map: map_components + + - name: map_relative_balances + kind: map + initialBlock: 12369300 # An arbitrary block that should change based on your requirements + inputs: + - source: sf.ethereum.type.v2.Block + - store: store_components + output: + type: proto:tycho.evm.v1.BalanceDeltas + + - name: store_balances + kind: store + initialBlock: 12369300 + updatePolicy: add + valueType: bigint + inputs: + - map: map_relative_balances + + - name: map_changes + kind: map + initialBlock: 12369300 + inputs: + - source: sf.ethereum.type.v2.Block + - map: map_components + - map: map_relative_balances + - store: store_components + - store: store_balances + mode: deltas # This is the key property that simplifies `BalanceChange` handling + output: + type: proto:tycho.evm.v1.BlockContractChanges diff --git a/substreams/ethereum-template/Cargo.toml b/substreams/ethereum-template/Cargo.toml index 82ae8f3..fa4ecad 100644 --- a/substreams/ethereum-template/Cargo.toml +++ b/substreams/ethereum-template/Cargo.toml @@ -1,13 +1,14 @@ [package] -name = "substreams-ethereum-template" +name = "ethereum-template" version = "0.1.0" edition = "2021" [lib] -name = "substreams_ethereum_template" +name = "ethereum_template" crate-type = ["cdylib"] [dependencies] -substreams = "0.5" -substreams-ethereum = "0.9" -prost = "0.11" +substreams.workspace = true +substreams-ethereum.workspace = true +prost.workspace = true +tycho-substreams.workspace = true \ No newline at end of file diff --git a/substreams/ethereum-template/src/lib.rs b/substreams/ethereum-template/src/lib.rs index 6e10475..94324fd 100644 --- a/substreams/ethereum-template/src/lib.rs +++ b/substreams/ethereum-template/src/lib.rs @@ -1,13 +1,9 @@ - use substreams_ethereum::pb::eth; - -use pb::tycho::evm::v1::{self as tycho}; - -mod pb; +mod modules; #[substreams::handlers::map] fn map_changes( block: eth::v2::Block, ) -> Result { todo!("Not implemented") -} \ No newline at end of file +} diff --git a/substreams/ethereum-template/src/modules.rs b/substreams/ethereum-template/src/modules.rs new file mode 100644 index 0000000..136d351 --- /dev/null +++ b/substreams/ethereum-template/src/modules.rs @@ -0,0 +1,12 @@ +use std::collections::HashMap; +use substreams_ethereum::pb::eth; +use tycho_substreams::prelude::*; + +#[substreams::handlers::map] +fn map_protocol_changes( + block: eth::v2::Block, +) -> Result { + let mut transaction_contract_changes = Vec::::new(); + // TODO: protocol specific logic goes here + Ok(BlockContractChanges { block: Some((&block).into()), changes: transaction_contract_changes }) +} diff --git a/substreams/ethereum-template/src/pb/tycho.evm.v1.rs b/substreams/ethereum-template/src/pb/tycho.evm.v1.rs deleted file mode 100644 index b59b5f7..0000000 --- a/substreams/ethereum-template/src/pb/tycho.evm.v1.rs +++ /dev/null @@ -1,183 +0,0 @@ -// @generated -// This file contains the proto definitions for Substreams common to all integrations. - -/// A struct describing a block. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Block { - /// The blocks hash. - #[prost(bytes="vec", tag="1")] - pub hash: ::prost::alloc::vec::Vec, - /// The parent blocks hash. - #[prost(bytes="vec", tag="2")] - pub parent_hash: ::prost::alloc::vec::Vec, - /// The block number. - #[prost(uint64, tag="3")] - pub number: u64, - /// The block timestamp. - #[prost(uint64, tag="4")] - pub ts: u64, -} -/// A struct describing a transaction. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Transaction { - /// The transaction hash. - #[prost(bytes="vec", tag="1")] - pub hash: ::prost::alloc::vec::Vec, - /// The sender of the transaction. - #[prost(bytes="vec", tag="2")] - pub from: ::prost::alloc::vec::Vec, - /// The receiver of the transaction. - #[prost(bytes="vec", tag="3")] - pub to: ::prost::alloc::vec::Vec, - /// The transactions index within the block. - #[prost(uint64, tag="4")] - pub index: u64, -} -/// A custom struct representing an arbitrary attribute of a protocol component. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Attribute { - /// The name of the attribute. - #[prost(string, tag="1")] - pub name: ::prost::alloc::string::String, - /// The value of the attribute. - #[prost(bytes="vec", tag="2")] - pub value: ::prost::alloc::vec::Vec, - /// The type of change the attribute underwent. - #[prost(enumeration="ChangeType", tag="3")] - pub change: i32, -} -/// A struct describing a part of the protocol. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ProtocolComponent { - /// A unique identifier for the component within the protocol. - /// Can be a stringified address or a string describing the trading pair. - #[prost(string, tag="1")] - pub id: ::prost::alloc::string::String, - /// Addresses of the ERC20 tokens used by the component. - #[prost(bytes="vec", repeated, tag="2")] - pub tokens: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, - /// Addresses of the contracts used by the component. - #[prost(bytes="vec", repeated, tag="3")] - pub contracts: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, - /// Attributes of the component. - /// The inner ChangeType of the attribute has to match the ChangeType of the ProtocolComponent. - #[prost(message, repeated, tag="4")] - pub static_att: ::prost::alloc::vec::Vec, - /// Type of change the component underwent. - #[prost(enumeration="ChangeType", tag="5")] - pub change: i32, -} -/// A struct for following the changes of Total Value Locked (TVL) of a protocol component. -/// Note that if the ProtocolComponent contains multiple contracts, the TVL is tracked for the component as a whole. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BalanceChange { - /// The address of the ERC20 token whose balance changed. - #[prost(bytes="vec", tag="1")] - pub token: ::prost::alloc::vec::Vec, - /// The new balance of the token. - #[prost(bytes="vec", tag="2")] - pub balance: ::prost::alloc::vec::Vec, - /// The id of the component whose TVL is tracked. - #[prost(bytes="vec", tag="3")] - pub component_id: ::prost::alloc::vec::Vec, -} -/// Enum to specify the type of a change. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum ChangeType { - Unspecified = 0, - Update = 1, - Creation = 2, - Deletion = 3, -} -impl ChangeType { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - ChangeType::Unspecified => "CHANGE_TYPE_UNSPECIFIED", - ChangeType::Update => "CHANGE_TYPE_UPDATE", - ChangeType::Creation => "CHANGE_TYPE_CREATION", - ChangeType::Deletion => "CHANGE_TYPE_DELETION", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "CHANGE_TYPE_UNSPECIFIED" => Some(Self::Unspecified), - "CHANGE_TYPE_UPDATE" => Some(Self::Update), - "CHANGE_TYPE_CREATION" => Some(Self::Creation), - "CHANGE_TYPE_DELETION" => Some(Self::Deletion), - _ => None, - } - } -} -// This file contains proto definitions specific to the VM integration. - -/// A key value entry into contract storage. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ContractSlot { - /// A contract's storage slot. - #[prost(bytes="vec", tag="2")] - pub slot: ::prost::alloc::vec::Vec, - /// The new value for this storage slot. - #[prost(bytes="vec", tag="3")] - pub value: ::prost::alloc::vec::Vec, -} -/// Changes made to a single contract's state. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ContractChange { - /// The contract's address - #[prost(bytes="vec", tag="1")] - pub address: ::prost::alloc::vec::Vec, - /// The new balance of the contract, empty bytes indicates no change. - #[prost(bytes="vec", tag="2")] - pub balance: ::prost::alloc::vec::Vec, - /// The new code of the contract, empty bytes indicates no change. - #[prost(bytes="vec", tag="3")] - pub code: ::prost::alloc::vec::Vec, - /// The changes to this contract's slots, empty sequence indicates no change. - #[prost(message, repeated, tag="4")] - pub slots: ::prost::alloc::vec::Vec, - /// Whether this is an update, a creation or a deletion. - #[prost(enumeration="ChangeType", tag="5")] - pub change: i32, -} -/// A set of changes aggregated by transaction. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TransactionContractChanges { - /// The transaction instance that results in the changes. - #[prost(message, optional, tag="1")] - pub tx: ::core::option::Option, - /// Contains the changes induced by the above transaction, aggregated on a per-contract basis. - #[prost(message, repeated, tag="2")] - pub contract_changes: ::prost::alloc::vec::Vec, - /// An array of newly added components. - #[prost(message, repeated, tag="3")] - pub component_changes: ::prost::alloc::vec::Vec, - /// An array of balance changes to components. - #[prost(message, repeated, tag="4")] - pub balance_changes: ::prost::alloc::vec::Vec, -} -/// A set of transaction changes within a single block. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BlockContractChanges { - /// The block for which these changes are collectively computed. - #[prost(message, optional, tag="1")] - pub block: ::core::option::Option, - /// The set of transaction changes observed in the specified block. - #[prost(message, repeated, tag="2")] - pub changes: ::prost::alloc::vec::Vec, -} -// @@protoc_insertion_point(module) diff --git a/substreams/ethereum-template/substreams.yaml b/substreams/ethereum-template/substreams.yaml index b3fa3fb..de5dcbf 100644 --- a/substreams/ethereum-template/substreams.yaml +++ b/substreams/ethereum-template/substreams.yaml @@ -1,22 +1,15 @@ specVersion: v0.1.0 package: - name: "substreams_ethereum_template" + name: "ethereum_template" version: v0.1.0 -protobuf: - files: - - vm.proto - - common.proto - importPaths: - - ../../proto/tycho/evm/v1/ - binaries: default: type: wasm/rust-v1 - file: ../../target/wasm32-unknown-unknown/substreams/substreams_ethereum_template.wasm + file: ../target/wasm32-unknown-unknown/release/ethereum_template.wasm modules: - - name: map_changes + - name: map_protocol_changes kind: map inputs: - source: sf.ethereum.type.v2.Block diff --git a/substreams/release.sh b/substreams/release.sh new file mode 100755 index 0000000..e011e95 --- /dev/null +++ b/substreams/release.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Allows releasing multiple substream packages within the same repo. +# To trigger a release simply create a tag with [package-name]-[semver]. +# The script will look for these tags, then infer which package needs to be built and +# released. + +# Try to get the tag name associated with the current HEAD commit +current_tag=$(git describe --tags --exact-match HEAD 2>/dev/null) + +if [ -n "$current_tag" ]; then + # If the HEAD is at a tag, extract the prefix and version + if [[ $current_tag =~ ^([a-zA-Z-]*-)?([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + # Prefix without the trailing hyphen (if any) + package="${BASH_REMATCH[1]%?}" + # Semantic version + version="${BASH_REMATCH[2]}" + + cargo_version=$(cargo pkgid -p ethereum-balancer | cut -d# -f2 | cut -d: -f2) + if [[ "$cargo_version" != "$version" ]]; then + echo "Error: Cargo version: ${cargo_version} does not match tag version: ${version}!" + exit 1 + fi + # Check if the Git repository is dirty + if [ -n "$(git status --porcelain)" ]; then + echo "Error: The repository is dirty. Please commit or stash your changes." + exit 1 + fi + else + echo "Error: Current tag ($current_tag) does not match the expected format." + exit 1 + fi +else + # If the HEAD is not at a tag, construct the tag name with the pre-release postfix + if [ -z "$1" ]; then + echo "Error: package argument is required to create a pre release!" + exit 1 + fi + package=$1 + + version_prefix=$(git describe --tags --match "$package-*" --abbrev=0 2>/dev/null) + if [ -z "$version_prefix" ]; then + # If no tags are found in the history, default to version 0.0.1 + version_prefix="0.0.1" + fi + + # Get the short commit hash of the current HEAD + commit_hash=$(git rev-parse --short HEAD) + version="${version_prefix}-pre.${commit_hash}" +fi + +REPOSITORY=${REPOSITORY:-"s3://repo.propellerheads/substreams"} +repository_path="$REPOSITORY/$package/$package-$version.spkg" + +cargo build --target wasm32-unknown-unknown --release -p "$package" +mkdir -p ./target/spkg/ +substreams pack $package/substreams.yaml -o ./target/spkg/$package-$version.spkg +aws s3 cp ./target/spkg/$package-$version.spkg $repository_path + +echo "Released substreams package: '$repository_path'" \ No newline at end of file diff --git a/substreams/rustfmt.toml b/substreams/rustfmt.toml new file mode 100644 index 0000000..1f27a7b --- /dev/null +++ b/substreams/rustfmt.toml @@ -0,0 +1,14 @@ +reorder_imports = true +imports_granularity = "Crate" +use_small_heuristics = "Max" +comment_width = 100 +wrap_comments = true +binop_separator = "Back" +trailing_comma = "Vertical" +trailing_semicolon = false +use_field_init_shorthand = true +chain_width = 40 +ignore = [ + "crates/tycho-substreams/src/pb", + "ethereum-balancer/src/abi", +] \ No newline at end of file